From: Richard Smith Date: Wed, 7 Dec 2011 00:43:50 +0000 (+0000) Subject: When folding the size of a global scope VLA to a constant, require the array X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aa9c3503867bc52e1f61c4da676116db1b1cdf01;p=clang When folding the size of a global scope VLA to a constant, require the array bound to not have side effects(!). Add constant-folding support for expressions of void type, to ensure that we can still fold ((void)0, 1) as an array bound. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146000 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 6a290a6c83..9b9150c148 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -4332,6 +4332,37 @@ bool ComplexExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { } } +//===----------------------------------------------------------------------===// +// Void expression evaluation, primarily for a cast to void on the LHS of a +// comma operator +//===----------------------------------------------------------------------===// + +namespace { +class VoidExprEvaluator + : public ExprEvaluatorBase { +public: + VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {} + + bool Success(const CCValue &V, const Expr *e) { return true; } + bool Error(const Expr *E) { return false; } + + bool VisitCastExpr(const CastExpr *E) { + switch (E->getCastKind()) { + default: + return ExprEvaluatorBaseTy::VisitCastExpr(E); + case CK_ToVoid: + VisitIgnoredValue(E->getSubExpr()); + return true; + } + } +}; +} // end anonymous namespace + +static bool EvaluateVoid(const Expr *E, EvalInfo &Info) { + assert(E->isRValue() && E->getType()->isVoidType()); + return VoidExprEvaluator(Info).Visit(E); +} + //===----------------------------------------------------------------------===// // Top level Expr::EvaluateAsRValue method. //===----------------------------------------------------------------------===// @@ -4383,6 +4414,9 @@ static bool Evaluate(CCValue &Result, EvalInfo &Info, const Expr *E) { if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info)) return false; Result = Info.CurrentCall->Temporaries[E]; + } else if (E->getType()->isVoidType()) { + if (!EvaluateVoid(E, Info)) + return false; } else return false; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index cc8ec878cc..793cbf31bf 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -18,7 +18,6 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "TypeLocBuilder.h" -#include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" @@ -3465,14 +3464,12 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, if (VLATy->getElementType()->isVariablyModifiedType()) return QualType(); - Expr::EvalResult EvalResult; + llvm::APSInt Res; if (!VLATy->getSizeExpr() || - !VLATy->getSizeExpr()->EvaluateAsRValue(EvalResult, Context) || - !EvalResult.Val.isInt()) + !VLATy->getSizeExpr()->EvaluateAsInt(Res, Context)) return QualType(); // Check whether the array size is negative. - llvm::APSInt &Res = EvalResult.Val.getInt(); if (Res.isSigned() && Res.isNegative()) { SizeIsNegative = true; return QualType(); diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c index 8904e12bf7..a40039bdc5 100644 --- a/test/Sema/const-eval.c +++ b/test/Sema/const-eval.c @@ -14,9 +14,9 @@ EVAL_EXPR(8, (_Bool)"asdf") EVAL_EXPR(9, !!&x) EVAL_EXPR(10, ((void)1, 12)) void g0(void); -EVAL_EXPR(11, (g0(), 12)) // FIXME: This should give an error +EVAL_EXPR(11, (g0(), 12)) // expected-error {{must have a constant size}} EVAL_EXPR(12, 1.0&&2.0) -EVAL_EXPR(13, x || 3.0) +EVAL_EXPR(13, x || 3.0) // expected-error {{must have a constant size}} unsigned int l_19 = 1; EVAL_EXPR(14, (1 ^ l_19) && 1); // expected-error {{fields must have a constant size}}