Further adjustments to -Wglobal-constructors; works for references and direct
initializations now.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110063 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index a36a83b..7642c0d 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1342,15 +1342,20 @@
return false;
}
-bool Expr::isConstantInitializer(ASTContext &Ctx) const {
+bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
// This function is attempting whether an expression is an initializer
// which can be evaluated at compile-time. isEvaluatable handles most
// of the cases, but it can't deal with some initializer-specific
// expressions, and it can't deal with aggregates; we deal with those here,
// and fall back to isEvaluatable for the other cases.
- // FIXME: This function assumes the variable being assigned to
- // isn't a reference type!
+ // If we ever capture reference-binding directly in the AST, we can
+ // kill the second parameter.
+
+ if (IsForRef) {
+ EvalResult Result;
+ return EvaluateAsLValue(Result, Ctx) && !Result.HasSideEffects;
+ }
switch (getStmtClass()) {
default: break;
@@ -1361,23 +1366,24 @@
case CXXTemporaryObjectExprClass:
case CXXConstructExprClass: {
const CXXConstructExpr *CE = cast<CXXConstructExpr>(this);
+
+ // Only if it's
+ // 1) an application of the trivial default constructor or
if (!CE->getConstructor()->isTrivial()) return false;
- for (CXXConstructExpr::const_arg_iterator
- I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I)
- if (!(*I)->isConstantInitializer(Ctx))
- return false;
- return true;
- }
- case CXXBindReferenceExprClass: {
- const CXXBindReferenceExpr *RE = cast<CXXBindReferenceExpr>(this);
- return RE->getSubExpr()->isConstantInitializer(Ctx);
+ if (!CE->getNumArgs()) return true;
+
+ // 2) an elidable trivial copy construction of an operand which is
+ // itself a constant initializer. Note that we consider the
+ // operand on its own, *not* as a reference binding.
+ return CE->isElidable() &&
+ CE->getArg(0)->isConstantInitializer(Ctx, false);
}
case CompoundLiteralExprClass: {
// This handles gcc's extension that allows global initializers like
// "struct x {int x;} x = (struct x) {};".
// FIXME: This accepts other cases it shouldn't!
const Expr *Exp = cast<CompoundLiteralExpr>(this)->getInitializer();
- return Exp->isConstantInitializer(Ctx);
+ return Exp->isConstantInitializer(Ctx, false);
}
case InitListExprClass: {
// FIXME: This doesn't deal with fields with reference types correctly.
@@ -1386,7 +1392,7 @@
const InitListExpr *Exp = cast<InitListExpr>(this);
unsigned numInits = Exp->getNumInits();
for (unsigned i = 0; i < numInits; i++) {
- if (!Exp->getInit(i)->isConstantInitializer(Ctx))
+ if (!Exp->getInit(i)->isConstantInitializer(Ctx, false))
return false;
}
return true;
@@ -1394,11 +1400,12 @@
case ImplicitValueInitExprClass:
return true;
case ParenExprClass:
- return cast<ParenExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<ParenExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, IsForRef);
case UnaryOperatorClass: {
const UnaryOperator* Exp = cast<UnaryOperator>(this);
if (Exp->getOpcode() == UnaryOperator::Extension)
- return Exp->getSubExpr()->isConstantInitializer(Ctx);
+ return Exp->getSubExpr()->isConstantInitializer(Ctx, false);
break;
}
case BinaryOperatorClass: {
@@ -1411,6 +1418,7 @@
return true;
break;
}
+ case CXXFunctionalCastExprClass:
case CXXStaticCastExprClass:
case ImplicitCastExprClass:
case CStyleCastExprClass:
@@ -1418,13 +1426,15 @@
// deals with both the gcc no-op struct cast extension and the
// cast-to-union extension.
if (getType()->isRecordType())
- return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, false);
// Integer->integer casts can be handled here, which is important for
// things like (int)(&&x-&&y). Scary but true.
if (getType()->isIntegerType() &&
cast<CastExpr>(this)->getSubExpr()->getType()->isIntegerType())
- return cast<CastExpr>(this)->getSubExpr()->isConstantInitializer(Ctx);
+ return cast<CastExpr>(this)->getSubExpr()
+ ->isConstantInitializer(Ctx, false);
break;
}