From 19fccc52ff2c1da1f93d9317c34769bd9bab8ac8 Mon Sep 17 00:00:00 2001 From: Saar Raz Date: Tue, 17 Mar 2020 01:43:29 +0200 Subject: [PATCH] [Concepts] Fix incorrect control flow when TryAnnotateTypeConstraint annotates an invalid template-id TryAnnotateTypeConstraint could annotate a template-id which doesn't end up being a type-constraint, in which case control flow would incorrectly flow into ParseImplicitInt. Reenter the loop in this case. Enable relevant tests for C++20. This required disabling typo-correction during TryAnnotateTypeConstraint and changing a test case which is broken due to a separate bug (will be reported and handled separately). --- clang/include/clang/Sema/Sema.h | 6 ++++-- clang/lib/Parse/ParseDecl.cpp | 6 ++++++ clang/lib/Parse/ParseTemplate.cpp | 3 ++- clang/lib/Sema/SemaTemplate.cpp | 13 ++++++++----- clang/test/SemaCXX/invalid-member-expr.cpp | 1 + clang/test/SemaCXX/typo-correction.cpp | 5 +++-- .../ms-lookup-template-base-classes.cpp | 1 + 7 files changed, 25 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index fd58c00640b0..121ceb7e5d36 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6986,7 +6986,8 @@ public: QualType ObjectType, bool EnteringContext, bool &MemberOfUnknownSpecialization, SourceLocation TemplateKWLoc = SourceLocation(), - AssumedTemplateKind *ATK = nullptr); + AssumedTemplateKind *ATK = nullptr, + bool Disambiguation = false); TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS, @@ -6995,7 +6996,8 @@ public: ParsedType ObjectType, bool EnteringContext, TemplateTy &Template, - bool &MemberOfUnknownSpecialization); + bool &MemberOfUnknownSpecialization, + bool Disambiguation = false); /// Try to resolve an undeclared template name as a type template. /// diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 6356d82f2d46..09d1732739b8 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3253,6 +3253,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; if (isTypeConstraintAnnotation()) continue; + if (NextToken().is(tok::annot_template_id)) + // Might have been annotated by TryAnnotateTypeConstraint. + continue; // Eat the scope spec so the identifier is current. ConsumeAnnotationToken(); ParsedAttributesWithRange Attrs(AttrFactory); @@ -3406,6 +3409,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; if (isTypeConstraintAnnotation()) continue; + if (Tok.is(tok::annot_template_id)) + // Might have been annotated by TryAnnotateTypeConstraint. + continue; ParsedAttributesWithRange Attrs(AttrFactory); if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) { if (!Attrs.empty()) { diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 53c4829f43f4..0406820f74a3 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -710,7 +710,8 @@ bool Parser::TryAnnotateTypeConstraint() { /*ObjectType=*/ParsedType(), /*EnteringContext=*/false, PossibleConcept, - MemberOfUnknownSpecialization); + MemberOfUnknownSpecialization, + /*Disambiguation=*/true); if (MemberOfUnknownSpecialization || !PossibleConcept || TNK != TNK_Concept_template) { if (SS.isNotEmpty()) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4923d0a6dad2..1ba66d4a976a 100755 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -174,7 +174,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S, ParsedType ObjectTypePtr, bool EnteringContext, TemplateTy &TemplateResult, - bool &MemberOfUnknownSpecialization) { + bool &MemberOfUnknownSpecialization, + bool Disambiguation) { assert(getLangOpts().CPlusPlus && "No template names in C!"); DeclarationName TName; @@ -204,7 +205,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, LookupResult R(*this, TName, Name.getBeginLoc(), LookupOrdinaryName); if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext, MemberOfUnknownSpecialization, SourceLocation(), - &AssumedTemplate)) + &AssumedTemplate, Disambiguation)) return TNK_Non_template; if (AssumedTemplate != AssumedTemplateKind::None) { @@ -371,7 +372,8 @@ bool Sema::LookupTemplateName(LookupResult &Found, bool EnteringContext, bool &MemberOfUnknownSpecialization, SourceLocation TemplateKWLoc, - AssumedTemplateKind *ATK) { + AssumedTemplateKind *ATK, + bool Disambiguation) { if (ATK) *ATK = AssumedTemplateKind::None; @@ -494,8 +496,9 @@ bool Sema::LookupTemplateName(LookupResult &Found, } } - if (Found.empty() && !IsDependent) { - // If we did not find any names, attempt to correct any typos. + if (Found.empty() && !IsDependent && !Disambiguation) { + // If we did not find any names, and this is not a disambiguation, attempt + // to correct any typos. DeclarationName Name = Found.getLookupName(); Found.clear(); // Simple filter callback that, for keywords, only accepts the C++ *_cast diff --git a/clang/test/SemaCXX/invalid-member-expr.cpp b/clang/test/SemaCXX/invalid-member-expr.cpp index 920d92380e69..e0b40794a0ce 100644 --- a/clang/test/SemaCXX/invalid-member-expr.cpp +++ b/clang/test/SemaCXX/invalid-member-expr.cpp @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s class X {}; diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp index 33dea4d36b3e..92a145074e72 100644 --- a/clang/test/SemaCXX/typo-correction.cpp +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fspell-checking-limit 0 -verify -Wno-c++11-extensions %s +// RUN: %clang_cc1 -fspell-checking-limit 0 -verify -Wno-c++11-extensions -std=c++20 %s namespace PR21817{ int a(-rsing[2]); // expected-error {{undeclared identifier 'rsing'; did you mean 'using'?}} @@ -523,8 +524,8 @@ PR18685::BitVector Map; // expected-error-re {{no type named 'BitVector' in nam namespace shadowed_template { template class Fizbin {}; // expected-note {{'::shadowed_template::Fizbin' declared here}} class Baz { - int Fizbin(); - Fizbin qux; // expected-error {{no template named 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} + int Fizbin; + Fizbin qux; // expected-error {{no template named 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} }; } diff --git a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp index a41248ee1b8e..cb497176ff0e 100644 --- a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp +++ b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++20 -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s template