From 809bd28961fc9ad33bf93f32c6b3546ad38bfeb0 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 4 Jan 2017 23:14:16 +0000 Subject: [PATCH] Bail out if we try to build a DeclRefExpr naming an invalid declaration. Most code paths would already bail out in this case, but certain paths, particularly overload resolution and typo correction, would not. Carrying on with an invalid declaration could in some cases result in crashes due to downstream code relying on declaration invariants that are not necessarily met for invalid declarations, and in other cases just resulted in undesirable follow-on diagnostics. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@291030 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 3 +++ lib/Sema/SemaExprCXX.cpp | 2 ++ test/SemaCXX/constant-expression-cxx11.cpp | 4 ++-- test/SemaCXX/conversion-function.cpp | 2 +- test/SemaCXX/cxx1z-decomposition.cpp | 5 +++++ test/SemaCXX/type-definition-in-specifier.cpp | 6 ++---- 6 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3c554c9a52..1509b22a9e 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2777,6 +2777,9 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, /// were not overloaded, and it doesn't promise that the declaration /// will in fact be used. static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { + if (D->isInvalidDecl()) + return true; + if (isa(D)) { S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName(); return true; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5f769cc40d..1379440e8a 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -7262,6 +7262,8 @@ public: while (TypoCorrection TC = State.Consumer->getNextCorrection()) { if (InitDecl && TC.getFoundDecl() == InitDecl) continue; + // FIXME: If we would typo-correct to an invalid declaration, it's + // probably best to just suppress all errors from this typo correction. ExprResult NE = State.RecoveryHandler ? State.RecoveryHandler(SemaRef, E, TC) : attemptRecovery(SemaRef, *State.Consumer, TC); diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 581a524339..884f2f30c4 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1725,7 +1725,7 @@ namespace AfterError { constexpr int error() { // expected-error {{no return statement}} return foobar; // expected-error {{undeclared identifier}} } - constexpr int k = error(); // expected-error {{must be initialized by a constant expression}} + constexpr int k = error(); } namespace std { @@ -2030,7 +2030,7 @@ namespace PR21786 { namespace PR21859 { constexpr int Fun() { return; } // expected-error {{non-void constexpr function 'Fun' should return a value}} - constexpr int Var = Fun(); // expected-error {{constexpr variable 'Var' must be initialized by a constant expression}} + constexpr int Var = Fun(); } struct InvalidRedef { diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index c725a0d5b7..531de818b6 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -440,7 +440,7 @@ namespace PR18234 { #endif } a; A::S s = a; // expected-error {{no viable conversion from 'struct A' to 'A::S'}} - A::E e = a; // expected-note {{here}} + A::E e = a; bool k1 = e == A::e; // expected-error {{no member named 'e'}} bool k2 = e.n == 0; } diff --git a/test/SemaCXX/cxx1z-decomposition.cpp b/test/SemaCXX/cxx1z-decomposition.cpp index 735a9e1dfe..d457ace5d8 100644 --- a/test/SemaCXX/cxx1z-decomposition.cpp +++ b/test/SemaCXX/cxx1z-decomposition.cpp @@ -65,4 +65,9 @@ void for_range() { } } +int error_recovery() { + auto [foobar]; // expected-error {{requires an initializer}} + return foobar_; // expected-error {{undeclared identifier 'foobar_'}} +} + // FIXME: by-value array copies diff --git a/test/SemaCXX/type-definition-in-specifier.cpp b/test/SemaCXX/type-definition-in-specifier.cpp index 74ba058b4f..2da649fdb0 100644 --- a/test/SemaCXX/type-definition-in-specifier.cpp +++ b/test/SemaCXX/type-definition-in-specifier.cpp @@ -59,10 +59,8 @@ struct s19018b { }; struct pr18963 { - short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot be defined in a parameter type}} \ - // expected-note{{declared here}} - - long foo5 (float foo6 = foo4); // expected-error{{'foo4' does not refer to a value}} + short bar5 (struct foo4 {} bar2); // expected-error{{'foo4' cannot be defined in a parameter type}} + long foo5 (float foo6 = foo4); }; // expected-error@+2 {{cannot be defined in a parameter type}} -- 2.50.1