I am using g++ 4.3.0 to compile this example :
#include <vector>
int main()
{
std::vector< int > a;
int b;
}
If I compile the example with maximum warning level, I get a warning that the variable b is not used :
[vladimir#juniper data_create]$ g++ m.cpp -Wall -Wextra -ansi -pedantic
m.cpp: In function ‘int main()’:
m.cpp:7: warning: unused variable ‘b’
[vladimir#juniper data_create]$
The question is : why the variable a is not reported as not used?
What parameters do I have to pass to get the warning for the variable a?
In theory, the default constructor for std::vector<int> could have arbitrary side effects, so the compiler cannot figure out whether removing the definition of a would change the semantics of the program. You only get those warning for built-in types.
A better example is a lock:
{
lock a;
// ...
// do critical stuff
// a is never used here
// ...
// lock is automatically released by a's destructor (RAII)
}
Even though a is never used after its definition, removing the first line would be wrong.
a is not a built-in type. You are actually calling the constructor of std::vector<int> and assigning the result to a. The compiler sees this as usage because the constructor could have side effects.
a is actually used after it is declared as its destructor gets called at the end of its scope.
Related
Clang warns (when using -Weverything or Wglobal-constructors) about constructors for static objects.
warning: declaration requires a global constructor
[-Wglobal-constructors]
A A::my_A; // triggers said warning
^~~~
Why is this relevant and how should one deal with this warning?
Simple example code:
class A {
// ...
static A my_A;
A();
};
A A::my_A; // triggers said warning
Here is a simpler case that triggers the same warning:
class A {
public:
// ...
A();
};
A my_A; // triggers said warning
test.cpp:7:3: warning: declaration requires a global constructor [-Wglobal-constructors]
A my_A; // triggers said warning
^~~~
1 warning generated.
This is perfectly legal and safe C++.
However for every non-trivial global constructor you have, launch time of your application suffers. The warning is simply a way of letting you know about this potential performance problem.
You can disable the warning with -Wno-global-constructors. Or you can change to a lazy initialization scheme like this:
A&
my_A()
{
static A a;
return a;
}
which avoids the issue entirely (and suppresses the warning).
Solution from #Howard Hinnant avoid global constructor, but it do exit time destructor still.
It can be found with option -Wexit-time-destructors
So Ideal solution can be based on CR_DEFINE_STATIC_LOCAL from http://src.chromium.org/svn/trunk/src/base/basictypes.h
A& my_A()
{
static A &a = *new A;
return a;
}
If you can declare the constructor constexpr, that will suppress the warning (because this guarantees constant initialization). See https://godbolt.org/z/s3hY83jdr
Clang warns (when using -Weverything or Wglobal-constructors) about constructors for static objects.
warning: declaration requires a global constructor
[-Wglobal-constructors]
A A::my_A; // triggers said warning
^~~~
Why is this relevant and how should one deal with this warning?
Simple example code:
class A {
// ...
static A my_A;
A();
};
A A::my_A; // triggers said warning
Here is a simpler case that triggers the same warning:
class A {
public:
// ...
A();
};
A my_A; // triggers said warning
test.cpp:7:3: warning: declaration requires a global constructor [-Wglobal-constructors]
A my_A; // triggers said warning
^~~~
1 warning generated.
This is perfectly legal and safe C++.
However for every non-trivial global constructor you have, launch time of your application suffers. The warning is simply a way of letting you know about this potential performance problem.
You can disable the warning with -Wno-global-constructors. Or you can change to a lazy initialization scheme like this:
A&
my_A()
{
static A a;
return a;
}
which avoids the issue entirely (and suppresses the warning).
Solution from #Howard Hinnant avoid global constructor, but it do exit time destructor still.
It can be found with option -Wexit-time-destructors
So Ideal solution can be based on CR_DEFINE_STATIC_LOCAL from http://src.chromium.org/svn/trunk/src/base/basictypes.h
A& my_A()
{
static A &a = *new A;
return a;
}
If you can declare the constructor constexpr, that will suppress the warning (because this guarantees constant initialization). See https://godbolt.org/z/s3hY83jdr
Is it possible (with any modification of class A) to have the following work? i.e., make the most vexing parse an error?
class A {
};
int main() {
A a(); // can this be forced to be an error??
A b; // this should work
}
No modification of the class A will have any effect on how a declaration A a(); is parsed. The parser determines that this is a function declaration before it even bothers to look at the definition of A. In fact the definition of A doesn't even need to be visible to parse this statement; A forward declaration is sufficient.
However compilers generally have a warning for this and you can probably turn that into an error. For example with clang you can use the flag -Werror=vexing-parse.
struct A;
A a(); // no error
int main() {
A a(); // error
}
clang++ -std=c++11 -Weverything -Werror=vexing-parse main.cpp
main.cpp:6:8: error: empty parentheses interpreted as a function declaration [-Werror,-Wvexing-parse]
A a();
^~
main.cpp:6:8: note: replace parentheses with an initializer to declare a variable
A a();
^~
{}
1 error generated.
Although technically speaking A a(); isn't the syntax known as the most vexing parse. That would be:
A a(B());
There is no way in the current language specification which could make this code an error. Normally, you just get a funny error message when you try to use the "object". However, some compilers do warn about the situation (e.g. clang):
clang++ -W -Wall -Werror -c -o vexing.o vexing.cpp
vexing.cpp:5:8: error: empty parentheses interpreted as a function declaration [-Werror,-Wvexing-parse]
A a(); // can this be forced to be an error??
^~
Clang warns (when using -Weverything or Wglobal-constructors) about constructors for static objects.
warning: declaration requires a global constructor
[-Wglobal-constructors]
A A::my_A; // triggers said warning
^~~~
Why is this relevant and how should one deal with this warning?
Simple example code:
class A {
// ...
static A my_A;
A();
};
A A::my_A; // triggers said warning
Here is a simpler case that triggers the same warning:
class A {
public:
// ...
A();
};
A my_A; // triggers said warning
test.cpp:7:3: warning: declaration requires a global constructor [-Wglobal-constructors]
A my_A; // triggers said warning
^~~~
1 warning generated.
This is perfectly legal and safe C++.
However for every non-trivial global constructor you have, launch time of your application suffers. The warning is simply a way of letting you know about this potential performance problem.
You can disable the warning with -Wno-global-constructors. Or you can change to a lazy initialization scheme like this:
A&
my_A()
{
static A a;
return a;
}
which avoids the issue entirely (and suppresses the warning).
Solution from #Howard Hinnant avoid global constructor, but it do exit time destructor still.
It can be found with option -Wexit-time-destructors
So Ideal solution can be based on CR_DEFINE_STATIC_LOCAL from http://src.chromium.org/svn/trunk/src/base/basictypes.h
A& my_A()
{
static A &a = *new A;
return a;
}
If you can declare the constructor constexpr, that will suppress the warning (because this guarantees constant initialization). See https://godbolt.org/z/s3hY83jdr
Note that derived uses C++11 uniform initialization syntax to call the base class constructor.
class base
{
protected:
base()
{}
};
class derived : public base
{
public:
derived()
: base{} // <-- Note the c++11 curly brace syntax
// using uniform initialization. Change the
// braces to () and it works.
{}
};
int main()
{
derived d1;
return 0;
}
g++4.6 compiles this, however g++4.7 does not:
$ g++-4.7 -std=c++11 -Wall -Wextra -pedantic curly.cpp -o curly
curly.cpp: In constructor ‘derived::derived()’:
curly.cpp:4:13: error: ‘base::base()’ is protected
curly.cpp:19:24: error: within this context
What's going on?
Update 1: It also compiles without warnings with clang++-3.1
Update 2: Looks like a compiler bug for sure. It's apparently fixed in GCC 4.7.3.
Paolo Carlini, a GCC/libstdc++ contributor, confirmed it is a bug/regression.
It is probably because in version 4.7 C11 explicit override control was added.
compiling this with icpc ( intel compiler tested with version 11.1 -> 12.1) gives:
-bash-3.2$ icpc -std=c++0x test.c
test.c(15): error: expected a declaration
{}
^
test.c(12): error: expected a "("
: base{} // <-- Note the c++11 curly brace syntax
^
compilation aborted for test.c (code 2)
edit: but then again, c++11 is not fully implemented yet in icpc either
http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/
same as with g++
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html
which clearly states it's still experimental, so a bug is very likely.
I found this:
"The draft says that an initializer list initializing a reference is done not by direct binding, but by first constructing a temporary out of the element in the initializer list, and then binding the target reference to that temporary"
So it might be choking on the fact that the temporary created by base{} is being done through a protected constructor.