diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3228,8 +3228,12 @@ "Cannot refer unambiguously to a function template"); SourceLocation Loc = NameInfo.getLoc(); - if (CheckDeclInExpr(*this, Loc, D)) - return ExprError(); + if (CheckDeclInExpr(*this, Loc, D)) { + // Recovery from invalid cases (e.g. D is an invalid Decl). + // We use the dependent type for the RecoveryExpr to prevent bogus follow-up + // diagnostics, as invalid decls use int as a fallback type. + return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); + } if (TemplateDecl *Template = dyn_cast(D)) { // Specifically diagnose references to class templates that are missing diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -401,3 +401,13 @@ // CHECK-NEXT: |-IntegerLiteral {{.*}} 'int' 7 // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 8 } + +void RecoveryExprForInvalidDecls(Unknown InvalidDecl) { + InvalidDecl + 1; + // CHECK: BinaryOperator {{.*}} + // CHECK-NEXT: |-RecoveryExpr {{.*}} '' + // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 + InvalidDecl(); + // CHECK: CallExpr {{.*}} + // CHECK-NEXT: `-RecoveryExpr {{.*}} '' +} diff --git a/clang/test/Sema/ms-inline-asm.c b/clang/test/Sema/ms-inline-asm.c --- a/clang/test/Sema/ms-inline-asm.c +++ b/clang/test/Sema/ms-inline-asm.c @@ -78,7 +78,6 @@ __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}} expected-error {{use of undeclared label 'UndeclaredId'}} // FIXME: Only emit one diagnostic here. - // expected-error@+3 {{use of undeclared label 'A'}} // expected-error@+2 {{unexpected type name 'A': expected expression}} // expected-error@+1 {{unknown token in expression}} __asm { mov eax, [eax] A } diff --git a/clang/test/SemaCXX/constructor-initializer.cpp b/clang/test/SemaCXX/constructor-initializer.cpp --- a/clang/test/SemaCXX/constructor-initializer.cpp +++ b/clang/test/SemaCXX/constructor-initializer.cpp @@ -249,7 +249,7 @@ class B : public A { public: B(const String& s, int e=0) // expected-error {{unknown type name}} - : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}} + : A(e), m_String(s) , m_ErrorStr(__null) {} // expected-error {{no matching constructor}} expected-error {{does not name}} expected-error {{member initializer 'm_ErrorStr' does not name}} B(const B& e) : A(e), m_String(e.m_String), m_ErrorStr(__null) { // expected-error 2{{does not name}} \ // expected-error {{no member named 'm_String' in 'test3::B'}} diff --git a/clang/test/SemaCXX/copy-assignment.cpp b/clang/test/SemaCXX/copy-assignment.cpp --- a/clang/test/SemaCXX/copy-assignment.cpp +++ b/clang/test/SemaCXX/copy-assignment.cpp @@ -114,6 +114,7 @@ namespace test1 { template class A : public unknown::X { // expected-error {{undeclared identifier 'unknown'}} expected-error {{expected class name}} A(UndeclaredType n) : X(n) {} // expected-error {{unknown type name 'UndeclaredType'}} + // expected-error@-1 {{member initializer 'X' does not name a non-static data member or base class}} }; template class B : public A { virtual void foo() {}