]> granicus.if.org Git - clang/commitdiff
When folding the size of a global scope VLA to a constant, require the array
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 7 Dec 2011 00:43:50 +0000 (00:43 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 7 Dec 2011 00:43:50 +0000 (00:43 +0000)
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

lib/AST/ExprConstant.cpp
lib/Sema/SemaDecl.cpp
test/Sema/const-eval.c

index 6a290a6c8340ac87f0624892dfdad82923c0da15..9b9150c148b4c1760d2f768b37360ade4079bc46 100644 (file)
@@ -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<VoidExprEvaluator, bool> {
+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;
 
index cc8ec878ccb41a62a1281887cccf1ff5efc46b7f..793cbf31bf1ab4847dfde26f3ccde1e12429422c 100644 (file)
@@ -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();
index 8904e12bf7ab2fd54602ff4c2813191394a539db..a40039bdc5bd61f0c8b24bb0abfb40633104b969 100644 (file)
@@ -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}}