More progress on array initializers.
- Added Expr::isConstantExpr().
- Added type checking for InitListExpr elements.
- Added diagnostic for trying to initialize a variable sized object.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41674 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/Expr.cpp b/AST/Expr.cpp
index d664c46..c257b3b 100644
--- a/AST/Expr.cpp
+++ b/AST/Expr.cpp
@@ -350,6 +350,120 @@
return MLV_Valid;
}
+bool Expr::isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const {
+
+ switch (getStmtClass()) {
+ default:
+ if (Loc) *Loc = getLocStart();
+ return false;
+ case ParenExprClass:
+ return cast<ParenExpr>(this)->getSubExpr()->isConstantExpr(Ctx, Loc);
+ case StringLiteralClass:
+ case FloatingLiteralClass:
+ case IntegerLiteralClass:
+ case CharacterLiteralClass:
+ case ImaginaryLiteralClass:
+ case TypesCompatibleExprClass:
+ break;
+ case CallExprClass: {
+ const CallExpr *CE = cast<CallExpr>(this);
+ llvm::APSInt Result(32);
+ Result.zextOrTrunc(Ctx.getTypeSize(getType(), CE->getLocStart()));
+ if (CE->isBuiltinClassifyType(Result))
+ break;
+ if (Loc) *Loc = getLocStart();
+ return false;
+ }
+ case DeclRefExprClass:
+ if (isa<EnumConstantDecl>(cast<DeclRefExpr>(this)->getDecl()))
+ break;
+ if (Loc) *Loc = getLocStart();
+ return false;
+ case UnaryOperatorClass: {
+ const UnaryOperator *Exp = cast<UnaryOperator>(this);
+
+ // Get the operand value. If this is sizeof/alignof, do not evalute the
+ // operand. This affects C99 6.6p3.
+ if (!Exp->isSizeOfAlignOfOp() &&
+ !Exp->getSubExpr()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ switch (Exp->getOpcode()) {
+ // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
+ // See C99 6.6p3.
+ default:
+ if (Loc) *Loc = Exp->getOperatorLoc();
+ return false;
+ case UnaryOperator::Extension:
+ return true; // FIXME: this is wrong.
+ case UnaryOperator::SizeOf:
+ case UnaryOperator::AlignOf:
+ // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
+ if (!Exp->getSubExpr()->getType()->isConstantSizeType(Ctx, Loc))
+ return false;
+ break;
+ case UnaryOperator::LNot:
+ case UnaryOperator::Plus:
+ case UnaryOperator::Minus:
+ case UnaryOperator::Not:
+ break;
+ }
+ break;
+ }
+ case SizeOfAlignOfTypeExprClass: {
+ const SizeOfAlignOfTypeExpr *Exp = cast<SizeOfAlignOfTypeExpr>(this);
+ // alignof always evaluates to a constant.
+ if (Exp->isSizeOf() && !Exp->getArgumentType()->isConstantSizeType(Ctx,Loc))
+ return false;
+ break;
+ }
+ case BinaryOperatorClass: {
+ const BinaryOperator *Exp = cast<BinaryOperator>(this);
+
+ // The LHS of a constant expr is always evaluated and needed.
+ if (!Exp->getLHS()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ if (!Exp->getRHS()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ break;
+ }
+ case ImplicitCastExprClass:
+ case CastExprClass: {
+ const Expr *SubExpr;
+ SourceLocation CastLoc;
+ if (const CastExpr *C = dyn_cast<CastExpr>(this)) {
+ SubExpr = C->getSubExpr();
+ CastLoc = C->getLParenLoc();
+ } else {
+ SubExpr = cast<ImplicitCastExpr>(this)->getSubExpr();
+ CastLoc = getLocStart();
+ }
+ if (!SubExpr->isConstantExpr(Ctx, Loc)) {
+ if (Loc) *Loc = SubExpr->getLocStart();
+ return false;
+ }
+ break;
+ }
+ case ConditionalOperatorClass: {
+ const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
+
+ if (!Exp->getCond()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ if (!Exp->getLHS()->isConstantExpr(Ctx, Loc))
+ return false;
+
+ if (!Exp->getRHS()->isConstantExpr(Ctx, Loc))
+ return false;
+ break;
+ }
+ }
+
+ return true;
+}
+
/// isIntegerConstantExpr - this recursive routine will test if an expression is
/// an integer constant expression. Note: With the introduction of VLA's in
/// C99 the result of the sizeof operator is no longer always a constant