diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-05-26 18:54:04 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-05-26 18:54:04 +0000 |
commit | 31cf12c0a628ce452e325eec45eaed307059df27 (patch) | |
tree | 7470279d12c5dc2a47215ff25b518964544f08cf /clang/lib/AST/Expr.cpp | |
parent | 7d287cb7ed0188f85fa4730f3e3c079aff5457d9 (diff) | |
download | bcm5719-llvm-31cf12c0a628ce452e325eec45eaed307059df27.tar.gz bcm5719-llvm-31cf12c0a628ce452e325eec45eaed307059df27.zip |
When evaluating a VarDecl as a constant or determining whether it is
an integral constant expression, maintain a cache of the value and the
is-an-ICE flag within the VarDecl itself. This eliminates
exponential-time behavior of the Fibonacci template metaprogram.
llvm-svn: 72428
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 6711faffe74..aca5efeb163 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1210,8 +1210,21 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { // type initialized by an ICE can be used in ICEs. if (const VarDecl *Dcl = dyn_cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl())) { - if (const Expr *Init = Dcl->getInit()) - return CheckICE(Init, Ctx); + if (Dcl->isInitKnownICE()) { + // We have already checked whether this subexpression is an + // integral constant expression. + if (Dcl->isInitICE()) + return NoDiag(); + else + return ICEDiag(2, E->getLocStart()); + } + + if (const Expr *Init = Dcl->getInit()) { + ICEDiag Result = CheckICE(Init, Ctx); + // Cache the result of the ICE test. + Dcl->setInitKnownICE(Ctx, Result.Val == 0); + return Result; + } } } return ICEDiag(2, E->getLocStart()); |