[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