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(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(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 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];