[cfe-commits] r90480 - in /cfe/trunk: include/clang/AST/Decl.h lib/AST/Expr.cpp lib/AST/ExprConstant.cpp test/CodeGenCXX/eval-recursive-constant.cpp test/SemaCXX/i-c-e-cxx.cpp

Eli Friedman eli.friedman at gmail.com
Thu Dec 3 12:31:57 PST 2009


Author: efriedma
Date: Thu Dec  3 14:31:57 2009
New Revision: 90480

URL: http://llvm.org/viewvc/llvm-project?rev=90480&view=rev
Log:
Add recursion guards to ice-checking and evaluation for declrefs, so we
don't infinitely recurse for cases we can't evaluate.


Added:
    cfe/trunk/test/CodeGenCXX/eval-recursive-constant.cpp
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/test/SemaCXX/i-c-e-cxx.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=90480&r1=90479&r2=90480&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Dec  3 14:31:57 2009
@@ -348,15 +348,23 @@
 /// which it was evaluated (if any), and whether or not the statement
 /// is an integral constant expression (if known).
 struct EvaluatedStmt {
-  EvaluatedStmt() : WasEvaluated(false), CheckedICE(false), IsICE(false) { }
+  EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
+                    CheckingICE(false), IsICE(false) { }
 
   /// \brief Whether this statement was already evaluated.
   bool WasEvaluated : 1;
 
+  /// \brief Whether this statement is being evaluated.
+  bool IsEvaluating : 1;
+
   /// \brief Whether we already checked whether this statement was an
   /// integral constant expression.
   bool CheckedICE : 1;
 
+  /// \brief Whether we are checking whether this statement is an
+  /// integral constant expression.
+  bool CheckingICE : 1;
+
   /// \brief Whether this statement is an integral constant
   /// expression. Only valid if CheckedICE is true.
   bool IsICE : 1;
@@ -504,23 +512,45 @@
 
   void setInit(ASTContext &C, Expr *I);
 
-  /// \brief Note that constant evaluation has computed the given
-  /// value for this variable's initializer.
-  void setEvaluatedValue(ASTContext &C, const APValue &Value) const {
+  EvaluatedStmt *EnsureEvaluatedStmt() const {
     EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
     if (!Eval) {
       Stmt *S = Init.get<Stmt *>();
-      Eval = new (C) EvaluatedStmt;
+      Eval = new (getASTContext()) EvaluatedStmt;
       Eval->Value = S;
       Init = Eval;
     }
+    return Eval;
+  }
+
+  /// \brief Check whether we are in the process of checking whether the
+  /// initializer can be evaluated.
+  bool isEvaluatingValue() const {
+    if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+      return Eval->IsEvaluating;
 
+    return false;
+  }
+
+  /// \brief Note that we now are checking whether the initializer can be
+  /// evaluated.
+  void setEvaluatingValue() const {
+    EvaluatedStmt *Eval = EnsureEvaluatedStmt();
+    Eval->IsEvaluating = true;
+  }
+
+  /// \brief Note that constant evaluation has computed the given
+  /// value for this variable's initializer.
+  void setEvaluatedValue(const APValue &Value) const {
+    EvaluatedStmt *Eval = EnsureEvaluatedStmt();
+    Eval->IsEvaluating = false;
     Eval->WasEvaluated = true;
     Eval->Evaluated = Value;
   }
 
   /// \brief Return the already-evaluated value of this variable's
-  /// initializer, or NULL if the value is not yet known.
+  /// initializer, or NULL if the value is not yet known. Returns pointer
+  /// to untyped APValue if the value could not be evaluated.
   APValue *getEvaluatedValue() const {
     if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
       if (Eval->WasEvaluated)
@@ -548,17 +578,27 @@
     return Init.get<EvaluatedStmt *>()->IsICE;
   }
 
-  /// \brief Note that we now know whether the initializer is an
+  /// \brief Check whether we are in the process of checking the initializer
+  /// is an integral constant expression.
+  bool isCheckingICE() const {
+    if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
+      return Eval->CheckingICE;
+
+    return false;
+  }
+
+  /// \brief Note that we now are checking whether the initializer is an
   /// integral constant expression.
-  void setInitKnownICE(ASTContext &C, bool IsICE) const {
-    EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>();
-    if (!Eval) {
-      Stmt *S = Init.get<Stmt *>();
-      Eval = new (C) EvaluatedStmt;
-      Eval->Value = S;
-      Init = Eval;
-    }
+  void setCheckingICE() const {
+    EvaluatedStmt *Eval = EnsureEvaluatedStmt();
+    Eval->CheckingICE = true;
+  }
 
+  /// \brief Note that we now know whether the initializer is an
+  /// integral constant expression.
+  void setInitKnownICE(bool IsICE) const {
+    EvaluatedStmt *Eval = EnsureEvaluatedStmt();
+    Eval->CheckingICE = false;
     Eval->CheckedICE = true;
     Eval->IsICE = IsICE;
   }

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=90480&r1=90479&r2=90480&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Thu Dec  3 14:31:57 2009
@@ -1596,13 +1596,18 @@
           //   constant expression (5.19). In that case, the member can appear
           //   in integral constant expressions.
           if (Def->isOutOfLine()) {
-            Dcl->setInitKnownICE(Ctx, false);
+            Dcl->setInitKnownICE(false);
             return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
           }
-          
+
+          if (Dcl->isCheckingICE()) {
+            return ICEDiag(2, cast<DeclRefExpr>(E)->getLocation());
+          }
+
+          Dcl->setCheckingICE();
           ICEDiag Result = CheckICE(Init, Ctx);
           // Cache the result of the ICE test.
-          Dcl->setInitKnownICE(Ctx, Result.Val == 0);
+          Dcl->setInitKnownICE(Result.Val == 0);
           return Result;
         }
       }

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=90480&r1=90479&r2=90480&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Dec  3 14:31:57 2009
@@ -866,15 +866,24 @@
     if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
       const VarDecl *Def = 0;
       if (const Expr *Init = VD->getDefinition(Def)) {
-        if (APValue *V = VD->getEvaluatedValue())
-          return Success(V->getInt(), E);
-          
+        if (APValue *V = VD->getEvaluatedValue()) {
+          if (V->isInt())
+            return Success(V->getInt(), E);
+          return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+        }
+
+        if (VD->isEvaluatingValue())
+          return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E);
+
+        VD->setEvaluatingValue();
+
         if (Visit(const_cast<Expr*>(Init))) {
           // Cache the evaluated value in the variable declaration.
-          VD->setEvaluatedValue(Info.Ctx, Result);
+          VD->setEvaluatedValue(Result);
           return true;
         }
 
+        VD->setEvaluatedValue(APValue());
         return false;
       }
     }

Added: cfe/trunk/test/CodeGenCXX/eval-recursive-constant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/eval-recursive-constant.cpp?rev=90480&view=auto

==============================================================================
--- cfe/trunk/test/CodeGenCXX/eval-recursive-constant.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/eval-recursive-constant.cpp Thu Dec  3 14:31:57 2009
@@ -0,0 +1,5 @@
+// RUN: clang-cc %s -emit-llvm-only
+
+extern const int a,b;
+const int a=b,b=a;
+int c() { if (a) return 1; return 0; }

Modified: cfe/trunk/test/SemaCXX/i-c-e-cxx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/i-c-e-cxx.cpp?rev=90480&r1=90479&r2=90480&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/i-c-e-cxx.cpp (original)
+++ cfe/trunk/test/SemaCXX/i-c-e-cxx.cpp Thu Dec  3 14:31:57 2009
@@ -14,3 +14,10 @@
     int array[value];
   }
 }
+
+int a() {
+  const int t=t; // expected-note {{subexpression not valid}}
+  switch(1) {
+    case t:; // expected-error {{not an integer constant expression}}
+  }
+}





More information about the cfe-commits mailing list