diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -383,6 +383,8 @@ if (Decl->isParameterPack()) Deps |= ExprDependence::UnexpandedPack; + if (Decl->isInvalidDecl()) + Deps |= ExprDependence::Error; Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error; // (TD) C++ [temp.dep.expr]p3: diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1233,7 +1233,8 @@ Result.resolveKind(); bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); - return BuildDeclarationNameExpr(SS, Result, ADL); + return BuildDeclarationNameExpr(SS, Result, ADL, + Context.getLangOpts().RecoveryAST); } Sema::TemplateNameKindForDiagnostics 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 @@ -3005,8 +3005,9 @@ /// as an expression. This is only actually called for lookups that /// 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()) +static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D, + bool AcceptInvalidDecl) { + if (!AcceptInvalidDecl && D->isInvalidDecl()) return true; if (isa(D)) { @@ -3052,7 +3053,8 @@ // result, because in the overloaded case the results can only be // functions and function templates. if (R.isSingleResult() && !ShouldLookupResultBeMultiVersionOverload(R) && - CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) + CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl(), + AcceptInvalidDecl)) return ExprError(); // Otherwise, just build an unresolved lookup expression. Suppress @@ -3084,7 +3086,7 @@ "Cannot refer unambiguously to a function template"); SourceLocation Loc = NameInfo.getLoc(); - if (CheckDeclInExpr(*this, Loc, D)) + if (CheckDeclInExpr(*this, Loc, D, AcceptInvalidDecl)) return ExprError(); if (TemplateDecl *Template = dyn_cast(D)) { @@ -3159,7 +3161,6 @@ case Decl::ObjCIvar: assert(getLangOpts().CPlusPlus && "building reference to field in C?"); - // These can't have reference type in well-formed programs, but // for internal consistency we do this anyway. type = type.getNonReferenceType(); diff --git a/clang/test/AST/ast-dump-expr-errors.cpp b/clang/test/AST/ast-dump-expr-errors.cpp --- a/clang/test/AST/ast-dump-expr-errors.cpp +++ b/clang/test/AST/ast-dump-expr-errors.cpp @@ -42,5 +42,16 @@ // FIXME: store initializer even when 'auto' could not be deduced. // Expressions with errors currently do not keep initializers around. -// CHECK: `-VarDecl {{.*}} invalid e 'auto' +// CHECK: |-VarDecl {{.*}} invalid e 'auto' auto e = bar(); + +// CHECK: FunctionDecl {{.*}} +// CHECK-NEXT: `-CompoundStmt {{.*}} +// CHECK-NEXT: |-DeclStmt {{.*}} +// CHECK-NEXT: | `-VarDecl {{.*}} invalid foo 'Foo' +// CHECK-NEXT: `-DeclRefExpr {{.*}} 'Foo' contains-errors +struct Foo { Foo(int); }; +void invalidDeclRefExpr() { + Foo foo; + foo; +} diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -93,7 +93,7 @@ void f(X *x) { auto value = x->method; // expected-error {{reference to non-static member function must be called}} - if (value) { } + if (value) { } // expected-error {{value of type 'auto' is not contextually convertible to 'bool'}} auto funcptr = &g; int (*funcptr2)(int) = funcptr; diff --git a/clang/test/CXX/drs/dr3xx.cpp b/clang/test/CXX/drs/dr3xx.cpp --- a/clang/test/CXX/drs/dr3xx.cpp +++ b/clang/test/CXX/drs/dr3xx.cpp @@ -429,8 +429,8 @@ namespace dr331 { // dr331: yes struct A { - A(volatile A&); // expected-note {{candidate}} - } const a, b(a); // expected-error {{no matching constructor}} + A(volatile A&); // expected-note 2{{candidate}} + } const a, b(a); // expected-error 2{{no matching constructor}} } namespace dr332 { // dr332: dup 577 diff --git a/clang/test/CodeCompletion/error-covery.cpp b/clang/test/CodeCompletion/error-covery.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeCompletion/error-covery.cpp @@ -0,0 +1,7 @@ +struct Foo { Foo(int); int abc; }; +void invalidDeclRefExpr() { + Foo foo; + foo.; + // RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:5:7 %s -o - | FileCheck %s + // CHECK: COMPLETION: abc +} diff --git a/clang/test/Modules/submodules-merge-defs.cpp b/clang/test/Modules/submodules-merge-defs.cpp --- a/clang/test/Modules/submodules-merge-defs.cpp +++ b/clang/test/Modules/submodules-merge-defs.cpp @@ -31,7 +31,9 @@ // expected-note@defs.h:4 +{{here}} // expected-note@defs.h:17 +{{here}} void pre_bfi(B b) { // expected-error +{{must be imported}} - b.f(); + b.f(); // expected-error {{member reference base type}} \ + expected-error {{expected '(' for function-style}} \ + expected-error {{expected expression}} } C_Base<1> pre_cb1; // expected-error +{{must be imported}} diff --git a/clang/test/OpenMP/openmp_check.cpp b/clang/test/OpenMP/openmp_check.cpp --- a/clang/test/OpenMP/openmp_check.cpp +++ b/clang/test/OpenMP/openmp_check.cpp @@ -28,5 +28,8 @@ } }; F(); +#if __cplusplus <= 199711L + // expected-error@-2 {{called object type 'auto' is not a function}} +#endif return a; } diff --git a/clang/test/SemaCXX/block-call.cpp b/clang/test/SemaCXX/block-call.cpp --- a/clang/test/SemaCXX/block-call.cpp +++ b/clang/test/SemaCXX/block-call.cpp @@ -33,7 +33,7 @@ int (^IPCC6) (int, char (^CArg) (float)) = IPCC4; // expected-error {{cannot initialize a variable of type 'int (^)(int, char (^)(float))' with an lvalue of type}} IPCC2 = 0; - IPCC2 = 1; + IPCC2 = 1; // expected-error {{invalid block pointer conversion assigning}} int (^x)() = 0; int (^y)() = 3; // expected-error {{cannot initialize a variable of type 'int (^)()' with an rvalue of type 'int'}} int a = 1; diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -440,7 +440,7 @@ #endif } a; A::S s = a; // expected-error {{no viable conversion from 'struct A' to 'A::S'}} - A::E e = a; + A::E e = a; // expected-note {{'e' declared here}} bool k1 = e == A::e; // expected-error {{no member named 'e'}} bool k2 = e.n == 0; } diff --git a/clang/test/SemaCXX/cxx11-crashes.cpp b/clang/test/SemaCXX/cxx11-crashes.cpp --- a/clang/test/SemaCXX/cxx11-crashes.cpp +++ b/clang/test/SemaCXX/cxx11-crashes.cpp @@ -70,7 +70,7 @@ for (auto x : s) { // We used to attempt to evaluate the initializer of this variable, // and crash because it has an undeduced type. - const int &n(x); + const int &n(x); // expected-error {{reference to type 'const int' could not bind}} } } } diff --git a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp --- a/clang/test/SemaCXX/cxx2a-explicit-bool.cpp +++ b/clang/test/SemaCXX/cxx2a-explicit-bool.cpp @@ -124,7 +124,7 @@ A && a6{ 0}; A a7 = { 0}; // expected-error {{chosen constructor is explicit in copy-initialization}} -a0 = 0; +a0 = 0; // expected-error {{no viable overloaded '='}} a1 = { 0}; // expected-error {{no viable overloaded '='}} a2 = A( 0); a3 = A{ 0}; diff --git a/clang/test/SemaCXX/for-range-examples.cpp b/clang/test/SemaCXX/for-range-examples.cpp --- a/clang/test/SemaCXX/for-range-examples.cpp +++ b/clang/test/SemaCXX/for-range-examples.cpp @@ -187,9 +187,9 @@ void f() { for (auto x : undeclared_identifier) // expected-error {{undeclared identifier}} for (auto y : x->foo) - y->bar(); + y->bar(); // expected-error {{member reference type 'auto' is not a pointer}} for (auto x : 123) // expected-error {{no viable 'begin'}} - x->foo(); + x->foo(); // expected-error {{member reference type 'auto' is not a pointer}} } }