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.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72428 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 34b0187..7651884 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -700,8 +700,17 @@
   // In C, they can also be folded, although they are not ICEs.
   if (E->getType().getCVRQualifiers() == QualType::Const) {
     if (const VarDecl *D = dyn_cast<VarDecl>(E->getDecl())) {
-      if (const Expr *Init = D->getInit())
-        return Visit(const_cast<Expr*>(Init));
+      if (APValue *V = D->getEvaluatedValue())
+        return Success(V->getInt(), E);
+      if (const Expr *Init = D->getInit()) {
+        if (Visit(const_cast<Expr*>(Init))) {
+          // Cache the evaluated value in the variable declaration.
+          D->setEvaluatedValue(Info.Ctx, Result);
+          return true;
+        }
+
+        return false;
+      }
     }
   }