forked from OSchip/llvm-project
[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).
This commit is contained in:
parent
2a3723ef11
commit
19fccc52ff
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {};
|
||||
|
||||
|
|
|
@ -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 <typename T> class Fizbin {}; // expected-note {{'::shadowed_template::Fizbin' declared here}}
|
||||
class Baz {
|
||||
int Fizbin();
|
||||
Fizbin<int> qux; // expected-error {{no template named 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}}
|
||||
int Fizbin;
|
||||
Fizbin<int> qux; // expected-error {{no template named 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <class T>
|
||||
|
|
Loading…
Reference in New Issue