diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8bb306e66d62..f365d82047b7 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2068,8 +2068,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, AcceptableWithoutRecovery = isa(UnderlyingND) || isa(UnderlyingND); } else { - // FIXME: We found a keyword. Suggest it, but don't provide a fix-it - // because we aren't able to recover. + // FIXME: We found a keyword or a type. Suggest it, but don't provide a + // fix-it because we aren't able to recover. AcceptableWithoutRecovery = true; } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 2b7924d244e1..001a06f0bdf8 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -4996,7 +4996,9 @@ FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs, : NumArgs(NumArgs), HasExplicitTemplateArgs(HasExplicitTemplateArgs), CurContext(SemaRef.CurContext), MemberFn(ME) { WantTypeSpecifiers = false; - WantFunctionLikeCasts = SemaRef.getLangOpts().CPlusPlus && NumArgs == 1; + WantFunctionLikeCasts = SemaRef.getLangOpts().CPlusPlus && + !HasExplicitTemplateArgs && NumArgs == 1; + WantCXXNamedCasts = HasExplicitTemplateArgs && NumArgs == 1; WantRemainingKeywords = false; } @@ -5025,6 +5027,13 @@ bool FunctionCallFilterCCC::ValidateCandidate(const TypoCorrection &candidate) { } } + // A typo for a function-style cast can look like a function call in C++. + if ((HasExplicitTemplateArgs ? getAsTypeTemplateDecl(ND) != nullptr + : isa(ND)) && + CurContext->getParentASTContext().getLangOpts().CPlusPlus) + // Only a class or class template can take two or more arguments. + return NumArgs <= 1 || HasExplicitTemplateArgs || isa(ND); + // Skip the current candidate if it is not a FunctionDecl or does not accept // the current number of arguments. if (!FD || !(FD->getNumParams() >= NumArgs && diff --git a/clang/test/CXX/class/class.mem/p1.cpp b/clang/test/CXX/class/class.mem/p1.cpp index a41f1dbb75ec..3bd1df99d173 100644 --- a/clang/test/CXX/class/class.mem/p1.cpp +++ b/clang/test/CXX/class/class.mem/p1.cpp @@ -9,14 +9,14 @@ struct S static int v; //expected-error{{redefinition of 'v' as different kind of symbol}} int v; //expected-error{{duplicate member 'v'}} static int v; //expected-error{{redefinition of 'v' as different kind of symbol}} - enum EnumT { E = 10 }; + enum EnumT { E = 10 }; // expected-note {{declared here}} friend struct M; struct X; //expected-note{{forward declaration of 'S::X'}} friend struct X; }; S::EnumT Evar = S::E; // ok -S::EnumT Evar2 = EnumT(); //expected-error{{use of undeclared identifier 'EnumT'}} +S::EnumT Evar2 = EnumT(); //expected-error{{use of undeclared identifier 'EnumT'; did you mean 'S::EnumT'?}} S::M m; //expected-error{{no type named 'M' in 'S'}} S::X x; //expected-error{{variable has incomplete type 'S::X'}} diff --git a/clang/test/FixIt/fixit-unrecoverable.cpp b/clang/test/FixIt/fixit-unrecoverable.cpp index f555792ed39b..ef09fa27c977 100644 --- a/clang/test/FixIt/fixit-unrecoverable.cpp +++ b/clang/test/FixIt/fixit-unrecoverable.cpp @@ -8,3 +8,10 @@ float f(int y) { return static_cst(y); // expected-error{{use of undeclared identifier 'static_cst'; did you mean 'static_cast'?}} } + +struct Foobar {}; // expected-note {{here}} +template struct Goobar {}; // expected-note {{here}} +void use_foobar() { + auto x = zoobar(); // expected-error {{did you mean 'Foobar'}} + auto y = zoobar(); // expected-error {{did you mean 'Goobar'}} +} diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp index aa5a45eafbf7..ddd43c08091c 100644 --- a/clang/test/SemaCXX/typo-correction.cpp +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -344,20 +344,20 @@ void zif::nab(int) { namespace TemplateFunction { template -void A(T) { } // expected-note {{'::TemplateFunction::A' declared here}} +void fnA(T) { } // expected-note {{'::TemplateFunction::fnA' declared here}} template -void B(T) { } // expected-note {{'::TemplateFunction::B' declared here}} +void fnB(T) { } // expected-note {{'::TemplateFunction::fnB' declared here}} class Foo { public: - void A(int, int) {} - void B() {} + void fnA(int, int) {} + void fnB() {} }; void test(Foo F, int num) { - F.A(num); // expected-error {{too few arguments to function call, expected 2, have 1; did you mean '::TemplateFunction::A'?}} - F.B(num); // expected-error {{too many arguments to function call, expected 0, have 1; did you mean '::TemplateFunction::B'?}} + F.fnA(num); // expected-error {{too few arguments to function call, expected 2, have 1; did you mean '::TemplateFunction::fnA'?}} + F.fnB(num); // expected-error {{too many arguments to function call, expected 0, have 1; did you mean '::TemplateFunction::fnB'?}} } } namespace using_suggestion_val_dropped_specifier { @@ -537,9 +537,9 @@ namespace no_correct_template_id_to_non_template { namespace PR18852 { void func() { struct foo { - void bar() {} + void barberry() {} }; - bar(); // expected-error-re {{use of undeclared identifier 'bar'{{$}}}} + barberry(); // expected-error-re {{use of undeclared identifier 'barberry'{{$}}}} } class Thread {