@@ -3866,6 +3866,57 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init) {
3866
3866
AddInitializerToDecl (dcl, move (init), /* DirectInit=*/ false );
3867
3867
}
3868
3868
3869
+ // / Make a reasonable guess at whether the given initializer will
3870
+ // / require a global constructor.
3871
+ static bool RequiresGlobalConstructor (Sema &S, Expr *Init) {
3872
+ // FIXME: reproducing the logic of CGExprConstant is kindof dumb.
3873
+ // Maybe this should be integrated into the constant-evaluator?
3874
+ // We'd need array and struct value types.
3875
+ //
3876
+ // It's probably okay to still warn in the theoretical cases where
3877
+ // IR gen can eliminate a global constructor based on
3878
+ // initialization order (not that it actually does that
3879
+ // optimization at the moment).
3880
+ if (Init->isEvaluatable (S.Context )) return false ;
3881
+
3882
+ Init = Init->IgnoreParenNoopCasts (S.Context );
3883
+
3884
+ // Look through reference-bindings.
3885
+ if (CXXBindReferenceExpr *BE = dyn_cast<CXXBindReferenceExpr>(Init))
3886
+ return RequiresGlobalConstructor (S, BE);
3887
+
3888
+ // A constructor call needs a global constructor if:
3889
+ if (CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init)) {
3890
+ // - the constructor is non-trivial
3891
+ if (!CE->getConstructor ()->isTrivial ()) return true ;
3892
+
3893
+ // - any of the argument expressions needs a global constructor
3894
+ for (CXXConstructExpr::arg_iterator
3895
+ I = CE->arg_begin (), E = CE->arg_end (); I != E; ++I)
3896
+ if (RequiresGlobalConstructor (S, *I))
3897
+ return true ;
3898
+
3899
+ // We don't have to worry about building temporaries with
3900
+ // non-trivial destructors because we should never have walked
3901
+ // through the CXXExprWithTemporaries.
3902
+
3903
+ // So it should be emitted as a constant expression.
3904
+ return false ;
3905
+ }
3906
+
3907
+ // / An initializer list requires a global constructor if any of the
3908
+ // / components do.
3909
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) {
3910
+ for (unsigned I = 0 , E = ILE->getNumInits (); I != E; ++I)
3911
+ if (RequiresGlobalConstructor (S, ILE->getInit (I)))
3912
+ return true ;
3913
+ return false ;
3914
+ }
3915
+
3916
+ // Assume everything else does.
3917
+ return true ;
3918
+ }
3919
+
3869
3920
// / AddInitializerToDecl - Adds the initializer Init to the
3870
3921
// / declaration dcl. If DirectInit is true, this is C++ direct
3871
3922
// / initialization rather than copy initialization.
@@ -4065,6 +4116,11 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
4065
4116
VDecl->setInit (Init);
4066
4117
4067
4118
if (getLangOptions ().CPlusPlus ) {
4119
+ if (!VDecl->isInvalidDecl () &&
4120
+ !VDecl->getDeclContext ()->isDependentContext () &&
4121
+ VDecl->hasGlobalStorage () && RequiresGlobalConstructor (*this , Init))
4122
+ Diag (VDecl->getLocation (), diag::warn_global_constructor);
4123
+
4068
4124
// Make sure we mark the destructor as used if necessary.
4069
4125
QualType InitType = VDecl->getType ();
4070
4126
while (const ArrayType *Array = Context.getAsArrayType (InitType))
@@ -4270,8 +4326,15 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
4270
4326
MultiExprArg (*this , 0 , 0 ));
4271
4327
if (Init.isInvalid ())
4272
4328
Var->setInvalidDecl ();
4273
- else if (Init.get ())
4329
+ else if (Init.get ()) {
4274
4330
Var->setInit (MaybeCreateCXXExprWithTemporaries (Init.takeAs <Expr>()));
4331
+
4332
+ if (getLangOptions ().CPlusPlus && !Var->isInvalidDecl () &&
4333
+ Var->hasGlobalStorage () &&
4334
+ !Var->getDeclContext ()->isDependentContext () &&
4335
+ RequiresGlobalConstructor (*this , Var->getInit ()))
4336
+ Diag (Var->getLocation (), diag::warn_global_constructor);
4337
+ }
4275
4338
}
4276
4339
4277
4340
if (!Var->isInvalidDecl () && getLangOptions ().CPlusPlus && Record)
0 commit comments