Forum: Compiler & IDEs Vermisse Warnung in C++ Code


von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Letztens hatte ich folgendes Problem, welches  mir die Fehlersuche 
erschwerte.

Ich hatte ein Semikolon zuviel im c++-Source. Deshalb wurde ein 
Statement ohne Effekt erzeugt, welches aber vom g++ trotz entsprechner 
Compiler-Optionen unbemerkt blieb.

Hier ein runtergebrochenes Beispiel:
1
#include <string>
2
#include <iostream>
3
4
int main (void)
5
{
6
    std::string bar = "bar";
7
8
    bar = "foo bar baz:";       // <-- Dieses Semikolon ist zuviel
9
          "foo" + bar + "baz";
10
11
    std::cout << bar << std::endl;
12
}
Eigentlich war hier eine String-Concatenation über mehrere Codezeilen 
gewünscht, leider hat das überflüssige Semikolon das verhindert.

Trotz Übersetzung mit
1
$ g++ -O2 -Wall -Werror -Wextra -Wunused -Wpedantic a.cc && ./a.out
2
foo bar baz:
wird keine Warnung ausgegeben. Wenn ich die Zeile
1
    "foo" + bar + "baz";
auf
1
    "foo";
kürze, erscheint auch erwartungsgemäß
1
error: statement has no effect [-Werror=unused-value]
Compiler: gcc version 10.2.1 20210110 (Raspbian 10.2.1-6+rpi1)

Frage: Habe ich eine Compileroption übersehen oder hat der Compiler ein 
überflüssiges Statement tatsächlich übersehen?

P.S.

Der Grund, warum ich hier String-Concatenation über mehrere Zeilen 
benutze, wird aus dem Beispiel nicht ersichtlich. Glaubt mir, es hat 
einen Grund. Aber der ist hier nicht Diskussionsthema.

: Bearbeitet durch Moderator
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Frank M. schrieb:
> wird keine Warnung ausgegeben

Naja, die Konkatenation von std::string ruft den "operator +" auf, der 
ja durchaus auch Nebeneffekte hat (Allokation). Die kann der Compiler 
nicht einfach als sinnlos erkennen. Der Compiler kann nicht 
durchblicken, dass das Erzeugen eines neuen, konkatenierten temporären 
std::string und dessen anschließendes Löschen keinen wirklichen Effekt 
auf das Programm hat und dementsprechend warnen; im "operator +", 
Konstruktor, Destruktor von std::string könnte ja irgendwas wichtiges, 
erwünschtes passieren. Vielleicht war ja der Speicher vorher randvoll, 
und das Konkatenieren hätte ein OOM bewirken sollen, das könnte ja 
Absicht sein ;-)

Bei
1
class X {
2
  public:
3
    X foo () { return {}; }
4
};
5
6
int main () {
7
  X {}.foo ();
8
}

wird auch nicht gewarnt, obwohl es nichts tut. Und die 
string-Konkatenation ist noch viel komplexer (Allokation etc.).

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Ab Version 13.x hat der Op+ für std::string das Attribute "nodiscard", 
dann bekommt man auch eine Warnung.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Wilhelm M. schrieb:
> Ab Version 13.x hat der Op+ für std::string das Attribute "nodiscard",
> dann bekommt man auch eine Warnung.

Danke.

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Wilhelm M. schrieb:
> Ab Version 13.x hat der Op+ für std::string das Attribute
> "nodiscard",
> dann bekommt man auch eine Warnung.

Zufaellig hab' ich grad' einen ofenfrischen 13.2er gcc da, das Beispiel 
sieht dann so aus:
1
(lfs chroot) root:~# g++ -O2 -Wall -Werror -Wextra -Wunused -Wpedantic a.cc 
2
a.cc: In function 'int main()':
3
a.cc:13:30: error: ignoring return value of 'std::__cxx11::basic_string<_CharT, _Traits, _Allocator> std::operator+(__cxx11::basic_string<_CharT, _Traits, _Allocator>&&, const _CharT*) [with _CharT = char; _Traits = char_traits<char>; _Alloc = allocator<char>]', declared with attribute 'nodiscard' [-Werror=unused-result]
4
   13 |           "foo" + bar + "baz";
5
      |                              ^
6
In file included from /usr/include/c++/13.2.0/string:54,
7
                 from a.cc:1:
8
/usr/include/c++/13.2.0/bits/basic_string.h:3676:5: note: declared here
9
 3676 |     operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs,
10
      |     ^~~~~~~~
11
cc1plus: all warnings being treated as errors

Gruss
WK

von Wilhelm M. (wimalopaan)


Lesenswert?

Dergute W. schrieb:
> Zufaellig hab' ich grad' einen ofenfrischen 13.2er gcc da,

Nimm doch "godbolt".

von Dergute W. (derguteweka)


Lesenswert?

Moin,

Wilhelm M. schrieb:
> Nimm doch "godbolt".

Wenn ich in meinem stillen Kaemmerlein ein LFS bau', ist ein 
Onlinecompiler nicht direkt das zielfuehrendste, was ich mir vorstellen 
kann :-)

Gruss
WK

von Wilhelm M. (wimalopaan)


Lesenswert?

Dergute W. schrieb:
> Wenn ich in meinem stillen Kaemmerlein ein LFS bau', ist ein
> Onlinecompiler nicht direkt das zielfuehrendste, was ich mir vorstellen
> kann :-)

Du kannst mit Deinem LFS machen, was Du willst.

Wenn Du allerdings verschiedene Compiler und deren Versionen auf 
verschiedenen Plattformen testen möchtest in Bezug auf ein MCVE eines 
Fragenden, so ist doch godbolt o.ä. das Mittel der Wahl.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.