Hi rsmith, eli.friedman,
This patch liberalizes -Wglobal-constructors to not emit warning if constructor
is likely to be optimized away. This covers important LinkerInitialized idiom
used e.g. in libsanitizer and Chromium:
enum LinkerInitialized { LINKER_INITIALIZED };
class Mutex {
public:
inline Mutex(base::LinkerInitialized) {}
};
Mutex mu(LINKER_INITIALIZED); // Will be optimized away
No regressions in check-all.
http://reviews.llvm.org/D7122
Files:
lib/Sema/SemaDecl.cpp
test/SemaCXX/warn-global-constructors.cpp
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -9523,18 +9523,34 @@
if (!var->getDeclContext()->isDependentContext() &&
Init && !Init->isValueDependent()) {
- if (IsGlobal && !var->isConstexpr() &&
- !getDiagnostics().isIgnored(diag::warn_global_constructor,
- var->getLocation())) {
+ do {
+ if (!IsGlobal || var->isConstexpr() ||
+ getDiagnostics().isIgnored(diag::warn_global_constructor,
+ var->getLocation()))
+ break;
+
// Warn about globals which don't have a constant initializer. Don't
// warn about globals with a non-trivial destructor because we already
// warned about them.
CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
- if (!(RD && !RD->hasTrivialDestructor()) &&
- !Init->isConstantInitializer(Context, baseType->isReferenceType()))
- Diag(var->getLocation(), diag::warn_global_constructor)
- << Init->getSourceRange();
- }
+ if ((RD && !RD->hasTrivialDestructor()) ||
+ Init->isConstantInitializer(Context, baseType->isReferenceType()))
+ break;
+
+ CXXConstructExpr *CtorInit = dyn_cast_or_null<CXXConstructExpr>(Init);
+ if (CtorInit) {
+ // Do not warn if constructor will likely generate no code.
+ CXXConstructorDecl *CtorDecl = CtorInit->getConstructor();
+ Stmt *CtorBody = CtorDecl->getBody();
+ bool HasEmptyBody = CtorBody && CtorDecl->isDefined() &&
cast<CompoundStmt>(CtorBody)->body_empty();
+ bool HasNoInitializers = !CtorDecl->getNumCtorInitializers();
+ if (HasEmptyBody && HasNoInitializers)
+ break;
+ }
+
+ Diag(var->getLocation(), diag::warn_global_constructor)
+ << Init->getSourceRange();
+ } while(0);
if (var->isConstexpr()) {
SmallVector<PartialDiagnosticAt, 8> Notes;
Index: test/SemaCXX/warn-global-constructors.cpp
===================================================================
--- test/SemaCXX/warn-global-constructors.cpp
+++ test/SemaCXX/warn-global-constructors.cpp
@@ -121,6 +121,18 @@
E e;
}
+namespace LinkerInitialized {
+ enum LinkerInitialized { LINKER_INITIALIZED = 0 };
+
+ struct BlockingMutex {
+ BlockingMutex(LinkerInitialized) {}
+ BlockingMutex() {}
+ char owner_;
+ };
+
+ BlockingMutex mu(LINKER_INITIALIZED); // elided
+}
+
namespace pr20420 {
// No warning is expected. This used to crash.
void *array_storage[1];
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -9523,18 +9523,34 @@
if (!var->getDeclContext()->isDependentContext() &&
Init && !Init->isValueDependent()) {
- if (IsGlobal && !var->isConstexpr() &&
- !getDiagnostics().isIgnored(diag::warn_global_constructor,
- var->getLocation())) {
+ do {
+ if (!IsGlobal || var->isConstexpr() ||
+ getDiagnostics().isIgnored(diag::warn_global_constructor,
+ var->getLocation()))
+ break;
+
// Warn about globals which don't have a constant initializer. Don't
// warn about globals with a non-trivial destructor because we already
// warned about them.
CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
- if (!(RD && !RD->hasTrivialDestructor()) &&
- !Init->isConstantInitializer(Context, baseType->isReferenceType()))
- Diag(var->getLocation(), diag::warn_global_constructor)
- << Init->getSourceRange();
- }
+ if ((RD && !RD->hasTrivialDestructor()) ||
+ Init->isConstantInitializer(Context, baseType->isReferenceType()))
+ break;
+
+ CXXConstructExpr *CtorInit = dyn_cast_or_null<CXXConstructExpr>(Init);
+ if (CtorInit) {
+ // Do not warn if constructor will likely generate no code.
+ CXXConstructorDecl *CtorDecl = CtorInit->getConstructor();
+ Stmt *CtorBody = CtorDecl->getBody();
+ bool HasEmptyBody = CtorBody && CtorDecl->isDefined() && cast<CompoundStmt>(CtorBody)->body_empty();
+ bool HasNoInitializers = !CtorDecl->getNumCtorInitializers();
+ if (HasEmptyBody && HasNoInitializers)
+ break;
+ }
+
+ Diag(var->getLocation(), diag::warn_global_constructor)
+ << Init->getSourceRange();
+ } while(0);
if (var->isConstexpr()) {
SmallVector<PartialDiagnosticAt, 8> Notes;
Index: test/SemaCXX/warn-global-constructors.cpp
===================================================================
--- test/SemaCXX/warn-global-constructors.cpp
+++ test/SemaCXX/warn-global-constructors.cpp
@@ -121,6 +121,18 @@
E e;
}
+namespace LinkerInitialized {
+ enum LinkerInitialized { LINKER_INITIALIZED = 0 };
+
+ struct BlockingMutex {
+ BlockingMutex(LinkerInitialized) {}
+ BlockingMutex() {}
+ char owner_;
+ };
+
+ BlockingMutex mu(LINKER_INITIALIZED); // elided
+}
+
namespace pr20420 {
// No warning is expected. This used to crash.
void *array_storage[1];
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits