diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1110,8 +1110,9 @@ public: TentativeParseCCC(const Token &Next) { WantRemainingKeywords = false; - WantTypeSpecifiers = Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater, - tok::l_brace, tok::identifier); + WantTypeSpecifiers = + Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater, tok::l_brace, + tok::identifier, tok::comma); } bool ValidateCandidate(const TypoCorrection &Candidate) override { diff --git a/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp --- a/clang/test/Parser/cxx-template-decl.cpp +++ b/clang/test/Parser/cxx-template-decl.cpp @@ -286,17 +286,3 @@ template int b; template auto f() -> b<0>; // expected-error +{{}} } - -namespace NoCrashOnNullNNSTypoCorrection { - -int AddObservation(); // expected-note {{declared here}} - -template // expected-note {{template parameter is declared here}} -class UsingImpl {}; -class AddObservation { - using Using = - UsingImpl; // expected-error {{use of undeclared identifier 'AddObservationFn'; did you mean}} \ - expected-error {{template argument for template type parameter must be a type}} -}; - -} diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp --- a/clang/test/SemaCXX/typo-correction.cpp +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -611,6 +611,41 @@ } } +namespace testIncludeTypeInTemplateArgument { +template +void foo(T t = {}, U = {}); // expected-note {{candidate template ignored}} + +class AddObservation {}; // expected-note {{declared here}} +int bar1() { + // should resolve to a class. + foo(); // expected-error {{unknown type name 'AddObservationFn'; did you mean 'AddObservation'?}} + + // should not resolve to a class. + foo(AddObservationFn, 1); // expected-error-re {{use of undeclared identifier 'AddObservationFn'{{$}}}} + int a = AddObservationFn, b; // expected-error-re {{use of undeclared identifier 'AddObservationFn'{{$}}}} + + int AddObservation; // expected-note 3{{declared here}} + // should resolve to a local variable. + foo(AddObservationFn, 1); // expected-error {{use of undeclared identifier 'AddObservationFn'; did you mean}} + int c = AddObservationFn, d; // expected-error {{use of undeclared identifier 'AddObservationFn'; did you mean}} + + // FIXME: would be nice to not resolve to a variable. + foo(); // expected-error {{use of undeclared identifier 'AddObservationFn'; did you mean}} \ + expected-error {{no matching function for call}} +} +} // namespace testIncludeTypeInTemplateArgument + +namespace testNoCrashOnNullNNSTypoCorrection { +int AddObservation(); +template +class UsingImpl {}; +class AddObservation { // expected-note {{declared here}} + using Using = + // should resolve to a class. + UsingImpl; // expected-error {{unknown type name 'AddObservationFn'; did you mean}} +}; +} // namespace testNoCrashOnNullNNSTypoCorrection + namespace testNonStaticMemberHandling { struct Foo { bool usesMetadata; // expected-note {{'usesMetadata' declared here}}