@@ -613,6 +613,10 @@ Wformat-truncation=
C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ LTO ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2)
Warn about calls to snprintf and similar functions that truncate output.
+Wglobal-constructors
+C++ ObjC++ Var(warn_global_constructors) Warning
+Warn about objects with static storage duration that require dynamic initialization or have nontrivial destructors.
+
Wif-not-aligned
C ObjC C++ ObjC++ Var(warn_if_not_aligned) Init(1) Warning
Warn when the field in a struct is not aligned.
@@ -8324,10 +8324,10 @@ expand_static_init (tree decl, tree init)
return;
}
+ location_t dloc = DECL_SOURCE_LOCATION (decl);
if (CP_DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl)
&& !DECL_FUNCTION_SCOPE_P (decl))
{
- location_t dloc = DECL_SOURCE_LOCATION (decl);
if (init)
error_at (dloc, "non-local variable %qD declared %<__thread%> "
"needs dynamic initialization", decl);
@@ -8467,10 +8467,24 @@ expand_static_init (tree decl, tree init)
finish_then_clause (if_stmt);
finish_if_stmt (if_stmt);
}
- else if (CP_DECL_THREAD_LOCAL_P (decl))
- tls_aggregates = tree_cons (init, decl, tls_aggregates);
else
- static_aggregates = tree_cons (init, decl, static_aggregates);
+ {
+ if (CP_DECL_THREAD_LOCAL_P (decl))
+ tls_aggregates = tree_cons (init, decl, tls_aggregates);
+ else
+ static_aggregates = tree_cons (init, decl, static_aggregates);
+
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
+ {
+ warning_at (dloc, OPT_Wglobal_constructors,
+ "declaration requires a global destructor");
+ return;
+ }
+
+ if (DECL_NONTRIVIALLY_INITIALIZED_P (decl) && !decl_constant_var_p (decl))
+ warning_at (dloc, OPT_Wglobal_constructors,
+ "declaration requires a global constructor");
+ }
}
@@ -312,6 +312,7 @@ Objective-C and Objective-C++ Dialects}.
-Wformat-security -Wformat-signedness -Wformat-truncation=@var{n} @gol
-Wformat-y2k -Wframe-address @gol
-Wframe-larger-than=@var{byte-size} -Wno-free-nonheap-object @gol
+-Wglobal-constructors @gol
-Wjump-misses-init @gol
-Whsa -Wif-not-aligned @gol
-Wignored-qualifiers -Wignored-attributes -Wincompatible-pointer-types @gol
@@ -6509,6 +6510,40 @@ to @option{-Wframe-larger-than=}@samp{SIZE_MAX} or larger.
Do not warn when attempting to free an object that was not allocated
on the heap.
+@item -Wglobal-constructors @r{(C++ and Objective-C++ only)}
+@opindex Wglobal-constructors
+@opindex Wno-global-constructors
+Warn whenever an object with static storage duration either requires dynamic
+initialization or has a nontrivial destructor. The compiler will issue a
+warning if a declaration's initializer is not a constant expression, as shown
+in the following examples:
+
+@smallexample
+@group
+const char* const tmp = getenv ("TMP");
+// warning: declaration requires a global constructor
+
+static int initialize() { return 42; }
+static int global = initialize ();
+// warning: declaration requires a global constructor
+
+@end group
+@end smallexample
+
+In cases where the compiler can treat the initializer as a constant expression,
+no warning is raised, as in the following example:
+
+@smallexample
+@group
+
+constexpr int initialize() { return 42; }
+static int i = initialize ();
+// no warning: initialize in this case is a constant expression
+
+@end group
+@end smallexample
+
+
@item -Wstack-usage=@var{byte-size}
@opindex Wstack-usage
@opindex Wno-stack-usage
new file mode 100644
@@ -0,0 +1,53 @@
+// { dg-do compile }
+// { dg-options "-Wglobal-constructors" }
+
+struct with_ctor {
+ int x;
+ with_ctor() : x(42) {}
+};
+
+struct with_dtor {
+ ~with_dtor() {}
+};
+
+struct with_both {
+ int x;
+ with_both() : x(42) {}
+ ~with_both() {}
+};
+
+struct with_default_ctor {
+ int x;
+ with_default_ctor() = default;
+};
+
+struct with_constexpr_ctor {
+ int x;
+ constexpr with_constexpr_ctor() : x(42) {}
+ constexpr with_constexpr_ctor(int x) : x(x) {}
+};
+
+with_ctor global_var; /* { dg-warning "declaration requires a global constructor" } */
+with_dtor global_var2; /* { dg-warning "declaration requires a global destructor" } */
+with_both global_var3; /* { dg-warning "declaration requires a global destructor" } */
+with_default_ctor global_var4; /* { dg-bogus "declaration requires a global constructor" } */
+with_constexpr_ctor global_var5; /* { dg-bogus "declaration requires a global constructor" } */
+
+int initialize() {
+ return 42;
+}
+
+int global_var6 = initialize(); /* { dg-warning "declaration requires a global constructor" } */
+with_constexpr_ctor global_var7(initialize()); /* { dg-warning "declaration requires a global constructor" } */
+
+constexpr int initialize_const() {
+ return 42;
+}
+
+int global_var8 = initialize_const(); /* { dg-bogus "declaration requires a global constructor" } */
+constexpr int global_var9 = initialize_const(); /* { dg-bogus "declaration requires a global constructor" } */
+
+
+int main() {
+ static with_ctor global_var; /* { dg-bogus "declaration requires a global constructor" } */
+}
new file mode 100644
@@ -0,0 +1,49 @@
+// { dg-do compile }
+// { dg-require-effective-target c++11 }
+// { dg-options "-Wglobal-constructors" }
+
+struct with_ctor {
+ int x;
+ with_ctor() : x(42) {}
+};
+
+struct with_dtor {
+ ~with_dtor() {}
+};
+
+struct with_both {
+ int x;
+ with_both() : x(42) {}
+ ~with_both() {}
+};
+
+struct with_default_ctor {
+ int x;
+ with_default_ctor() = default;
+};
+
+struct with_constexpr_ctor {
+ int x;
+ constexpr with_constexpr_ctor() : x(42) {}
+ constexpr with_constexpr_ctor(int x) : x(x) {}
+};
+
+thread_local with_ctor global_var; /* { dg-warning "declaration requires a global constructor" } */
+thread_local with_dtor global_var2; /* { dg-warning "declaration requires a global destructor" } */
+thread_local with_both global_var3; /* { dg-warning "declaration requires a global destructor" } */
+thread_local with_default_ctor global_var4; /* { dg-bogus "declaration requires a global constructor" } */
+thread_local with_constexpr_ctor global_var5; /* { dg-bogus "declaration requires a global constructor" } */
+
+int initialize() {
+ return 42;
+}
+
+thread_local int global_var6 = initialize(); /* { dg-warning "declaration requires a global constructor" } */
+thread_local with_constexpr_ctor global_var7(initialize()); /* { dg-warning "declaration requires a global constructor" } */
+
+constexpr int initialize_const() {
+ return 42;
+}
+
+thread_local int global_var8 = initialize_const(); /* { dg-bogus "declaration requires a global constructor" } */
+thread_local constexpr int global_var9 = initialize_const(); /* { dg-bogus "declaration requires a global constructor" } */