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
Related
struct sa
{
struct sb { int a = 123;};
inline static sb b;
};
The above code generates an error:
main.cpp:25:20: error: default member initializer for ‘sa::sb::a’ required before the end of its enclosing class
inline static sb b;
^
main.cpp:24:21: note: defined here
struct sb { int a = 123;};
^~~~~~
Removing the inline keyword or the default member initializer works. But just from the output, I don't understand why this usage is wrong.
I think this code is correct and should be accepted; gcc and clang are erring on the side of caution in order to avoid the defect of Core Issue 1397.
That issue ruled that a program is ill-formed if a NSDMI (non-static data member initializer) causes the class's defaulted default constructor to be generated.
However your code doesn't do that. The NSDMI is just an integer literal. The example that prompted this issue had code like int a = ( (sa(), 123) );
What I guess might be happening is: The standard also says that , when processing the NSDMI, the class sa should be treated as complete. So perhaps the compilers are deferring the NSDMI processing until after the closing brace of sa is reached; and then flagging the error because inline static sb b; would generate sb::sb().
Possibly the standard is still defective and nobody thought of your example until now.
As a workaround you can explicitly provide the troublesome constructor:
struct sb { int a = 123; sb() {} };
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
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.