]> granicus.if.org Git - clang/commitdiff
Fix a crash-on-valid that has been here for a very long time:
authorChandler Carruth <chandlerc@gmail.com>
Mon, 22 Aug 2011 17:24:56 +0000 (17:24 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Mon, 22 Aug 2011 17:24:56 +0000 (17:24 +0000)
  const int &x = x;

This crashed by inifinetly recursing within the lvalue evaluation
routine. I've added a (somewhat) braindead way of preventing this
recursion. If folks have better suggestions for how to avoid it I'm all
ears.

That said, we have some work to do. This doesn't trigger a single
warning for uninitialized, self-initialized or otherwise completely
wrong code. In some senses, the crash was almost better.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138239 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
test/SemaCXX/references.cpp

index fdcff0a4dafac85a21c1399b23480dd8208b6d39..2cd85a104a20bb862b956ebc7b62429dc94b3cd7 100644 (file)
@@ -447,6 +447,7 @@ namespace {
 class LValueExprEvaluator
   : public ExprEvaluatorBase<LValueExprEvaluator, bool> {
   LValue &Result;
+  const Decl *PrevDecl;
 
   bool Success(const Expr *E) {
     Result.Base = E;
@@ -456,7 +457,7 @@ class LValueExprEvaluator
 public:
 
   LValueExprEvaluator(EvalInfo &info, LValue &Result) :
-    ExprEvaluatorBaseTy(info), Result(Result) {}
+    ExprEvaluatorBaseTy(info), Result(Result), PrevDecl(0) {}
 
   bool Success(const APValue &V, const Expr *E) {
     Result.setFrom(V);
@@ -501,10 +502,16 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
       return Success(E);
     // Reference parameters can refer to anything even if they have an
     // "initializer" in the form of a default argument.
-    if (!isa<ParmVarDecl>(VD))
+    if (!isa<ParmVarDecl>(VD)) {
       // FIXME: Check whether VD might be overridden!
+
+      // Check for recursive initializers of references.
+      if (PrevDecl == VD)
+        return Error(E);
+      PrevDecl = VD;
       if (const Expr *Init = VD->getAnyInitializer())
         return Visit(Init);
+    }
   }
 
   return ExprEvaluatorBaseTy::VisitDeclRefExpr(E);
index ab44e78453b2cfdbb7eda4da841eb1c40cdaed6f..70d3799a0ea5684e0d1bc47d67eee8e4e5c2afda 100644 (file)
@@ -134,3 +134,6 @@ namespace PR7149 {
 namespace PR8608 {
   bool& f(unsigned char& c) { return (bool&)c; }
 }
+
+// The following crashed trying to recursively evaluate the LValue.
+const int &do_not_crash = do_not_crash;