diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2011-08-22 17:24:56 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2011-08-22 17:24:56 +0000 |
commit | 0124839d7fb3d846795190ba2ccf3951f27784fe (patch) | |
tree | 7478b216ba45fdd2962dcfc0ef5b8c935b50b137 | |
parent | 80f775359357f90f34b6adb8104506f13a816a67 (diff) |
Fix a crash-on-valid that has been here for a very long time:
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
-rw-r--r-- | lib/AST/ExprConstant.cpp | 11 | ||||
-rw-r--r-- | test/SemaCXX/references.cpp | 3 |
2 files changed, 12 insertions, 2 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index fdcff0a4da..2cd85a104a 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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); diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp index ab44e78453..70d3799a0e 100644 --- a/test/SemaCXX/references.cpp +++ b/test/SemaCXX/references.cpp @@ -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; |