]> granicus.if.org Git - clang/commitdiff
Bail out if we try to build a DeclRefExpr naming an invalid declaration.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 4 Jan 2017 23:14:16 +0000 (23:14 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 4 Jan 2017 23:14:16 +0000 (23:14 +0000)
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
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/constant-expression-cxx11.cpp
test/SemaCXX/conversion-function.cpp
test/SemaCXX/cxx1z-decomposition.cpp
test/SemaCXX/type-definition-in-specifier.cpp

index 3c554c9a5244f1753f5c7ffc1a1e520cd3b3faea..1509b22a9e5a67945b157035482d2cadb5f9d3fc 100644 (file)
@@ -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<TypedefNameDecl>(D)) {
     S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName();
     return true;
index 5f769cc40ded4132957a469deef9e975ecb4dece..1379440e8a031afbb09203388f32402977c76b3b 100644 (file)
@@ -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);
index 581a524339e752326005e91fe31a88497bd1d517..884f2f30c42f5a4b83a85d633519440f3918b445 100644 (file)
@@ -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 {
index c725a0d5b7c1914f0da07751ee671a42429eefc2..531de818b6807b08fc91586fd02c835b6111cc8f 100644 (file)
@@ -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;
 }
index 735a9e1dfee0f39bd721711204f9a14b14b1d91a..d457ace5d844e422df44adcc50b34239c8f49b47 100644 (file)
@@ -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
index 74ba058b4f12b8652c96299fcf1c7dee1434d49c..2da649fdb0b8dad68407b0ff0c832319d281d8a9 100644 (file)
@@ -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}}