[clang] [libcxx] [Clang] Implement resolution for CWG1835 (PR #92957)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 4 07:35:48 PDT 2024
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92957
>From 2e4fe34128390910ef440512950dd98d8cafe034 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 21 May 2024 13:15:24 -0400
Subject: [PATCH 01/19] [WIP][Clang] Implement resolution for CWG1835
---
clang/include/clang/Sema/DeclSpec.h | 8 +++
clang/include/clang/Sema/Sema.h | 2 +-
clang/lib/Parse/ParseDeclCXX.cpp | 2 +-
clang/lib/Parse/ParseExpr.cpp | 9 +--
clang/lib/Sema/SemaCXXScopeSpec.cpp | 60 +++++++++++++------
clang/lib/Sema/SemaExprMember.cpp | 10 +---
clang/lib/Sema/SemaPseudoObject.cpp | 16 ++---
clang/lib/Sema/SemaTemplate.cpp | 22 ++++---
clang/lib/Sema/TreeTransform.h | 15 +++++
.../basic.lookup.classref/p1-cxx11.cpp | 16 +++--
.../basic.lookup/basic.lookup.classref/p1.cpp | 16 +++--
.../class.derived/class.member.lookup/p8.cpp | 4 +-
clang/test/CXX/drs/cwg1xx.cpp | 7 ++-
clang/test/SemaCXX/static-assert-cxx17.cpp | 2 +-
.../SemaTemplate/temp_arg_nontype_cxx20.cpp | 2 +-
15 files changed, 127 insertions(+), 64 deletions(-)
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 23bc780e04979..c6d87ca1683a8 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -75,6 +75,7 @@ class CXXScopeSpec {
SourceRange Range;
NestedNameSpecifierLocBuilder Builder;
ArrayRef<TemplateParameterList *> TemplateParamLists;
+ NamedDecl *FoundFirstQualifierInScope;
public:
SourceRange getRange() const { return Range; }
@@ -91,6 +92,13 @@ class CXXScopeSpec {
return TemplateParamLists;
}
+ void setFoundFirstQualifierInScope(NamedDecl *Found) {
+ FoundFirstQualifierInScope = Found;
+ }
+ NamedDecl *getFirstQualifierFoundInScope() const {
+ return FoundFirstQualifierInScope;
+ }
+
/// Retrieve the representation of the nested-name-specifier.
NestedNameSpecifier *getScopeRep() const {
return Builder.getRepresentation();
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7dea2b6826cfd..6c3d1e65e0dfb 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6942,7 +6942,7 @@ class Sema final : public SemaBase {
const TemplateArgumentListInfo *TemplateArgs);
ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
- tok::TokenKind OpKind, CXXScopeSpec &SS,
+ bool IsArrow, CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Member, Decl *ObjCImpDecl);
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 9a4a777f575b2..884e7ea8ee2de 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -720,7 +720,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(
return nullptr;
}
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, /*ParsedType=*/nullptr,
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
/*ObectHasErrors=*/false,
/*EnteringConttext=*/false,
/*MayBePseudoDestructor=*/nullptr,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index eb7447fa038e4..b3c25f88b403d 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2254,6 +2254,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
break;
}
+
ParseOptionalCXXScopeSpecifier(
SS, ObjectType, LHS.get() && LHS.get()->containsErrors(),
/*EnteringContext=*/false, &MayBePseudoDestructor);
@@ -2328,10 +2329,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
- OpKind, SS, TemplateKWLoc, Name,
- CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
- : nullptr);
+ LHS = Actions.ActOnMemberAccessExpr(
+ getCurScope(), LHS.get(), OpLoc, OpKind == tok::arrow, SS,
+ TemplateKWLoc, Name,
+ CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr);
if (!LHS.isInvalid()) {
if (Tok.is(tok::less))
checkPotentialAngleBracket(LHS);
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index c405fbc0aa421..6efa8925d1446 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -397,11 +397,19 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
while (NNS->getPrefix())
NNS = NNS->getPrefix();
- if (NNS->getKind() != NestedNameSpecifier::Identifier)
- return nullptr;
-
- LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(),
- LookupNestedNameSpecifierName);
+ const IdentifierInfo *II = NNS->getAsIdentifier();
+ if (!II) {
+ if (const auto *DTST =
+ dyn_cast_if_present<DependentTemplateSpecializationType>(
+ NNS->getAsType()))
+ II = DTST->getIdentifier();
+ else
+ return nullptr;
+ }
+ assert(II && "Missing first qualifier in scope");
+ LookupResult Found(*this, II, SourceLocation(),
+ NNS->getAsIdentifier() ? LookupNestedNameSpecifierName
+ : LookupOrdinaryName);
LookupName(Found, S);
assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
@@ -409,10 +417,10 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
return nullptr;
NamedDecl *Result = Found.getFoundDecl();
- if (isAcceptableNestedNameSpecifier(Result))
- return Result;
+ // if (isAcceptableNestedNameSpecifier(Result))
+ return Result;
- return nullptr;
+ // return nullptr;
}
namespace {
@@ -493,12 +501,15 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
// x->B::f, and we are looking into the type of the object.
assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist");
LookupCtx = computeDeclContext(ObjectType);
- isDependent = ObjectType->isDependentType();
- } else if (SS.isSet()) {
+ isDependent = !LookupCtx && ObjectType->isDependentType();
+ } else if (SS.isNotEmpty()) {
// This nested-name-specifier occurs after another nested-name-specifier,
// so look into the context associated with the prior nested-name-specifier.
LookupCtx = computeDeclContext(SS, EnteringContext);
- isDependent = isDependentScopeSpecifier(SS);
+ isDependent = !LookupCtx && isDependentScopeSpecifier(SS);
+ // The declaration context must be complete.
+ if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx))
+ return true;
Found.setContextRange(SS.getRange());
}
@@ -509,14 +520,28 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
// expression or the declaration context associated with a prior
// nested-name-specifier.
- // The declaration context must be complete.
- if (!LookupCtx->isDependentContext() &&
- RequireCompleteDeclContext(SS, LookupCtx))
- return true;
-
LookupQualifiedName(Found, LookupCtx);
- if (!ObjectType.isNull() && Found.empty()) {
+ isDependent |= Found.wasNotFoundInCurrentInstantiation();
+ }
+
+ bool LookupFirstQualifierInScope =
+ Found.empty() && !ObjectType.isNull() && !isDependent;
+
+ // FIXME: We should still do the lookup if the object expression is dependent,
+ // but instead of using them we should store them via
+ // setFirstQualifierFoundInScope and pretend we found nothing.
+ if (SS.isEmpty() && (ObjectType.isNull() || LookupFirstQualifierInScope)) {
+ if (S)
+ LookupName(Found, S);
+ else if (LookupFirstQualifierInScope && SS.getFirstQualifierFoundInScope())
+ Found.addDecl(SS.getFirstQualifierFoundInScope());
+
+ if (!ObjectType.isNull())
+ ObjectTypeSearchedInScope = true;
+ }
+#if 0
+ if (!ObjectType.isNull() && Found.empty() && !isDependent) {
// C++ [basic.lookup.classref]p4:
// If the id-expression in a class member access is a qualified-id of
// the form
@@ -548,6 +573,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
// Perform unqualified name lookup in the current scope.
LookupName(Found, S);
}
+#endif
if (Found.isAmbiguous())
return true;
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 3ae1af26d0096..6dbb0b4c398c4 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -1054,7 +1054,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {
CXXScopeSpec TempSS(SS);
RetryExpr = ActOnMemberAccessExpr(
- ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,
+ ExtraArgs->S, RetryExpr.get(), OpLoc, /*IsArrow=*/true, TempSS,
TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);
}
if (Trap.hasErrorOccurred())
@@ -1768,12 +1768,10 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
/// decl; this is an ugly hack around the fact that Objective-C
/// \@implementations aren't properly put in the context chain
ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
+ SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
- UnqualifiedId &Id,
- Decl *ObjCImpDecl) {
+ UnqualifiedId &Id, Decl *ObjCImpDecl) {
if (SS.isSet() && SS.isInvalid())
return ExprError();
@@ -1791,8 +1789,6 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
DecomposeUnqualifiedId(Id, TemplateArgsBuffer,
NameInfo, TemplateArgs);
- bool IsArrow = (OpKind == tok::arrow);
-
if (getLangOpts().HLSL && IsArrow)
return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2);
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index fdb584ceb8105..86c303e67bc1d 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -1395,10 +1395,10 @@ ExprResult MSPropertyOpBuilder::buildGet() {
GetterName.setIdentifier(II, RefExpr->getMemberLoc());
CXXScopeSpec SS;
SS.Adopt(RefExpr->getQualifierLoc());
- ExprResult GetterExpr =
- S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
- RefExpr->isArrow() ? tok::arrow : tok::period, SS,
- SourceLocation(), GetterName, nullptr);
+ ExprResult GetterExpr = S.ActOnMemberAccessExpr(
+ S.getCurScope(), InstanceBase, /*OpLoc=*/SourceLocation(),
+ RefExpr->isArrow(), SS, /*TemplateKWLoc=*/SourceLocation(), GetterName,
+ /*ObjCImpDecl=*/nullptr);
if (GetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::err_cannot_find_suitable_accessor) << 0 /* getter */
@@ -1424,10 +1424,10 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
SetterName.setIdentifier(II, RefExpr->getMemberLoc());
CXXScopeSpec SS;
SS.Adopt(RefExpr->getQualifierLoc());
- ExprResult SetterExpr =
- S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
- RefExpr->isArrow() ? tok::arrow : tok::period, SS,
- SourceLocation(), SetterName, nullptr);
+ ExprResult SetterExpr = S.ActOnMemberAccessExpr(
+ S.getCurScope(), InstanceBase, /*OpLoc=*/SourceLocation(),
+ RefExpr->isArrow(), SS, /*TemplateKWLoc=*/SourceLocation(), SetterName,
+ /*ObjCImpDecl=*/nullptr);
if (SetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::err_cannot_find_suitable_accessor) << 1 /* setter */
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 40a759ea330de..6fc290e382b0f 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -214,6 +214,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
&AssumedTemplate,
/*AllowTypoCorrection=*/!Disambiguation))
return TNK_Non_template;
+
MemberOfUnknownSpecialization = R.wasNotFoundInCurrentInstantiation();
if (AssumedTemplate != AssumedTemplateKind::None) {
@@ -433,7 +434,6 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
}
bool ObjectTypeSearchedInScope = false;
- bool AllowFunctionTemplatesInLookup = true;
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
// computed, which is either the type of the base of a member access
@@ -452,7 +452,14 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
IsDependent |= Found.wasNotFoundInCurrentInstantiation();
}
- if (SS.isEmpty() && (ObjectType.isNull() || Found.empty())) {
+ bool LookupFirstQualifierInScope =
+ Found.getLookupKind() != LookupMemberName && Found.empty() &&
+ !ObjectType.isNull() && !IsDependent;
+
+ // FIXME: We should still do the lookup if the object expression is dependent,
+ // but instead of using them we should store them via
+ // setFirstQualifierFoundInScope and pretend we found nothing.
+ if (SS.isEmpty() && (ObjectType.isNull() || LookupFirstQualifierInScope)) {
// C++ [basic.lookup.classref]p1:
// In a class member access expression (5.2.5), if the . or -> token is
// immediately followed by an identifier followed by a <, the
@@ -464,14 +471,11 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
// template.
if (S)
LookupName(Found, S);
+ else if (LookupFirstQualifierInScope && SS.getFirstQualifierFoundInScope())
+ Found.addDecl(SS.getFirstQualifierFoundInScope());
- if (!ObjectType.isNull()) {
- // FIXME: We should filter out all non-type templates here, particularly
- // variable templates and concepts. But the exclusion of alias templates
- // and template template parameters is a wording defect.
- AllowFunctionTemplatesInLookup = false;
+ if (!ObjectType.isNull())
ObjectTypeSearchedInScope = true;
- }
IsDependent |= Found.wasNotFoundInCurrentInstantiation();
}
@@ -542,7 +546,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
NamedDecl *ExampleLookupResult =
Found.empty() ? nullptr : Found.getRepresentativeDecl();
- FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup);
+ FilterAcceptableTemplateNames(Found);
if (Found.empty()) {
if (IsDependent) {
Found.setNotFoundInCurrentInstantiation();
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index efba99b85b0fb..c037f93bbbc3f 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2894,6 +2894,8 @@ class TreeTransform {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
+ if (FirstQualifierInScope)
+ SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
Base = BaseResult.get();
QualType BaseType = Base->getType();
@@ -3582,6 +3584,9 @@ class TreeTransform {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
+ if (FirstQualifierInScope)
+ SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
+
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
SS, TemplateKWLoc,
@@ -3605,6 +3610,9 @@ class TreeTransform {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
+ if (FirstQualifierInScope)
+ SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
+
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
SS, TemplateKWLoc,
@@ -4383,6 +4391,8 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
insertNNS(NNS);
CXXScopeSpec SS;
+ if (FirstQualifierInScope)
+ SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
while (!Qualifiers.empty()) {
NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier();
@@ -5180,6 +5190,9 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
TypeLocBuilder TLB;
QualType Result;
+ if (UnqualLookup)
+ SS.setFoundFirstQualifierInScope(UnqualLookup);
+
if (isa<TemplateSpecializationType>(T)) {
TemplateSpecializationTypeLoc SpecTL =
TL.castAs<TemplateSpecializationTypeLoc>();
@@ -16173,6 +16186,8 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
+ if (FirstQualifierInScope)
+ SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
getSema().ActOnTemplateName(/*Scope=*/nullptr, SS, TemplateKWLoc,
TemplateName, ParsedType::make(ObjectType),
/*EnteringContext=*/false, Template,
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1-cxx11.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1-cxx11.cpp
index 1afea99e8895c..476745537f691 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1-cxx11.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1-cxx11.cpp
@@ -55,15 +55,21 @@ namespace PR11856 {
template<typename T> T *end(T*);
- class X { };
+ struct X { };
+ struct Y {
+ int end;
+ };
template <typename T>
void Foo2() {
T it1;
- if (it1->end < it1->end) {
- }
+ if (it1->end < it1->end) { }
X *x;
- if (x->end < 7) { // expected-error{{no member named 'end' in 'PR11856::X'}}
- }
+ if (x->end < 7) { } // expected-error{{expected '>'}}
+ // expected-note at -1{{to match this '<'}}
+ // expected-error at -2{{expected unqualified-id}}
+
+ Y *y;
+ if (y->end < 7) { }
}
}
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
index e3599db18350b..cabf3f73830bc 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
@@ -86,15 +86,21 @@ namespace PR11856 {
template<typename T> T *end(T*);
- class X { };
+ struct X { };
+ struct Y {
+ int end;
+ };
template <typename T>
void Foo2() {
T it1;
- if (it1->end < it1->end) {
- }
+ if (it1->end < it1->end) { }
X *x;
- if (x->end < 7) { // expected-error{{no member named 'end' in 'PR11856::X'}}
- }
+ if (x->end < 7) { } // expected-error{{expected '>'}}
+ // expected-note at -1{{to match this '<'}}
+ // expected-error at -2{{expected unqualified-id}}
+
+ Y *y;
+ if (y->end < 7) { }
}
}
diff --git a/clang/test/CXX/class.derived/class.member.lookup/p8.cpp b/clang/test/CXX/class.derived/class.member.lookup/p8.cpp
index 78e83c0ab4566..e9a57f739cc35 100644
--- a/clang/test/CXX/class.derived/class.member.lookup/p8.cpp
+++ b/clang/test/CXX/class.derived/class.member.lookup/p8.cpp
@@ -47,8 +47,8 @@ template<typename T>
void DerivedT<T>::Inner() {
Derived1T<T>::Foo();
Derived2T<T>::Member = 42;
- this->Derived1T<T>::Foo();
- this->Derived2T<T>::Member = 42;
+ this->Derived1T<T>::Foo(); // expected-error{{use 'template' keyword to treat 'Derived1T' as a dependent template name}}
+ this->Derived2T<T>::Member = 42; // expected-error{{use 'template' keyword to treat 'Derived2T' as a dependent template name}}
this->Foo(); // expected-error{{non-static member 'Foo' found in multiple base-class subobjects of type 'BaseT<int>'}}
}
diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp
index b39cc21fa4917..ea38bff0d8d34 100644
--- a/clang/test/CXX/drs/cwg1xx.cpp
+++ b/clang/test/CXX/drs/cwg1xx.cpp
@@ -618,7 +618,6 @@ namespace cwg141 { // cwg141: 3.1
// FIXME: we issue a useful diagnostic first, then some bogus ones.
b.f<int>();
// expected-error at -1 {{no member named 'f' in 'cwg141::B'}}
- // expected-error at -2 +{{}}
(void)b.S<int>::n;
}
template<typename T> struct C {
@@ -628,10 +627,12 @@ namespace cwg141 { // cwg141: 3.1
// expected-error at -1 {{use 'template' keyword to treat 'f' as a dependent template name}}
}
void h() {
- (void)t.S<int>::n; // ok
+ (void)t.S<int>::n;
+ // expected-error at -1 {{use 'template' keyword to treat 'S' as a dependent template name}}
}
void i() {
- (void)t.S<int>(); // ok!
+ (void)t.S<int>();
+ // expected-error at -1 {{use 'template' keyword to treat 'S' as a dependent template name}}
}
};
void h() { C<B>().h(); } // ok
diff --git a/clang/test/SemaCXX/static-assert-cxx17.cpp b/clang/test/SemaCXX/static-assert-cxx17.cpp
index 41a7b025d0eb7..754f4ae5f1d38 100644
--- a/clang/test/SemaCXX/static-assert-cxx17.cpp
+++ b/clang/test/SemaCXX/static-assert-cxx17.cpp
@@ -96,7 +96,7 @@ void foo6() {
// expected-error at -1{{static assertion failed due to requirement 'static_cast<const X<int> *>(nullptr)'}}
static_assert((const X<typename T::T>[]){} == nullptr);
// expected-error at -1{{static assertion failed due to requirement '(const X<int>[0]){} == nullptr'}}
- static_assert(sizeof(X<decltype(X<typename T::T>().X<typename T::T>::~X())>) == 0);
+ static_assert(sizeof(X<decltype(X<typename T::T>().template X<typename T::T>::~X())>) == 0);
// expected-error at -1{{static assertion failed due to requirement 'sizeof(X<void>) == 0'}} \
// expected-note at -1 {{evaluates to '8 == 0'}}
static_assert(constexpr_return_false<typename T::T, typename T::U>());
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
index ad73daa8e214c..7768d2f03ac5b 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp
@@ -115,7 +115,7 @@ namespace CopyCounting {
static_assert(f(X<A{}>()) == 0);
template<A a> struct Y { void f(); };
- template<A a> void g(Y<a> y) { y.Y<a>::f(); }
+ template<A a> void g(Y<a> y) { y.template Y<a>::f(); }
void h() { constexpr A a; g<a>(Y<a>{}); }
template<A a> struct Z {
>From 9e0b8dc456d5132183028d02d5fe05481a8f5e20 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 21 May 2024 15:57:06 -0400
Subject: [PATCH 02/19] [FOLD] add comment
---
clang/lib/Sema/SemaCXXScopeSpec.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 6efa8925d1446..f70ba1ecfa17c 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -397,6 +397,8 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
while (NNS->getPrefix())
NNS = NNS->getPrefix();
+ // FIXME: This is a rather nasty hack! Ideally we should get the results
+ // from LookupTemplateName/BuildCXXNestedNameSpecifier.
const IdentifierInfo *II = NNS->getAsIdentifier();
if (!II) {
if (const auto *DTST =
>From f2dbd87e48c9aafb1935df2ea439ebe518a66090 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 31 May 2024 12:59:34 -0400
Subject: [PATCH 03/19] [FOLD] store all results found by unqualified lookup
for the first component name of a member-qualified nested-name-specifier
---
clang/include/clang/AST/ExprCXX.h | 83 +++++++++----
clang/include/clang/AST/Stmt.h | 13 +-
clang/include/clang/AST/UnresolvedSet.h | 4 +
clang/include/clang/Sema/DeclSpec.h | 10 +-
clang/include/clang/Sema/Lookup.h | 8 +-
clang/include/clang/Sema/Sema.h | 10 +-
clang/lib/AST/ASTImporter.cpp | 13 +-
clang/lib/AST/ExprCXX.cpp | 65 ++++++----
clang/lib/AST/ItaniumMangle.cpp | 10 +-
clang/lib/Sema/SemaCXXScopeSpec.cpp | 41 ++++---
clang/lib/Sema/SemaCoroutine.cpp | 2 +-
clang/lib/Sema/SemaDeclCXX.cpp | 22 ++--
clang/lib/Sema/SemaExpr.cpp | 2 +-
clang/lib/Sema/SemaExprMember.cpp | 37 +++---
clang/lib/Sema/SemaOverload.cpp | 3 +-
clang/lib/Sema/SemaStmtAsm.cpp | 7 +-
clang/lib/Sema/SemaTemplate.cpp | 11 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 5 +-
clang/lib/Sema/TreeTransform.h | 132 +++++++++------------
clang/lib/Serialization/ASTReaderStmt.cpp | 51 +++++++-
clang/lib/Serialization/ASTWriterStmt.cpp | 38 ++++++
clang/test/SemaCXX/pseudo-destructors.cpp | 18 +--
22 files changed, 359 insertions(+), 226 deletions(-)
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index dbf693611a7fa..3e4d673590b71 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -3672,8 +3672,10 @@ class CXXUnresolvedConstructExpr final
class CXXDependentScopeMemberExpr final
: public Expr,
private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
+ NestedNameSpecifierLoc,
+ DeclAccessPair,
ASTTemplateKWAndArgsInfo,
- TemplateArgumentLoc, NamedDecl *> {
+ TemplateArgumentLoc> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend TrailingObjects;
@@ -3686,17 +3688,15 @@ class CXXDependentScopeMemberExpr final
/// implicit accesses.
QualType BaseType;
- /// The nested-name-specifier that precedes the member name, if any.
- /// FIXME: This could be in principle store as a trailing object.
- /// However the performance impact of doing so should be investigated first.
- NestedNameSpecifierLoc QualifierLoc;
-
/// The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor.
///
/// FIXME: could also be a template-id
DeclarationNameInfo MemberNameInfo;
+ /// The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+
// CXXDependentScopeMemberExpr is followed by several trailing objects,
// some of which optional. They are in order:
//
@@ -3716,8 +3716,16 @@ class CXXDependentScopeMemberExpr final
return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo;
}
- bool hasFirstQualifierFoundInScope() const {
- return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope;
+ unsigned getNumUnqualifiedLookups() const {
+ return CXXDependentScopeMemberExprBits.NumUnqualifiedLookups;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const {
+ return hasQualifier();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const {
+ return getNumUnqualifiedLookups();
}
unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const {
@@ -3728,33 +3736,35 @@ class CXXDependentScopeMemberExpr final
return getNumTemplateArgs();
}
- unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const {
- return hasFirstQualifierFoundInScope();
- }
-
CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base,
QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierFoundInScope,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
- CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
- bool HasFirstQualifierFoundInScope);
+ CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasQualifier,
+ unsigned NumUnqualifiedLookups,
+ bool HasTemplateKWAndArgsInfo);
public:
static CXXDependentScopeMemberExpr *
- Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
- SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
+ Create(const ASTContext &Ctx, Expr *Base,
+ QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr *
- CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
- unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope);
+ CreateEmpty(const ASTContext &Ctx, bool HasQualifier,
+ unsigned NumUnqualifiedLookups,
+ bool HasTemplateKWAndArgsInfo,
+ unsigned NumTemplateArgs);
/// True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
@@ -3780,18 +3790,32 @@ class CXXDependentScopeMemberExpr final
/// Retrieve the location of the '->' or '.' operator.
SourceLocation getOperatorLoc() const {
- return CXXDependentScopeMemberExprBits.OperatorLoc;
+ return OperatorLoc;
+ }
+
+ /// Determines whether this member expression had a nested-name-specifier
+ /// prior to the name of the member, e.g., x->Base::foo.
+ bool hasQualifier() const {
+ return CXXDependentScopeMemberExprBits.HasQualifier;
}
- /// Retrieve the nested-name-specifier that qualifies the member name.
+ /// If the member name was qualified, retrieves the nested-name-specifier
+ /// that precedes the member name, with source-location information.
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ if (!hasQualifier())
+ return NestedNameSpecifierLoc();
+ return *getTrailingObjects<NestedNameSpecifierLoc>();
+ }
+
+ /// If the member name was qualified, retrieves the
+ /// nested-name-specifier that precedes the member name. Otherwise, returns
+ /// NULL.
NestedNameSpecifier *getQualifier() const {
- return QualifierLoc.getNestedNameSpecifier();
+ return getQualifierLoc().getNestedNameSpecifier();
}
- /// Retrieve the nested-name-specifier that qualifies the member
- /// name, with source location information.
- NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
+ #if 0
/// Retrieve the first part of the nested-name-specifier that was
/// found in the scope of the member access expression when the member access
/// was initially parsed.
@@ -3808,6 +3832,13 @@ class CXXDependentScopeMemberExpr final
return nullptr;
return *getTrailingObjects<NamedDecl *>();
}
+ #endif
+
+ ArrayRef<DeclAccessPair> unqualified_lookups() const {
+ if (!getNumUnqualifiedLookups())
+ return std::nullopt;
+ return {getTrailingObjects<DeclAccessPair>(), getNumUnqualifiedLookups()};
+ }
/// Retrieve the name of the member that this expression refers to.
const DeclarationNameInfo &getMemberNameInfo() const {
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 9cd7a364cd3f1..e0e5c8fb99dc3 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -1020,18 +1020,25 @@ class alignas(void *) Stmt {
LLVM_PREFERRED_TYPE(bool)
unsigned IsArrow : 1;
+ /// True if this member expression used a nested-name-specifier to
+ /// refer to the member, e.g., "x->Base::f".
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned HasQualifier : 1;
+
/// Whether this member expression has info for explicit template
/// keyword and arguments.
LLVM_PREFERRED_TYPE(bool)
unsigned HasTemplateKWAndArgsInfo : 1;
+ #if 0
/// See getFirstQualifierFoundInScope() and the comment listing
/// the trailing objects.
LLVM_PREFERRED_TYPE(bool)
unsigned HasFirstQualifierFoundInScope : 1;
-
- /// The location of the '->' or '.' operator.
- SourceLocation OperatorLoc;
+ #endif
+ /// Number of declarations found by unqualified lookup for the
+ /// first component name of the nested-name-specifier.
+ unsigned NumUnqualifiedLookups;
};
class OverloadExprBitfields {
diff --git a/clang/include/clang/AST/UnresolvedSet.h b/clang/include/clang/AST/UnresolvedSet.h
index ee31be969b6e3..e2083e2a0bd24 100644
--- a/clang/include/clang/AST/UnresolvedSet.h
+++ b/clang/include/clang/AST/UnresolvedSet.h
@@ -96,6 +96,10 @@ class UnresolvedSetImpl {
decls().push_back(DeclAccessPair::make(D, AS));
}
+ void addAllDecls(ArrayRef<DeclAccessPair> Other) {
+ append(iterator(Other.begin()), iterator(Other.end()));
+ }
+
/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index c6d87ca1683a8..231f3fc6fec83 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -75,7 +75,7 @@ class CXXScopeSpec {
SourceRange Range;
NestedNameSpecifierLocBuilder Builder;
ArrayRef<TemplateParameterList *> TemplateParamLists;
- NamedDecl *FoundFirstQualifierInScope;
+ ArrayRef<DeclAccessPair> UnqualifiedLookups;
public:
SourceRange getRange() const { return Range; }
@@ -92,11 +92,11 @@ class CXXScopeSpec {
return TemplateParamLists;
}
- void setFoundFirstQualifierInScope(NamedDecl *Found) {
- FoundFirstQualifierInScope = Found;
+ void setUnqualifiedLookups(ArrayRef<DeclAccessPair> Found) {
+ UnqualifiedLookups = Found;
}
- NamedDecl *getFirstQualifierFoundInScope() const {
- return FoundFirstQualifierInScope;
+ ArrayRef<DeclAccessPair> getUnqualifiedLookups() const {
+ return UnqualifiedLookups;
}
/// Retrieve the representation of the nested-name-specifier.
diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h
index b0a08a05ac6a0..6b765ef3c980f 100644
--- a/clang/include/clang/Sema/Lookup.h
+++ b/clang/include/clang/Sema/Lookup.h
@@ -483,11 +483,15 @@ class LookupResult {
ResultKind = Found;
}
+ void addAllDecls(ArrayRef<DeclAccessPair> Other) {
+ Decls.addAllDecls(Other);
+ ResultKind = Found;
+ }
+
/// Add all the declarations from another set of lookup
/// results.
void addAllDecls(const LookupResult &Other) {
- Decls.append(Other.Decls.begin(), Other.Decls.end());
- ResultKind = Found;
+ addAllDecls(Other.Decls.pairs());
}
/// Determine whether no result was found because we could not
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 6c3d1e65e0dfb..9fab8d13a1c35 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2390,7 +2390,7 @@ class Sema final : public SemaBase {
bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
bool *CanCorrect = nullptr);
- NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+ bool LookupFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS, UnresolvedSetImpl &R);
/// Keeps information about an identifier in a nested-name-spec.
///
@@ -2423,7 +2423,6 @@ class Sema final : public SemaBase {
bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
bool EnteringContext, CXXScopeSpec &SS,
- NamedDecl *ScopeLookupResult,
bool ErrorRecoveryLookup,
bool *IsCorrectedToColon = nullptr,
bool OnlyNamespace = false);
@@ -6938,7 +6937,7 @@ class Sema final : public SemaBase {
ExprResult ActOnDependentMemberExpr(
Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OpLoc,
const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs);
ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
@@ -6973,15 +6972,14 @@ class Sema final : public SemaBase {
ExprResult BuildMemberReferenceExpr(
Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
ExprResult
BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc,
bool IsArrow, const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope, LookupResult &R,
+ SourceLocation TemplateKWLoc, LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
const Scope *S, bool SuppressQualifierCheck = false,
ActOnMemberAccessExtraArgs *ExtraArgs = nullptr);
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index cab5ee6047956..6c306418fe071 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -8432,8 +8432,15 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
auto ToOperatorLoc = importChecked(Err, E->getOperatorLoc());
auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
- auto ToFirstQualifierFoundInScope =
- importChecked(Err, E->getFirstQualifierFoundInScope());
+
+
+ UnresolvedSet<8> ToUnqualifiedLookups;
+ for (auto D : E->unqualified_lookups())
+ if (auto ToDOrErr = import(D.getDecl()))
+ ToUnqualifiedLookups.addDecl(*ToDOrErr);
+ else
+ return ToDOrErr.takeError();
+
if (Err)
return std::move(Err);
@@ -8467,7 +8474,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
return CXXDependentScopeMemberExpr::Create(
Importer.getToContext(), ToBase, ToType, E->isArrow(), ToOperatorLoc,
- ToQualifierLoc, ToTemplateKeywordLoc, ToFirstQualifierFoundInScope,
+ ToQualifierLoc, ToTemplateKeywordLoc, ToUnqualifiedLookups.pairs(),
ToMemberNameInfo, ResInfo);
}
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 2abc0acbfde3b..87e33564ca02e 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1442,19 +1442,27 @@ SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
+ SourceLocation TemplateKWLoc, ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
OK_Ordinary),
- Base(Base), BaseType(BaseType), QualifierLoc(QualifierLoc),
+ Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc),
MemberNameInfo(MemberNameInfo) {
CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
+ CXXDependentScopeMemberExprBits.HasQualifier =
+ QualifierLoc.hasQualifier();
+ CXXDependentScopeMemberExprBits.NumUnqualifiedLookups =
+ UnqualifiedLookups.size();
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
- CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
- FirstQualifierFoundInScope != nullptr;
- CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
+
+ if (hasQualifier())
+ new (getTrailingObjects<NestedNameSpecifierLoc>())
+ NestedNameSpecifierLoc(QualifierLoc);
+
+ std::uninitialized_copy_n(UnqualifiedLookups.data(),
+ UnqualifiedLookups.size(), getTrailingObjects<DeclAccessPair>());
if (TemplateArgs) {
auto Deps = TemplateArgumentDependence::None;
@@ -1466,54 +1474,61 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
TemplateKWLoc);
}
- if (hasFirstQualifierFoundInScope())
- *getTrailingObjects<NamedDecl *>() = FirstQualifierFoundInScope;
setDependence(computeDependence(this));
}
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
- EmptyShell Empty, bool HasTemplateKWAndArgsInfo,
- bool HasFirstQualifierFoundInScope)
+ EmptyShell Empty, bool HasQualifier, unsigned NumUnqualifiedLookups,
+ bool HasTemplateKWAndArgsInfo)
: Expr(CXXDependentScopeMemberExprClass, Empty) {
+ CXXDependentScopeMemberExprBits.HasQualifier = HasQualifier;
+ CXXDependentScopeMemberExprBits.NumUnqualifiedLookups =
+ NumUnqualifiedLookups;
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
HasTemplateKWAndArgsInfo;
- CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope =
- HasFirstQualifierFoundInScope;
}
CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::Create(
const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope,
+ SourceLocation TemplateKWLoc, ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
+ bool HasQualifier = QualifierLoc.hasQualifier();
+ unsigned NumUnqualifiedLookups = UnqualifiedLookups.size();
+ assert(!NumUnqualifiedLookups || HasQualifier);
bool HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
- bool HasFirstQualifierFoundInScope = FirstQualifierFoundInScope != nullptr;
-
- unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
- TemplateArgumentLoc, NamedDecl *>(
- HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
+ unsigned Size = totalSizeToAlloc<NestedNameSpecifierLoc,
+ DeclAccessPair,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(
+ HasQualifier, NumUnqualifiedLookups,
+ HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(
Ctx, Base, BaseType, IsArrow, OperatorLoc, QualifierLoc, TemplateKWLoc,
- FirstQualifierFoundInScope, MemberNameInfo, TemplateArgs);
+ UnqualifiedLookups, MemberNameInfo, TemplateArgs);
}
CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
- const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo,
- unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope) {
- assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
+ const ASTContext &Ctx, bool HasQualifier, unsigned NumUnqualifiedLookups,
+ bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs) {
+ assert(!NumTemplateArgs || HasTemplateKWAndArgsInfo);
+ assert(!NumUnqualifiedLookups || HasQualifier);
- unsigned Size = totalSizeToAlloc<ASTTemplateKWAndArgsInfo,
- TemplateArgumentLoc, NamedDecl *>(
- HasTemplateKWAndArgsInfo, NumTemplateArgs, HasFirstQualifierFoundInScope);
+ unsigned Size = totalSizeToAlloc<NestedNameSpecifierLoc,
+ DeclAccessPair,
+ ASTTemplateKWAndArgsInfo,
+ TemplateArgumentLoc>(
+ HasQualifier, NumUnqualifiedLookups,
+ HasTemplateKWAndArgsInfo, NumTemplateArgs);
void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(
- EmptyShell(), HasTemplateKWAndArgsInfo, HasFirstQualifierFoundInScope);
+ EmptyShell(), HasQualifier, NumUnqualifiedLookups, HasTemplateKWAndArgsInfo);
}
CXXThisExpr *CXXThisExpr::Create(const ASTContext &Ctx, SourceLocation L,
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index ed9e6eeb36c75..43c046a46ade3 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -595,7 +595,7 @@ class CXXNameMangler {
void mangleMemberExprBase(const Expr *base, bool isArrow);
void mangleMemberExpr(const Expr *base, bool isArrow,
NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationName name,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
@@ -4494,7 +4494,7 @@ void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
void CXXNameMangler::mangleMemberExpr(const Expr *base,
bool isArrow,
NestedNameSpecifier *qualifier,
- NamedDecl *firstQualifierLookup,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationName member,
const TemplateArgumentLoc *TemplateArgs,
unsigned NumTemplateArgs,
@@ -4980,7 +4980,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
NotPrimaryExpr();
const MemberExpr *ME = cast<MemberExpr>(E);
mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), nullptr,
+ ME->getQualifier(), std::nullopt,
ME->getMemberDecl()->getDeclName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
@@ -4991,7 +4991,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
NotPrimaryExpr();
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
- ME->isArrow(), ME->getQualifier(), nullptr,
+ ME->isArrow(), ME->getQualifier(), std::nullopt,
ME->getMemberName(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
@@ -5004,7 +5004,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(),
- ME->getFirstQualifierFoundInScope(),
+ ME->unqualified_lookups(),
ME->getMember(),
ME->getTemplateArgs(), ME->getNumTemplateArgs(),
Arity);
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index f70ba1ecfa17c..99c5476392fc9 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -390,9 +390,9 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
/// (e.g., Base::), perform name lookup for that identifier as a
/// nested-name-specifier within the given scope, and return the result of that
/// name lookup.
-NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
- if (!S || !NNS)
- return nullptr;
+bool Sema::LookupFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS, UnresolvedSetImpl &R) {
+ if (!S)
+ return false;
while (NNS->getPrefix())
NNS = NNS->getPrefix();
@@ -406,23 +406,20 @@ NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) {
NNS->getAsType()))
II = DTST->getIdentifier();
else
- return nullptr;
+ return false;
}
assert(II && "Missing first qualifier in scope");
LookupResult Found(*this, II, SourceLocation(),
NNS->getAsIdentifier() ? LookupNestedNameSpecifierName
: LookupOrdinaryName);
LookupName(Found, S);
- assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet");
-
- if (!Found.isSingleResult())
- return nullptr;
- NamedDecl *Result = Found.getFoundDecl();
- // if (isAcceptableNestedNameSpecifier(Result))
- return Result;
+ if (Found.empty())
+ return false;
- // return nullptr;
+ R.addAllDecls(Found.asUnresolvedSet().pairs());
+ Found.suppressDiagnostics();
+ return true;
}
namespace {
@@ -482,7 +479,6 @@ class NestedNameSpecifierValidatorCCC final
/// specifier.
bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
bool EnteringContext, CXXScopeSpec &SS,
- NamedDecl *ScopeLookupResult,
bool ErrorRecoveryLookup,
bool *IsCorrectedToColon,
bool OnlyNamespace) {
@@ -534,10 +530,13 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
// but instead of using them we should store them via
// setFirstQualifierFoundInScope and pretend we found nothing.
if (SS.isEmpty() && (ObjectType.isNull() || LookupFirstQualifierInScope)) {
- if (S)
+ if (S) {
LookupName(Found, S);
- else if (LookupFirstQualifierInScope && SS.getFirstQualifierFoundInScope())
- Found.addDecl(SS.getFirstQualifierFoundInScope());
+ } else if (LookupFirstQualifierInScope &&
+ !SS.getUnqualifiedLookups().empty()) {
+ Found.addAllDecls(SS.getUnqualifiedLookups());
+ Found.resolveKind();
+ }
if (!ObjectType.isNull())
ObjectTypeSearchedInScope = true;
@@ -687,14 +686,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
// scope, reconstruct the result from the template instantiation itself.
//
// Note that C++11 does *not* perform this redundant lookup.
- NamedDecl *OuterDecl;
+ NamedDecl *OuterDecl = nullptr;
if (S) {
LookupResult FoundOuter(*this, IdInfo.Identifier, IdInfo.IdentifierLoc,
LookupNestedNameSpecifierName);
LookupName(FoundOuter, S);
OuterDecl = FoundOuter.getAsSingle<NamedDecl>();
- } else
- OuterDecl = ScopeLookupResult;
+ } else if (!SS.getUnqualifiedLookups().empty())
+ OuterDecl = SS.getUnqualifiedLookups().front().getDecl();
if (isAcceptableNestedNameSpecifier(OuterDecl) &&
OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() &&
@@ -872,7 +871,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
return true;
return BuildCXXNestedNameSpecifier(S, IdInfo, EnteringContext, SS,
- /*ScopeLookupResult=*/nullptr, false,
+ /*ErrorRecoveryLookup=*/false,
IsCorrectedToColon, OnlyNamespace);
}
@@ -939,7 +938,7 @@ bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
return false;
return !BuildCXXNestedNameSpecifier(S, IdInfo, EnteringContext, SS,
- /*ScopeLookupResult=*/nullptr, true);
+ /*ErrorRecoveryLookup=*/true);
}
bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 81334c817b2af..dbe0f0cf11b90 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -307,7 +307,7 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
CXXScopeSpec SS;
ExprResult Result = S.BuildMemberReferenceExpr(
Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
- SourceLocation(), nullptr, NameInfo, /*TemplateArgs=*/nullptr,
+ SourceLocation(), NameInfo, /*TemplateArgs=*/nullptr,
/*Scope=*/nullptr);
if (Result.isInvalid())
return ExprError();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 631fd4e354927..29ff6e2501b5b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1293,9 +1293,11 @@ static bool checkTupleLikeDecomposition(Sema &S,
if (UseMemberGet) {
// if [lookup of member get] finds at least one declaration, the
// initializer is e.get<i-1>().
- E = S.BuildMemberReferenceExpr(E.get(), DecompType, Loc, false,
- CXXScopeSpec(), SourceLocation(), nullptr,
- MemberGet, &Args, nullptr);
+ E = S.BuildMemberReferenceExpr(E.get(), DecompType, Loc,
+ /*IsArrow=*/false,
+ /*SS=*/CXXScopeSpec(),
+ /*TemplateKWLoc=*/SourceLocation(),
+ MemberGet, &Args, /*S=*/nullptr);
if (E.isInvalid())
return true;
@@ -5016,10 +5018,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
/*IsArrow=*/false,
SS,
/*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/nullptr,
MemberLookup,
/*TemplateArgs=*/nullptr,
- /*S*/nullptr);
+ /*S=*/nullptr);
if (CtorArg.isInvalid())
return true;
@@ -14543,8 +14544,9 @@ class MemberBuilder: public ExprBuilder {
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
- Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(),
- nullptr, MemberLookup, nullptr, nullptr).get());
+ Builder.build(S, Loc), Type, Loc, IsArrow, SS,
+ /*TemplateKwLoc=*/SourceLocation(), MemberLookup,
+ /*TemplateArgs=*/nullptr, /*S=*/nullptr).get());
}
MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
@@ -14753,7 +14755,6 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
ExprResult OpEqualRef
= S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*IsArrow=*/false,
SS, /*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/nullptr,
OpLookup,
/*TemplateArgs=*/nullptr, /*S*/nullptr,
/*SuppressQualifierCheck=*/true);
@@ -17390,8 +17391,9 @@ bool Sema::EvaluateStaticAssertMessageAsString(Expr *Message,
auto BuildExpr = [&](LookupResult &LR) {
ExprResult Res = BuildMemberReferenceExpr(
- Message, Message->getType(), Message->getBeginLoc(), false,
- CXXScopeSpec(), SourceLocation(), nullptr, LR, nullptr, nullptr);
+ Message, Message->getType(), Message->getBeginLoc(), /*IsArrow=*/false,
+ /*SS=*/CXXScopeSpec(), /*TemplateKWLoc=*/SourceLocation(), LR,
+ /*TemplateArgs=*/nullptr, /*S=*/nullptr);
if (Res.isInvalid())
return ExprError();
Res = BuildCallExpr(nullptr, Res.get(), Loc, std::nullopt, Loc, nullptr,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index fb4154757775b..fc8a05ef71b45 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -2677,7 +2677,7 @@ recoverFromMSUnqualifiedLookup(Sema &S, ASTContext &Context,
return CXXDependentScopeMemberExpr::Create(
Context, /*This=*/nullptr, ThisType, /*IsArrow=*/true,
/*Op=*/SourceLocation(), NestedNameSpecifierLoc(), TemplateKWLoc,
- /*FirstQualifierFoundInScope=*/nullptr, NameInfo, TemplateArgs);
+ /*UnqualifiedLookups=*/std::nullopt, NameInfo, TemplateArgs);
}
// Synthesize a fake NNS that points to the derived class. This will
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 6dbb0b4c398c4..5efa5d0d1421e 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -557,7 +557,6 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
bool IsArrow, SourceLocation OpLoc,
const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
// Even in dependent contexts, try to diagnose base expressions with
@@ -591,8 +590,8 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
// must have pointer type, and the accessed type is the pointee.
return CXXDependentScopeMemberExpr::Create(
Context, BaseExpr, BaseType, IsArrow, OpLoc,
- SS.getWithLocInContext(Context), TemplateKWLoc, FirstQualifierInScope,
- NameInfo, TemplateArgs);
+ SS.getWithLocInContext(Context), TemplateKWLoc,
+ SS.getUnqualifiedLookups(), NameInfo, TemplateArgs);
}
/// We know that the given qualified member reference points only to
@@ -780,8 +779,9 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
R.addDecl(ND);
R.resolveKind();
return SemaRef.BuildMemberReferenceExpr(
- BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS, SourceLocation(),
- nullptr, R, nullptr, nullptr);
+ BaseExpr, BaseExpr->getType(), OpLoc, IsArrow, SS,
+ /*TemplateKWLoc=*/SourceLocation(), R, /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
},
Sema::CTK_ErrorRecovery, DC);
@@ -797,7 +797,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
ExprResult Sema::BuildMemberReferenceExpr(
Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow,
CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo,
+ const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
ActOnMemberAccessExtraArgs *ExtraArgs) {
LookupResult R(*this, NameInfo, LookupMemberName);
@@ -841,8 +841,9 @@ ExprResult Sema::BuildMemberReferenceExpr(
return BuildMemberReferenceExpr(Base, BaseType,
OpLoc, IsArrow, SS, TemplateKWLoc,
- FirstQualifierInScope, R, TemplateArgs, S,
- false, ExtraArgs);
+ R, TemplateArgs, S,
+ /*SuppressQualifierCheck=*/false,
+ ExtraArgs);
}
ExprResult
@@ -985,7 +986,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
SourceLocation OpLoc, bool IsArrow,
const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs,
const Scope *S,
@@ -1000,8 +1000,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
(SS.isSet() ? SS.getScopeRep()->isDependent()
: BaseExprType->isDependentType())))
return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS,
- TemplateKWLoc, FirstQualifierInScope,
- R.getLookupNameInfo(), TemplateArgs);
+ TemplateKWLoc, R.getLookupNameInfo(),
+ TemplateArgs);
QualType BaseType = BaseExprType;
if (IsArrow) {
@@ -1208,7 +1208,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
if (!VDecl.get())
return ActOnDependentMemberExpr(
BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc,
- FirstQualifierInScope, MemberNameInfo, TemplateArgs);
+ MemberNameInfo, TemplateArgs);
VarDecl *Var = cast<VarDecl>(VDecl.get());
if (!Var->getTemplateSpecializationKind())
@@ -1792,9 +1792,10 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
if (getLangOpts().HLSL && IsArrow)
return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2);
- NamedDecl *FirstQualifierInScope
- = (!SS.isSet() ? nullptr : FindFirstQualifierInScope(S, SS.getScopeRep()));
-
+ UnresolvedSet<4> UnqualifiedLookups;
+ if (SS.isValid() && LookupFirstQualifierInScope(S, SS.getScopeRep(), UnqualifiedLookups)) {
+ SS.setUnqualifiedLookups(UnqualifiedLookups.pairs());
+ }
// This is a postfix expression, so get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
if (Result.isInvalid()) return ExprError();
@@ -1803,7 +1804,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
ExprResult Res = BuildMemberReferenceExpr(
Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc,
- FirstQualifierInScope, NameInfo, TemplateArgs, S, &ExtraArgs);
+ NameInfo, TemplateArgs, S, &ExtraArgs);
if (!Res.isInvalid() && isa<MemberExpr>(Res.get()))
CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get()));
@@ -1954,6 +1955,6 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
return BuildMemberReferenceExpr(
baseExpr, ThisTy,
/*OpLoc=*/SourceLocation(),
- /*IsArrow=*/!getLangOpts().HLSL, SS, TemplateKWLoc,
- /*FirstQualifierInScope=*/nullptr, R, TemplateArgs, S);
+ /*IsArrow=*/!getLangOpts().HLSL, SS,
+ TemplateKWLoc, R, TemplateArgs, S);
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6c4ce1022ae27..6f066235461b0 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -16219,9 +16219,8 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
if (!MemberLookup.empty()) {
ExprResult MemberRef =
BuildMemberReferenceExpr(Range, Range->getType(), Loc,
- /*IsPtr=*/false, CXXScopeSpec(),
+ /*IsPtr=*/false, /*SS=*/CXXScopeSpec(),
/*TemplateKWLoc=*/SourceLocation(),
- /*FirstQualifierInScope=*/nullptr,
MemberLookup,
/*TemplateArgs=*/nullptr, S);
if (MemberRef.isInvalid()) {
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 32d42f3c3f3bb..9b1e49620173d 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -900,7 +900,7 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
return CXXDependentScopeMemberExpr::Create(
Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(),
SourceLocation(),
- /*FirstQualifierFoundInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr);
+ /*UnqualifiedLookups=*/std::nullopt, NameInfo, /*TemplateArgs=*/nullptr);
}
const RecordType *RT = T->getAs<RecordType>();
@@ -923,8 +923,9 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
// Make an Expr to thread through OpDecl.
ExprResult Result = BuildMemberReferenceExpr(
- E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
- SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
+ E, E->getType(), AsmLoc, /*IsArrow=*/false, /*SS=*/CXXScopeSpec(),
+ /*TemplateKWLoc*/SourceLocation(), FieldResult,
+ /*TemplateArgs=*/nullptr, /*S=*/nullptr);
return Result;
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 6fc290e382b0f..57fe755ae8fc0 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -469,10 +469,13 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
// expression. If the identifier is not found, it is then looked up in
// the context of the entire postfix-expression and shall name a class
// template.
- if (S)
+ if (S) {
LookupName(Found, S);
- else if (LookupFirstQualifierInScope && SS.getFirstQualifierFoundInScope())
- Found.addDecl(SS.getFirstQualifierFoundInScope());
+ } else if (LookupFirstQualifierInScope &&
+ !SS.getUnqualifiedLookups().empty()) {
+ Found.addAllDecls(SS.getUnqualifiedLookups());
+ Found.resolveKind();
+ }
if (!ObjectType.isNull())
ObjectTypeSearchedInScope = true;
@@ -747,7 +750,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
/*IsArrow=*/!Context.getLangOpts().HLSL,
/*OperatorLoc=*/SourceLocation(),
/*QualifierLoc=*/NestedNameSpecifierLoc(), TemplateKWLoc,
- /*FirstQualifierFoundInScope=*/nullptr, NameInfo, TemplateArgs);
+ /*UnqualifiedLookups=*/std::nullopt, NameInfo, TemplateArgs);
}
return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index abb8a260faab9..73ca3a0fde478 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1549,7 +1549,6 @@ namespace {
TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = nullptr,
bool AllowInjectedClassName = false);
const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
@@ -1982,8 +1981,7 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
TemplateName TemplateInstantiator::TransformTemplateName(
CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
- QualType ObjectType, NamedDecl *FirstQualifierInScope,
- bool AllowInjectedClassName) {
+ QualType ObjectType, bool AllowInjectedClassName) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
@@ -2057,7 +2055,6 @@ TemplateName TemplateInstantiator::TransformTemplateName(
}
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
- FirstQualifierInScope,
AllowInjectedClassName);
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index c037f93bbbc3f..e421510105c69 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -544,7 +544,7 @@ class TreeTransform {
NestedNameSpecifierLoc
TransformNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = nullptr);
+ ArrayRef<DeclAccessPair> UnqualifiedLookups = std::nullopt);
/// Transform the given declaration name.
///
@@ -589,7 +589,6 @@ class TreeTransform {
TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
- NamedDecl *FirstQualifierInScope = nullptr,
bool AllowInjectedClassName = false);
/// Transform the given template argument.
@@ -1140,7 +1139,7 @@ class TreeTransform {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
TemplateName InstName = getDerived().RebuildTemplateName(
- SS, TemplateKWLoc, *Name, NameLoc, QualType(), nullptr,
+ SS, TemplateKWLoc, *Name, NameLoc, QualType(),
AllowInjectedClassName);
if (InstName.isNull())
@@ -1312,7 +1311,6 @@ class TreeTransform {
SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,
SourceLocation NameLoc, QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
bool AllowInjectedClassName);
/// Build a new template name given a nested name specifier and the
@@ -2857,7 +2855,7 @@ class TreeTransform {
ValueDecl *Member,
NamedDecl *FoundDecl,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
- NamedDecl *FirstQualifierInScope) {
+ ArrayRef<DeclAccessPair> UnqualifiedLookups) {
ExprResult BaseResult = getSema().PerformMemberExprBaseConversion(Base,
isArrow);
if (!Member->getDeclName()) {
@@ -2894,8 +2892,7 @@ class TreeTransform {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
- if (FirstQualifierInScope)
- SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
+ SS.setUnqualifiedLookups(UnqualifiedLookups);
Base = BaseResult.get();
QualType BaseType = Base->getType();
@@ -2926,7 +2923,6 @@ class TreeTransform {
return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow,
SS, TemplateKWLoc,
- FirstQualifierInScope,
R, ExplicitTemplateArgs,
/*S*/nullptr);
}
@@ -3001,10 +2997,9 @@ class TreeTransform {
CXXScopeSpec SS;
DeclarationNameInfo NameInfo(&Accessor, AccessorLoc);
return getSema().BuildMemberReferenceExpr(
- Base, Base->getType(), OpLoc, IsArrow, SS, SourceLocation(),
- /*FirstQualifierInScope*/ nullptr, NameInfo,
- /* TemplateArgs */ nullptr,
- /*S*/ nullptr);
+ Base, Base->getType(), OpLoc, IsArrow, SS,
+ /*TemplateKWLoc=*/SourceLocation(), NameInfo,
+ /*TemplateArgs=*/ nullptr, /*S=*/nullptr);
}
/// Build a new initializer list expression.
@@ -3578,21 +3573,18 @@ class TreeTransform {
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups,
const DeclarationNameInfo &MemberNameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
-
- if (FirstQualifierInScope)
- SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
+ SS.setUnqualifiedLookups(UnqualifiedLookups);
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
SS, TemplateKWLoc,
- FirstQualifierInScope,
MemberNameInfo,
- TemplateArgs, /*S*/nullptr);
+ TemplateArgs, /*S=*/nullptr);
}
/// Build a new member reference expression.
@@ -3604,20 +3596,17 @@ class TreeTransform {
bool IsArrow,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
- NamedDecl *FirstQualifierInScope,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
-
- if (FirstQualifierInScope)
- SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
+ SS.setUnqualifiedLookups(UnqualifiedLookups);
return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
OperatorLoc, IsArrow,
SS, TemplateKWLoc,
- FirstQualifierInScope,
- R, TemplateArgs, /*S*/nullptr);
+ R, TemplateArgs, /*S=*/nullptr);
}
/// Build a new noexcept expression.
@@ -3836,10 +3825,8 @@ class TreeTransform {
DeclarationNameInfo NameInfo(Ivar->getDeclName(), IvarLoc);
ExprResult Result = getSema().BuildMemberReferenceExpr(
BaseArg, BaseArg->getType(),
- /*FIXME:*/ IvarLoc, IsArrow, SS, SourceLocation(),
- /*FirstQualifierInScope=*/nullptr, NameInfo,
- /*TemplateArgs=*/nullptr,
- /*S=*/nullptr);
+ /*FIXME:*/ IvarLoc, IsArrow, SS, /*TemplateKWLoc=*/SourceLocation(),
+ NameInfo, /*TemplateArgs=*/nullptr, /*S=*/nullptr);
if (IsFreeIvar && Result.isUsable())
cast<ObjCIvarRefExpr>(Result.get())->setIsFreeIvar(IsFreeIvar);
return Result;
@@ -3857,8 +3844,7 @@ class TreeTransform {
return getSema().BuildMemberReferenceExpr(BaseArg, BaseArg->getType(),
/*FIXME:*/PropertyLoc,
/*IsArrow=*/false,
- SS, SourceLocation(),
- /*FirstQualifierInScope=*/nullptr,
+ SS, /*TemplateKWLoc=*/SourceLocation(),
NameInfo,
/*TemplateArgs=*/nullptr,
/*S=*/nullptr);
@@ -3890,8 +3876,7 @@ class TreeTransform {
DeclarationNameInfo NameInfo(&getSema().Context.Idents.get("isa"), IsaLoc);
return getSema().BuildMemberReferenceExpr(BaseArg, BaseArg->getType(),
OpLoc, IsArrow,
- SS, SourceLocation(),
- /*FirstQualifierInScope=*/nullptr,
+ SS, /*TemplateKWLoc=*/SourceLocation(),
NameInfo,
/*TemplateArgs=*/nullptr,
/*S=*/nullptr);
@@ -4052,16 +4037,14 @@ class TreeTransform {
private:
TypeLoc TransformTypeInObjectScope(TypeLoc TL,
QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
CXXScopeSpec &SS);
TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
CXXScopeSpec &SS);
- TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL, QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
+ TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL,
+ QualType ObjectType,
CXXScopeSpec &SS);
QualType TransformDependentNameType(TypeLocBuilder &TLB,
@@ -4380,7 +4363,7 @@ Sema::ConditionResult TreeTransform<Derived>::TransformCondition(
template <typename Derived>
NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
NestedNameSpecifierLoc NNS, QualType ObjectType,
- NamedDecl *FirstQualifierInScope) {
+ ArrayRef<DeclAccessPair> UnqualifiedLookups) {
SmallVector<NestedNameSpecifierLoc, 4> Qualifiers;
auto insertNNS = [&Qualifiers](NestedNameSpecifierLoc NNS) {
@@ -4391,8 +4374,8 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
insertNNS(NNS);
CXXScopeSpec SS;
- if (FirstQualifierInScope)
- SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
+ SS.setUnqualifiedLookups(UnqualifiedLookups);
+
while (!Qualifiers.empty()) {
NestedNameSpecifierLoc Q = Qualifiers.pop_back_val();
NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier();
@@ -4402,8 +4385,9 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
Sema::NestedNameSpecInfo IdInfo(QNNS->getAsIdentifier(),
Q.getLocalBeginLoc(), Q.getLocalEndLoc(),
ObjectType);
- if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo, false,
- SS, FirstQualifierInScope, false))
+ if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo,
+ /*EnteringContext=*/false,
+ SS, /*ErrorRecoveryLookup=*/false))
return NestedNameSpecifierLoc();
break;
}
@@ -4441,8 +4425,7 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
case NestedNameSpecifier::TypeSpecWithTemplate:
case NestedNameSpecifier::TypeSpec: {
- TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType,
- FirstQualifierInScope, SS);
+ TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType, SS);
if (!TL)
return NestedNameSpecifierLoc();
@@ -4475,7 +4458,7 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
}
// The qualifier-in-scope and object type only apply to the leftmost entity.
- FirstQualifierInScope = nullptr;
+ SS.setUnqualifiedLookups(std::nullopt);
ObjectType = QualType();
}
@@ -4564,7 +4547,6 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
bool AllowInjectedClassName) {
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl();
@@ -4589,7 +4571,7 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
if (SS.getScopeRep()) {
// These apply to the scope specifier, not the template.
ObjectType = QualType();
- FirstQualifierInScope = nullptr;
+ SS.setUnqualifiedLookups(std::nullopt);
}
if (!getDerived().AlwaysRebuild() &&
@@ -4606,7 +4588,6 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
*DTN->getIdentifier(),
NameLoc,
ObjectType,
- FirstQualifierInScope,
AllowInjectedClassName);
}
@@ -5155,13 +5136,12 @@ template<typename Derived>
TypeLoc
TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
QualType ObjectType,
- NamedDecl *UnqualLookup,
CXXScopeSpec &SS) {
if (getDerived().AlreadyTransformed(TL.getType()))
return TL;
TypeSourceInfo *TSI =
- TransformTSIInObjectScope(TL, ObjectType, UnqualLookup, SS);
+ TransformTSIInObjectScope(TL, ObjectType, SS);
if (TSI)
return TSI->getTypeLoc();
return TypeLoc();
@@ -5171,35 +5151,29 @@ template<typename Derived>
TypeSourceInfo *
TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
QualType ObjectType,
- NamedDecl *UnqualLookup,
CXXScopeSpec &SS) {
if (getDerived().AlreadyTransformed(TSInfo->getType()))
return TSInfo;
- return TransformTSIInObjectScope(TSInfo->getTypeLoc(), ObjectType,
- UnqualLookup, SS);
+ return TransformTSIInObjectScope(TSInfo->getTypeLoc(), ObjectType, SS);
}
template <typename Derived>
TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
- TypeLoc TL, QualType ObjectType, NamedDecl *UnqualLookup,
- CXXScopeSpec &SS) {
+ TypeLoc TL, QualType ObjectType, CXXScopeSpec &SS) {
QualType T = TL.getType();
assert(!getDerived().AlreadyTransformed(T));
TypeLocBuilder TLB;
QualType Result;
- if (UnqualLookup)
- SS.setFoundFirstQualifierInScope(UnqualLookup);
-
if (isa<TemplateSpecializationType>(T)) {
TemplateSpecializationTypeLoc SpecTL =
TL.castAs<TemplateSpecializationTypeLoc>();
TemplateName Template = getDerived().TransformTemplateName(
SS, SpecTL.getTypePtr()->getTemplateName(), SpecTL.getTemplateNameLoc(),
- ObjectType, UnqualLookup, /*AllowInjectedClassName*/true);
+ ObjectType, /*AllowInjectedClassName=*/true);
if (Template.isNull())
return nullptr;
@@ -5214,8 +5188,8 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
SpecTL.getTemplateKeywordLoc(),
*SpecTL.getTypePtr()->getIdentifier(),
SpecTL.getTemplateNameLoc(),
- ObjectType, UnqualLookup,
- /*AllowInjectedClassName*/true);
+ ObjectType,
+ /*AllowInjectedClassName=*/true);
if (Template.isNull())
return nullptr;
@@ -12259,7 +12233,8 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
// first-qualifier-in-scope here, just in case we had a dependent
// base (and therefore couldn't do the check) and a
// nested-name-qualifier (and therefore could do the lookup).
- NamedDecl *FirstQualifierInScope = nullptr;
+ ArrayRef<DeclAccessPair> UnqualifiedLookups;
+
DeclarationNameInfo MemberNameInfo = E->getMemberNameInfo();
if (MemberNameInfo.getName()) {
MemberNameInfo = getDerived().TransformDeclarationNameInfo(MemberNameInfo);
@@ -12276,7 +12251,7 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
FoundDecl,
(E->hasExplicitTemplateArgs()
? &TransArgs : nullptr),
- FirstQualifierInScope);
+ UnqualifiedLookups);
}
template<typename Derived>
@@ -13400,7 +13375,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
if (E->getDestroyedTypeInfo()) {
TypeSourceInfo *DestroyedTypeInfo
= getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
- ObjectType, nullptr, SS);
+ ObjectType, SS);
if (!DestroyedTypeInfo)
return ExprError();
Destroyed = DestroyedTypeInfo;
@@ -13426,7 +13401,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
if (E->getScopeTypeInfo()) {
CXXScopeSpec EmptySS;
ScopeTypeInfo = getDerived().TransformTypeInObjectScope(
- E->getScopeTypeInfo(), ObjectType, nullptr, EmptySS);
+ E->getScopeTypeInfo(), ObjectType, EmptySS);
if (!ScopeTypeInfo)
return ExprError();
}
@@ -14688,19 +14663,28 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
ObjectType = BaseType->castAs<PointerType>()->getPointeeType();
}
+ #if 0
// Transform the first part of the nested-name-specifier that qualifies
// the member name.
NamedDecl *FirstQualifierInScope
= getDerived().TransformFirstQualifierInScope(
E->getFirstQualifierFoundInScope(),
E->getQualifierLoc().getBeginLoc());
+ #endif
+
+ UnresolvedSet<4> UnqualifiedLookups;
+ for (auto D : E->unqualified_lookups()) {
+ if (NamedDecl *InstD = getDerived().TransformFirstQualifierInScope(
+ D.getDecl(), E->getQualifierLoc().getBeginLoc()))
+ UnqualifiedLookups.addDecl(InstD);
+ }
NestedNameSpecifierLoc QualifierLoc;
if (E->getQualifier()) {
QualifierLoc
= getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc(),
ObjectType,
- FirstQualifierInScope);
+ UnqualifiedLookups.pairs());
if (!QualifierLoc)
return ExprError();
}
@@ -14724,7 +14708,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
BaseType == E->getBaseType() &&
QualifierLoc == E->getQualifierLoc() &&
NameInfo.getName() == E->getMember() &&
- FirstQualifierInScope == E->getFirstQualifierFoundInScope())
+ UnqualifiedLookups.pairs() == E->unqualified_lookups())
return E;
return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
@@ -14733,7 +14717,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
E->getOperatorLoc(),
QualifierLoc,
TemplateKWLoc,
- FirstQualifierInScope,
+ UnqualifiedLookups.pairs(),
NameInfo,
/*TemplateArgs*/nullptr);
}
@@ -14750,7 +14734,7 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
E->getOperatorLoc(),
QualifierLoc,
TemplateKWLoc,
- FirstQualifierInScope,
+ UnqualifiedLookups.pairs(),
NameInfo,
&TransArgs);
}
@@ -14813,11 +14797,11 @@ ExprResult TreeTransform<Derived>::TransformUnresolvedMemberExpr(
// first-qualifier-in-scope here, just in case we had a dependent
// base (and therefore couldn't do the check) and a
// nested-name-qualifier (and therefore could do the lookup).
- NamedDecl *FirstQualifierInScope = nullptr;
+ ArrayRef<DeclAccessPair> UnqualifiedLookups;
return getDerived().RebuildUnresolvedMemberExpr(
Base.get(), BaseType, Old->getOperatorLoc(), Old->isArrow(), QualifierLoc,
- TemplateKWLoc, FirstQualifierInScope, R,
+ TemplateKWLoc, UnqualifiedLookups, R,
(Old->hasExplicitTemplateArgs() ? &TransArgs : nullptr));
}
@@ -16181,13 +16165,10 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
const IdentifierInfo &Name,
SourceLocation NameLoc,
QualType ObjectType,
- NamedDecl *FirstQualifierInScope,
bool AllowInjectedClassName) {
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
- if (FirstQualifierInScope)
- SS.setFoundFirstQualifierInScope(FirstQualifierInScope);
getSema().ActOnTemplateName(/*Scope=*/nullptr, SS, TemplateKWLoc,
TemplateName, ParsedType::make(ObjectType),
/*EnteringContext=*/false, Template,
@@ -16342,10 +16323,9 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
return getSema().BuildMemberReferenceExpr(Base, BaseType,
OperatorLoc, isArrow,
SS, TemplateKWLoc,
- /*FIXME: FirstQualifier*/ nullptr,
NameInfo,
- /*TemplateArgs*/ nullptr,
- /*S*/nullptr);
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
template<typename Derived>
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index bea2b94989107..1054abf3170a1 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1983,6 +1983,43 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
CXXDependentScopeMemberExpr *E) {
VisitExpr(E);
+ CurrentUnpackingBits.emplace(Record.readInt());
+ bool HasQualifier = CurrentUnpackingBits->getNextBit();
+ bool HasTemplateInfo = CurrentUnpackingBits->getNextBit();
+ unsigned NumUnqualifiedLookups = Record.readInt();
+ unsigned NumTemplateArgs = Record.readInt();
+ E->CXXDependentScopeMemberExprBits.HasQualifier = HasQualifier;
+ E->CXXDependentScopeMemberExprBits.NumUnqualifiedLookups = NumUnqualifiedLookups;
+ E->CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo;
+
+ E->BaseType = Record.readType();
+ E->CXXDependentScopeMemberExprBits.IsArrow = CurrentUnpackingBits->getNextBit();
+
+ if (CurrentUnpackingBits->getNextBit())
+ E->Base = Record.readSubExpr();
+ else
+ E->Base = nullptr;
+
+ E->OperatorLoc = Record.readSourceLocation();
+ E->MemberNameInfo = Record.readDeclarationNameInfo();
+
+ if (HasQualifier)
+ new (E->getTrailingObjects<NestedNameSpecifierLoc>())
+ NestedNameSpecifierLoc(Record.readNestedNameSpecifierLoc());
+
+ for (unsigned I = 0; I != NumUnqualifiedLookups; ++I) {
+ auto *FoundD = Record.readDeclAs<NamedDecl>();
+ auto AS = (AccessSpecifier)Record.readInt();
+ E->getTrailingObjects<DeclAccessPair>()[I] = DeclAccessPair::make(FoundD, AS);;
+ }
+
+ if (HasTemplateInfo)
+ ReadTemplateKWAndArgsInfo(
+ *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
+ E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
+
+
+ #if 0
unsigned NumTemplateArgs = Record.readInt();
CurrentUnpackingBits.emplace(Record.readInt());
bool HasTemplateKWAndArgsInfo = CurrentUnpackingBits->getNextBit();
@@ -2019,6 +2056,7 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
*E->getTrailingObjects<NamedDecl *>() = readDeclAs<NamedDecl>();
E->MemberNameInfo = Record.readDeclarationNameInfo();
+ #endif
}
void
@@ -4055,6 +4093,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: {
+
+ #if 0
unsigned NumTemplateArgs = Record[ASTStmtReader::NumExprFields];
BitsUnpacker DependentScopeMemberBits(
Record[ASTStmtReader::NumExprFields + 1]);
@@ -4062,9 +4102,16 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
bool HasFirstQualifierFoundInScope =
DependentScopeMemberBits.getNextBit();
+ #endif
+ BitsUnpacker DependentScopeMemberBits(Record[ASTStmtReader::NumExprFields]);
+ bool HasQualifier = DependentScopeMemberBits.getNextBit();
+ bool HasTemplateInfo = DependentScopeMemberBits.getNextBit();
+ unsigned NumUnqualifiedLookups = Record[ASTStmtReader::NumExprFields + 1];
+ unsigned NumTemplateArgs = Record[ASTStmtReader::NumExprFields + 2];
+
S = CXXDependentScopeMemberExpr::CreateEmpty(
- Context, HasTemplateKWAndArgsInfo, NumTemplateArgs,
- HasFirstQualifierFoundInScope);
+ Context, HasQualifier, NumUnqualifiedLookups,
+ HasTemplateInfo, NumTemplateArgs);
break;
}
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 3c586b270fbf4..bb117d1d2a7d2 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -1977,6 +1977,42 @@ void ASTStmtWriter::VisitCXXDependentScopeMemberExpr(
CXXDependentScopeMemberExpr *E) {
VisitExpr(E);
+ bool HasQualifier = E->hasQualifier();
+ unsigned NumUnqualifiedLookups = E->getNumUnqualifiedLookups();
+ bool HasTemplateInfo = E->hasTemplateKWAndArgsInfo();
+ unsigned NumTemplateArgs = E->getNumTemplateArgs();
+
+ // Write these first for easy access when deserializing, as they affect the
+ // size of the CXXDependentScopeMemberExpr.
+ CurrentPackingBits.updateBits();
+ CurrentPackingBits.addBit(HasQualifier);
+ CurrentPackingBits.addBit(HasTemplateInfo);
+ Record.push_back(NumUnqualifiedLookups);
+ Record.push_back(NumTemplateArgs);
+
+ Record.AddTypeRef(E->getBaseType());
+ CurrentPackingBits.addBit(E->isArrow());
+ CurrentPackingBits.addBit(!E->isImplicitAccess());
+ if (!E->isImplicitAccess())
+ Record.AddStmt(E->getBase());
+
+ Record.AddSourceLocation(E->getOperatorLoc());
+
+ Record.AddDeclarationNameInfo(E->MemberNameInfo);
+
+ if (HasQualifier)
+ Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
+
+ for (DeclAccessPair D : E->unqualified_lookups()) {
+ Record.AddDeclRef(D.getDecl());
+ Record.push_back(D.getAccess());
+ }
+
+ if (HasTemplateInfo)
+ AddTemplateKWAndArgsInfo(*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
+ E->getTrailingObjects<TemplateArgumentLoc>());
+
+ #if 0
// Don't emit anything here (or if you do you will have to update
// the corresponding deserialization function).
Record.push_back(E->getNumTemplateArgs());
@@ -2005,6 +2041,8 @@ void ASTStmtWriter::VisitCXXDependentScopeMemberExpr(
Record.AddDeclRef(E->getFirstQualifierFoundInScope());
Record.AddDeclarationNameInfo(E->MemberNameInfo);
+ #endif
+
Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
}
diff --git a/clang/test/SemaCXX/pseudo-destructors.cpp b/clang/test/SemaCXX/pseudo-destructors.cpp
index 55a96002be2ab..44dc9ce8b1520 100644
--- a/clang/test/SemaCXX/pseudo-destructors.cpp
+++ b/clang/test/SemaCXX/pseudo-destructors.cpp
@@ -22,21 +22,21 @@ void cv_test(const volatile T* cvt) {
void f(A* a, Foo *f, int *i, double *d, int ii) {
a->~A();
a->A::~A();
-
+
a->~foo(); // expected-error{{undeclared identifier 'foo' in destructor name}}
-
+
a->~Bar(); // expected-error{{destructor type 'Bar' (aka 'Foo') in object destruction expression does not match the type 'A' of the object being destroyed}}
-
+
f->~Bar();
f->~Foo();
i->~Bar(); // expected-error{{does not match}}
-
+
g().~Bar(); // expected-error{{non-scalar}}
-
+
f->::~Bar(); // expected-error {{not a structure or union}}
f->::Bar::~Bar();
f->N::~Wibble(); // expected-error{{'N' does not refer to a type}} expected-error{{'Wibble' does not refer to a type}}
-
+
f->Bar::~Bar(17, 42); // expected-error{{cannot have any arguments}}
i->~Integer();
@@ -148,12 +148,12 @@ namespace TwoPhaseLookup {
namespace Template {
template<typename T> struct Y {};
template<class U> using G = Y<U>;
- template<typename T> void f(T *p) { p->~G<int>(); } // expected-error {{no member named '~Y'}}
+ template<typename T> void f(T *p) { p->~G<int>(); } // expected-error {{no member named 'G'}}
void h1(Y<int> *p) { p->~G<int>(); }
- void h2(Y<int> *p) { f(p); }
+ void h2(Y<int> *p) { f(p); } // expected-note {{instantiation of}}
namespace N { template<typename T> struct G {}; }
void h3(N::G<int> *p) { p->~G<int>(); }
- void h4(N::G<int> *p) { f(p); } // expected-note {{instantiation of}}
+ void h4(N::G<int> *p) { f(p); }
}
namespace TemplateUndeclared {
>From cd778c571a8dfa6f789332a071c769c8ed69d9a1 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 31 May 2024 13:13:40 -0400
Subject: [PATCH 04/19] [FOLD] format
---
clang/include/clang/AST/ExprCXX.h | 26 +--
clang/include/clang/AST/Stmt.h | 4 +-
clang/include/clang/Sema/Sema.h | 14 +-
clang/lib/AST/ASTImporter.cpp | 1 -
clang/lib/AST/ExprCXX.cpp | 36 ++-
clang/lib/AST/ItaniumMangle.cpp | 35 ++-
clang/lib/Sema/SemaCXXScopeSpec.cpp | 5 +-
clang/lib/Sema/SemaCoroutine.cpp | 4 +-
clang/lib/Sema/SemaDeclCXX.cpp | 33 ++-
clang/lib/Sema/SemaExprMember.cpp | 50 ++--
clang/lib/Sema/SemaOverload.cpp | 11 +-
clang/lib/Sema/SemaStmtAsm.cpp | 5 +-
clang/lib/Sema/SemaTemplate.cpp | 2 +-
clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 +-
clang/lib/Sema/TreeTransform.h | 260 ++++++++-------------
clang/lib/Serialization/ASTReaderStmt.cpp | 26 ++-
clang/lib/Serialization/ASTWriterStmt.cpp | 4 +-
17 files changed, 222 insertions(+), 303 deletions(-)
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 3e4d673590b71..d8f87ad4a94f3 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -3671,11 +3671,9 @@ class CXXUnresolvedConstructExpr final
/// an implicit access if a qualifier is provided.
class CXXDependentScopeMemberExpr final
: public Expr,
- private llvm::TrailingObjects<CXXDependentScopeMemberExpr,
- NestedNameSpecifierLoc,
- DeclAccessPair,
- ASTTemplateKWAndArgsInfo,
- TemplateArgumentLoc> {
+ private llvm::TrailingObjects<
+ CXXDependentScopeMemberExpr, NestedNameSpecifierLoc, DeclAccessPair,
+ ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend TrailingObjects;
@@ -3751,10 +3749,8 @@ class CXXDependentScopeMemberExpr final
public:
static CXXDependentScopeMemberExpr *
- Create(const ASTContext &Ctx, Expr *Base,
- QualType BaseType, bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
+ Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationNameInfo MemberNameInfo,
@@ -3762,8 +3758,7 @@ class CXXDependentScopeMemberExpr final
static CXXDependentScopeMemberExpr *
CreateEmpty(const ASTContext &Ctx, bool HasQualifier,
- unsigned NumUnqualifiedLookups,
- bool HasTemplateKWAndArgsInfo,
+ unsigned NumUnqualifiedLookups, bool HasTemplateKWAndArgsInfo,
unsigned NumTemplateArgs);
/// True if this is an implicit access, i.e. one in which the
@@ -3789,9 +3784,7 @@ class CXXDependentScopeMemberExpr final
bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; }
/// Retrieve the location of the '->' or '.' operator.
- SourceLocation getOperatorLoc() const {
- return OperatorLoc;
- }
+ SourceLocation getOperatorLoc() const { return OperatorLoc; }
/// Determines whether this member expression had a nested-name-specifier
/// prior to the name of the member, e.g., x->Base::foo.
@@ -3814,8 +3807,7 @@ class CXXDependentScopeMemberExpr final
return getQualifierLoc().getNestedNameSpecifier();
}
-
- #if 0
+#if 0
/// Retrieve the first part of the nested-name-specifier that was
/// found in the scope of the member access expression when the member access
/// was initially parsed.
@@ -3832,7 +3824,7 @@ class CXXDependentScopeMemberExpr final
return nullptr;
return *getTrailingObjects<NamedDecl *>();
}
- #endif
+#endif
ArrayRef<DeclAccessPair> unqualified_lookups() const {
if (!getNumUnqualifiedLookups())
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index e0e5c8fb99dc3..6e6221ec15fdb 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -1030,12 +1030,12 @@ class alignas(void *) Stmt {
LLVM_PREFERRED_TYPE(bool)
unsigned HasTemplateKWAndArgsInfo : 1;
- #if 0
+#if 0
/// See getFirstQualifierFoundInScope() and the comment listing
/// the trailing objects.
LLVM_PREFERRED_TYPE(bool)
unsigned HasFirstQualifierFoundInScope : 1;
- #endif
+#endif
/// Number of declarations found by unqualified lookup for the
/// first component name of the nested-name-specifier.
unsigned NumUnqualifiedLookups;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9fab8d13a1c35..4208da06db3dc 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2390,7 +2390,8 @@ class Sema final : public SemaBase {
bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
bool *CanCorrect = nullptr);
- bool LookupFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS, UnresolvedSetImpl &R);
+ bool LookupFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS,
+ UnresolvedSetImpl &R);
/// Keeps information about an identifier in a nested-name-spec.
///
@@ -6934,11 +6935,12 @@ class Sema final : public SemaBase {
const TemplateArgumentListInfo *TemplateArgs,
bool IsDefiniteInstance, const Scope *S);
- ExprResult ActOnDependentMemberExpr(
- Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OpLoc,
- const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &NameInfo,
- const TemplateArgumentListInfo *TemplateArgs);
+ ExprResult
+ ActOnDependentMemberExpr(Expr *Base, QualType BaseType, bool IsArrow,
+ SourceLocation OpLoc, const CXXScopeSpec &SS,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &NameInfo,
+ const TemplateArgumentListInfo *TemplateArgs);
ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
bool IsArrow, CXXScopeSpec &SS,
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 6c306418fe071..b47d7e86013dd 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -8433,7 +8433,6 @@ ExpectedStmt ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
auto ToQualifierLoc = importChecked(Err, E->getQualifierLoc());
auto ToTemplateKeywordLoc = importChecked(Err, E->getTemplateKeywordLoc());
-
UnresolvedSet<8> ToUnqualifiedLookups;
for (auto D : E->unqualified_lookups())
if (auto ToDOrErr = import(D.getDecl()))
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 87e33564ca02e..826f66fe1624c 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1450,8 +1450,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc),
MemberNameInfo(MemberNameInfo) {
CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
- CXXDependentScopeMemberExprBits.HasQualifier =
- QualifierLoc.hasQualifier();
+ CXXDependentScopeMemberExprBits.HasQualifier = QualifierLoc.hasQualifier();
CXXDependentScopeMemberExprBits.NumUnqualifiedLookups =
UnqualifiedLookups.size();
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
@@ -1462,7 +1461,8 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
NestedNameSpecifierLoc(QualifierLoc);
std::uninitialized_copy_n(UnqualifiedLookups.data(),
- UnqualifiedLookups.size(), getTrailingObjects<DeclAccessPair>());
+ UnqualifiedLookups.size(),
+ getTrailingObjects<DeclAccessPair>());
if (TemplateArgs) {
auto Deps = TemplateArgumentDependence::None;
@@ -1482,8 +1482,7 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
bool HasTemplateKWAndArgsInfo)
: Expr(CXXDependentScopeMemberExprClass, Empty) {
CXXDependentScopeMemberExprBits.HasQualifier = HasQualifier;
- CXXDependentScopeMemberExprBits.NumUnqualifiedLookups =
- NumUnqualifiedLookups;
+ CXXDependentScopeMemberExprBits.NumUnqualifiedLookups = NumUnqualifiedLookups;
CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo =
HasTemplateKWAndArgsInfo;
}
@@ -1500,12 +1499,11 @@ CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::Create(
bool HasTemplateKWAndArgsInfo =
(TemplateArgs != nullptr) || TemplateKWLoc.isValid();
unsigned NumTemplateArgs = TemplateArgs ? TemplateArgs->size() : 0;
- unsigned Size = totalSizeToAlloc<NestedNameSpecifierLoc,
- DeclAccessPair,
- ASTTemplateKWAndArgsInfo,
- TemplateArgumentLoc>(
- HasQualifier, NumUnqualifiedLookups,
- HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ unsigned Size =
+ totalSizeToAlloc<NestedNameSpecifierLoc, DeclAccessPair,
+ ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasQualifier, NumUnqualifiedLookups, HasTemplateKWAndArgsInfo,
+ NumTemplateArgs);
void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
return new (Mem) CXXDependentScopeMemberExpr(
@@ -1519,16 +1517,16 @@ CXXDependentScopeMemberExpr *CXXDependentScopeMemberExpr::CreateEmpty(
assert(!NumTemplateArgs || HasTemplateKWAndArgsInfo);
assert(!NumUnqualifiedLookups || HasQualifier);
- unsigned Size = totalSizeToAlloc<NestedNameSpecifierLoc,
- DeclAccessPair,
- ASTTemplateKWAndArgsInfo,
- TemplateArgumentLoc>(
- HasQualifier, NumUnqualifiedLookups,
- HasTemplateKWAndArgsInfo, NumTemplateArgs);
+ unsigned Size =
+ totalSizeToAlloc<NestedNameSpecifierLoc, DeclAccessPair,
+ ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
+ HasQualifier, NumUnqualifiedLookups, HasTemplateKWAndArgsInfo,
+ NumTemplateArgs);
void *Mem = Ctx.Allocate(Size, alignof(CXXDependentScopeMemberExpr));
- return new (Mem) CXXDependentScopeMemberExpr(
- EmptyShell(), HasQualifier, NumUnqualifiedLookups, HasTemplateKWAndArgsInfo);
+ return new (Mem) CXXDependentScopeMemberExpr(EmptyShell(), HasQualifier,
+ NumUnqualifiedLookups,
+ HasTemplateKWAndArgsInfo);
}
CXXThisExpr *CXXThisExpr::Create(const ASTContext &Ctx, SourceLocation L,
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 43c046a46ade3..631d32427a1d7 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -598,8 +598,7 @@ class CXXNameMangler {
ArrayRef<DeclAccessPair> UnqualifiedLookups,
DeclarationName name,
const TemplateArgumentLoc *TemplateArgs,
- unsigned NumTemplateArgs,
- unsigned knownArity);
+ unsigned NumTemplateArgs, unsigned knownArity);
void mangleCastExpression(const Expr *E, StringRef CastEncoding);
void mangleInitListElements(const InitListExpr *InitList);
void mangleRequirement(SourceLocation RequiresExprLoc,
@@ -4491,14 +4490,11 @@ void CXXNameMangler::mangleMemberExprBase(const Expr *Base, bool IsArrow) {
}
/// Mangles a member expression.
-void CXXNameMangler::mangleMemberExpr(const Expr *base,
- bool isArrow,
- NestedNameSpecifier *qualifier,
- ArrayRef<DeclAccessPair> UnqualifiedLookups,
- DeclarationName member,
- const TemplateArgumentLoc *TemplateArgs,
- unsigned NumTemplateArgs,
- unsigned arity) {
+void CXXNameMangler::mangleMemberExpr(
+ const Expr *base, bool isArrow, NestedNameSpecifier *qualifier,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups, DeclarationName member,
+ const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs,
+ unsigned arity) {
// <expression> ::= dt <expression> <unresolved-name>
// ::= pt <expression> <unresolved-name>
if (base)
@@ -4979,11 +4975,9 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::MemberExprClass: {
NotPrimaryExpr();
const MemberExpr *ME = cast<MemberExpr>(E);
- mangleMemberExpr(ME->getBase(), ME->isArrow(),
- ME->getQualifier(), std::nullopt,
- ME->getMemberDecl()->getDeclName(),
- ME->getTemplateArgs(), ME->getNumTemplateArgs(),
- Arity);
+ mangleMemberExpr(ME->getBase(), ME->isArrow(), ME->getQualifier(),
+ std::nullopt, ME->getMemberDecl()->getDeclName(),
+ ME->getTemplateArgs(), ME->getNumTemplateArgs(), Arity);
break;
}
@@ -4992,9 +4986,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
const UnresolvedMemberExpr *ME = cast<UnresolvedMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(), std::nullopt,
- ME->getMemberName(),
- ME->getTemplateArgs(), ME->getNumTemplateArgs(),
- Arity);
+ ME->getMemberName(), ME->getTemplateArgs(),
+ ME->getNumTemplateArgs(), Arity);
break;
}
@@ -5004,10 +4997,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
= cast<CXXDependentScopeMemberExpr>(E);
mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(),
ME->isArrow(), ME->getQualifier(),
- ME->unqualified_lookups(),
- ME->getMember(),
- ME->getTemplateArgs(), ME->getNumTemplateArgs(),
- Arity);
+ ME->unqualified_lookups(), ME->getMember(),
+ ME->getTemplateArgs(), ME->getNumTemplateArgs(), Arity);
break;
}
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index 99c5476392fc9..fd3f68bfbd0a5 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -390,7 +390,8 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD,
/// (e.g., Base::), perform name lookup for that identifier as a
/// nested-name-specifier within the given scope, and return the result of that
/// name lookup.
-bool Sema::LookupFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS, UnresolvedSetImpl &R) {
+bool Sema::LookupFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS,
+ UnresolvedSetImpl &R) {
if (!S)
return false;
@@ -533,7 +534,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
if (S) {
LookupName(Found, S);
} else if (LookupFirstQualifierInScope &&
- !SS.getUnqualifiedLookups().empty()) {
+ !SS.getUnqualifiedLookups().empty()) {
Found.addAllDecls(SS.getUnqualifiedLookups());
Found.resolveKind();
}
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index dbe0f0cf11b90..fa0eb1d2afbee 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -306,8 +306,8 @@ static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc,
// FIXME: Fix BuildMemberReferenceExpr to take a const CXXScopeSpec&.
CXXScopeSpec SS;
ExprResult Result = S.BuildMemberReferenceExpr(
- Base, Base->getType(), Loc, /*IsPtr=*/false, SS,
- SourceLocation(), NameInfo, /*TemplateArgs=*/nullptr,
+ Base, Base->getType(), Loc, /*IsPtr=*/false, SS, SourceLocation(),
+ NameInfo, /*TemplateArgs=*/nullptr,
/*Scope=*/nullptr);
if (Result.isInvalid())
return ExprError();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 29ff6e2501b5b..4a77b40a3acd3 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5012,15 +5012,12 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
MemberLookup.addDecl(Indirect ? cast<ValueDecl>(Indirect)
: cast<ValueDecl>(Field), AS_public);
MemberLookup.resolveKind();
- ExprResult CtorArg
- = SemaRef.BuildMemberReferenceExpr(MemberExprBase,
- ParamType, Loc,
- /*IsArrow=*/false,
- SS,
- /*TemplateKWLoc=*/SourceLocation(),
- MemberLookup,
- /*TemplateArgs=*/nullptr,
- /*S=*/nullptr);
+ ExprResult CtorArg = SemaRef.BuildMemberReferenceExpr(
+ MemberExprBase, ParamType, Loc,
+ /*IsArrow=*/false, SS,
+ /*TemplateKWLoc=*/SourceLocation(), MemberLookup,
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
if (CtorArg.isInvalid())
return true;
@@ -14544,9 +14541,10 @@ class MemberBuilder: public ExprBuilder {
public:
Expr *build(Sema &S, SourceLocation Loc) const override {
return assertNotNull(S.BuildMemberReferenceExpr(
- Builder.build(S, Loc), Type, Loc, IsArrow, SS,
- /*TemplateKwLoc=*/SourceLocation(), MemberLookup,
- /*TemplateArgs=*/nullptr, /*S=*/nullptr).get());
+ Builder.build(S, Loc), Type, Loc, IsArrow, SS,
+ /*TemplateKwLoc=*/SourceLocation(), MemberLookup,
+ /*TemplateArgs=*/nullptr, /*S=*/nullptr)
+ .get());
}
MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
@@ -14752,12 +14750,11 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
Loc);
// Create the reference to operator=.
- ExprResult OpEqualRef
- = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*IsArrow=*/false,
- SS, /*TemplateKWLoc=*/SourceLocation(),
- OpLookup,
- /*TemplateArgs=*/nullptr, /*S*/nullptr,
- /*SuppressQualifierCheck=*/true);
+ ExprResult OpEqualRef = S.BuildMemberReferenceExpr(
+ To.build(S, Loc), T, Loc, /*IsArrow=*/false, SS,
+ /*TemplateKWLoc=*/SourceLocation(), OpLookup,
+ /*TemplateArgs=*/nullptr, /*S*/ nullptr,
+ /*SuppressQualifierCheck=*/true);
if (OpEqualRef.isInvalid())
return StmtError();
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 5efa5d0d1421e..038b3e9ceadb3 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -553,9 +553,8 @@ static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy,
}
ExprResult
-Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType,
- bool IsArrow, SourceLocation OpLoc,
- const CXXScopeSpec &SS,
+Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, bool IsArrow,
+ SourceLocation OpLoc, const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
const DeclarationNameInfo &NameInfo,
const TemplateArgumentListInfo *TemplateArgs) {
@@ -839,11 +838,9 @@ ExprResult Sema::BuildMemberReferenceExpr(
BaseType = Base->getType();
}
- return BuildMemberReferenceExpr(Base, BaseType,
- OpLoc, IsArrow, SS, TemplateKWLoc,
- R, TemplateArgs, S,
- /*SuppressQualifierCheck=*/false,
- ExtraArgs);
+ return BuildMemberReferenceExpr(Base, BaseType, OpLoc, IsArrow, SS,
+ TemplateKWLoc, R, TemplateArgs, S,
+ /*SuppressQualifierCheck=*/false, ExtraArgs);
}
ExprResult
@@ -981,16 +978,11 @@ static bool IsInFnTryBlockHandler(const Scope *S) {
return false;
}
-ExprResult
-Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
- SourceLocation OpLoc, bool IsArrow,
- const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- LookupResult &R,
- const TemplateArgumentListInfo *TemplateArgs,
- const Scope *S,
- bool SuppressQualifierCheck,
- ActOnMemberAccessExtraArgs *ExtraArgs) {
+ExprResult Sema::BuildMemberReferenceExpr(
+ Expr *BaseExpr, QualType BaseExprType, SourceLocation OpLoc, bool IsArrow,
+ const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs, const Scope *S,
+ bool SuppressQualifierCheck, ActOnMemberAccessExtraArgs *ExtraArgs) {
assert(!SS.isInvalid() && "nested-name-specifier cannot be invalid");
// If the member wasn't found in the current instantiation, or if the
// arrow operator was used with a dependent non-pointer object expression,
@@ -1206,9 +1198,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
// Non-dependent member, but dependent template arguments.
if (!VDecl.get())
- return ActOnDependentMemberExpr(
- BaseExpr, BaseExpr->getType(), IsArrow, OpLoc, SS, TemplateKWLoc,
- MemberNameInfo, TemplateArgs);
+ return ActOnDependentMemberExpr(BaseExpr, BaseExpr->getType(), IsArrow,
+ OpLoc, SS, TemplateKWLoc, MemberNameInfo,
+ TemplateArgs);
VarDecl *Var = cast<VarDecl>(VDecl.get());
if (!Var->getTemplateSpecializationKind())
@@ -1793,7 +1785,8 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2);
UnresolvedSet<4> UnqualifiedLookups;
- if (SS.isValid() && LookupFirstQualifierInScope(S, SS.getScopeRep(), UnqualifiedLookups)) {
+ if (SS.isValid() &&
+ LookupFirstQualifierInScope(S, SS.getScopeRep(), UnqualifiedLookups)) {
SS.setUnqualifiedLookups(UnqualifiedLookups.pairs());
}
// This is a postfix expression, so get rid of ParenListExprs.
@@ -1803,8 +1796,8 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
ExprResult Res = BuildMemberReferenceExpr(
- Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc,
- NameInfo, TemplateArgs, S, &ExtraArgs);
+ Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, NameInfo,
+ TemplateArgs, S, &ExtraArgs);
if (!Res.isInvalid() && isa<MemberExpr>(Res.get()))
CheckMemberAccessOfNoDeref(cast<MemberExpr>(Res.get()));
@@ -1952,9 +1945,8 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
baseExpr = BuildCXXThisExpr(loc, ThisTy, /*IsImplicit=*/true);
}
- return BuildMemberReferenceExpr(
- baseExpr, ThisTy,
- /*OpLoc=*/SourceLocation(),
- /*IsArrow=*/!getLangOpts().HLSL, SS,
- TemplateKWLoc, R, TemplateArgs, S);
+ return BuildMemberReferenceExpr(baseExpr, ThisTy,
+ /*OpLoc=*/SourceLocation(),
+ /*IsArrow=*/!getLangOpts().HLSL, SS,
+ TemplateKWLoc, R, TemplateArgs, S);
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6f066235461b0..a7f4f8454fe09 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -16217,12 +16217,11 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc,
CandidateSet->clear(OverloadCandidateSet::CSK_Normal);
if (!MemberLookup.empty()) {
- ExprResult MemberRef =
- BuildMemberReferenceExpr(Range, Range->getType(), Loc,
- /*IsPtr=*/false, /*SS=*/CXXScopeSpec(),
- /*TemplateKWLoc=*/SourceLocation(),
- MemberLookup,
- /*TemplateArgs=*/nullptr, S);
+ ExprResult MemberRef = BuildMemberReferenceExpr(
+ Range, Range->getType(), Loc,
+ /*IsPtr=*/false, /*SS=*/CXXScopeSpec(),
+ /*TemplateKWLoc=*/SourceLocation(), MemberLookup,
+ /*TemplateArgs=*/nullptr, S);
if (MemberRef.isInvalid()) {
*CallExpr = ExprError();
return FRS_DiagnosticIssued;
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp
index 9b1e49620173d..da2e99b6bc00c 100644
--- a/clang/lib/Sema/SemaStmtAsm.cpp
+++ b/clang/lib/Sema/SemaStmtAsm.cpp
@@ -900,7 +900,8 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
return CXXDependentScopeMemberExpr::Create(
Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(),
SourceLocation(),
- /*UnqualifiedLookups=*/std::nullopt, NameInfo, /*TemplateArgs=*/nullptr);
+ /*UnqualifiedLookups=*/std::nullopt, NameInfo,
+ /*TemplateArgs=*/nullptr);
}
const RecordType *RT = T->getAs<RecordType>();
@@ -924,7 +925,7 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
// Make an Expr to thread through OpDecl.
ExprResult Result = BuildMemberReferenceExpr(
E, E->getType(), AsmLoc, /*IsArrow=*/false, /*SS=*/CXXScopeSpec(),
- /*TemplateKWLoc*/SourceLocation(), FieldResult,
+ /*TemplateKWLoc*/ SourceLocation(), FieldResult,
/*TemplateArgs=*/nullptr, /*S=*/nullptr);
return Result;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 57fe755ae8fc0..4f38af1187896 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -472,7 +472,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
if (S) {
LookupName(Found, S);
} else if (LookupFirstQualifierInScope &&
- !SS.getUnqualifiedLookups().empty()) {
+ !SS.getUnqualifiedLookups().empty()) {
Found.addAllDecls(SS.getUnqualifiedLookups());
Found.resolveKind();
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 73ca3a0fde478..dcbe8aff6127d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1545,11 +1545,10 @@ namespace {
NestedNameSpecifierLoc QualifierLoc,
QualType T);
- TemplateName
- TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType = QualType(),
- bool AllowInjectedClassName = false);
+ TemplateName TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
+ SourceLocation NameLoc,
+ QualType ObjectType = QualType(),
+ bool AllowInjectedClassName = false);
const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index e421510105c69..f4e7ccdf309af 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -541,10 +541,9 @@ class TreeTransform {
/// By default, transforms all of the types and declarations within the
/// nested-name-specifier. Subclasses may override this function to provide
/// alternate behavior.
- NestedNameSpecifierLoc
- TransformNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
- QualType ObjectType = QualType(),
- ArrayRef<DeclAccessPair> UnqualifiedLookups = std::nullopt);
+ NestedNameSpecifierLoc TransformNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS, QualType ObjectType = QualType(),
+ ArrayRef<DeclAccessPair> UnqualifiedLookups = std::nullopt);
/// Transform the given declaration name.
///
@@ -585,11 +584,10 @@ class TreeTransform {
/// By default, transforms the template name by transforming the declarations
/// and nested-name-specifiers that occur within the template name.
/// Subclasses may override this function to provide alternate behavior.
- TemplateName
- TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType = QualType(),
- bool AllowInjectedClassName = false);
+ TemplateName TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
+ SourceLocation NameLoc,
+ QualType ObjectType = QualType(),
+ bool AllowInjectedClassName = false);
/// Transform the given template argument.
///
@@ -1139,8 +1137,7 @@ class TreeTransform {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
TemplateName InstName = getDerived().RebuildTemplateName(
- SS, TemplateKWLoc, *Name, NameLoc, QualType(),
- AllowInjectedClassName);
+ SS, TemplateKWLoc, *Name, NameLoc, QualType(), AllowInjectedClassName);
if (InstName.isNull())
return QualType();
@@ -2847,15 +2844,14 @@ class TreeTransform {
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc,
- bool isArrow,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &MemberNameInfo,
- ValueDecl *Member,
- NamedDecl *FoundDecl,
- const TemplateArgumentListInfo *ExplicitTemplateArgs,
- ArrayRef<DeclAccessPair> UnqualifiedLookups) {
+ ExprResult
+ RebuildMemberExpr(Expr *Base, SourceLocation OpLoc, bool isArrow,
+ NestedNameSpecifierLoc QualifierLoc,
+ SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &MemberNameInfo,
+ ValueDecl *Member, NamedDecl *FoundDecl,
+ const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups) {
ExprResult BaseResult = getSema().PerformMemberExprBaseConversion(Base,
isArrow);
if (!Member->getDeclName()) {
@@ -2922,9 +2918,9 @@ class TreeTransform {
}
return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow,
- SS, TemplateKWLoc,
- R, ExplicitTemplateArgs,
- /*S*/nullptr);
+ SS, TemplateKWLoc, R,
+ ExplicitTemplateArgs,
+ /*S*/ nullptr);
}
/// Build a new binary operator expression.
@@ -2999,7 +2995,7 @@ class TreeTransform {
return getSema().BuildMemberReferenceExpr(
Base, Base->getType(), OpLoc, IsArrow, SS,
/*TemplateKWLoc=*/SourceLocation(), NameInfo,
- /*TemplateArgs=*/ nullptr, /*S=*/nullptr);
+ /*TemplateArgs=*/nullptr, /*S=*/nullptr);
}
/// Build a new initializer list expression.
@@ -3567,46 +3563,37 @@ class TreeTransform {
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE,
- QualType BaseType,
- bool IsArrow,
- SourceLocation OperatorLoc,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ArrayRef<DeclAccessPair> UnqualifiedLookups,
- const DeclarationNameInfo &MemberNameInfo,
- const TemplateArgumentListInfo *TemplateArgs) {
+ ExprResult RebuildCXXDependentScopeMemberExpr(
+ Expr *BaseE, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups,
+ const DeclarationNameInfo &MemberNameInfo,
+ const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
SS.setUnqualifiedLookups(UnqualifiedLookups);
- return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
- OperatorLoc, IsArrow,
- SS, TemplateKWLoc,
- MemberNameInfo,
- TemplateArgs, /*S=*/nullptr);
+ return SemaRef.BuildMemberReferenceExpr(
+ BaseE, BaseType, OperatorLoc, IsArrow, SS, TemplateKWLoc,
+ MemberNameInfo, TemplateArgs, /*S=*/nullptr);
}
/// Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
- ExprResult RebuildUnresolvedMemberExpr(Expr *BaseE, QualType BaseType,
- SourceLocation OperatorLoc,
- bool IsArrow,
- NestedNameSpecifierLoc QualifierLoc,
- SourceLocation TemplateKWLoc,
- ArrayRef<DeclAccessPair> UnqualifiedLookups,
- LookupResult &R,
- const TemplateArgumentListInfo *TemplateArgs) {
+ ExprResult RebuildUnresolvedMemberExpr(
+ Expr *BaseE, QualType BaseType, SourceLocation OperatorLoc, bool IsArrow,
+ NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
+ ArrayRef<DeclAccessPair> UnqualifiedLookups, LookupResult &R,
+ const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
SS.setUnqualifiedLookups(UnqualifiedLookups);
- return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType,
- OperatorLoc, IsArrow,
- SS, TemplateKWLoc,
- R, TemplateArgs, /*S=*/nullptr);
+ return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, OperatorLoc,
+ IsArrow, SS, TemplateKWLoc, R,
+ TemplateArgs, /*S=*/nullptr);
}
/// Build a new noexcept expression.
@@ -3841,13 +3828,12 @@ class TreeTransform {
SourceLocation PropertyLoc) {
CXXScopeSpec SS;
DeclarationNameInfo NameInfo(Property->getDeclName(), PropertyLoc);
- return getSema().BuildMemberReferenceExpr(BaseArg, BaseArg->getType(),
- /*FIXME:*/PropertyLoc,
- /*IsArrow=*/false,
- SS, /*TemplateKWLoc=*/SourceLocation(),
- NameInfo,
- /*TemplateArgs=*/nullptr,
- /*S=*/nullptr);
+ return getSema().BuildMemberReferenceExpr(
+ BaseArg, BaseArg->getType(),
+ /*FIXME:*/ PropertyLoc,
+ /*IsArrow=*/false, SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo,
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
/// Build a new Objective-C property reference expression.
@@ -3874,12 +3860,11 @@ class TreeTransform {
SourceLocation OpLoc, bool IsArrow) {
CXXScopeSpec SS;
DeclarationNameInfo NameInfo(&getSema().Context.Idents.get("isa"), IsaLoc);
- return getSema().BuildMemberReferenceExpr(BaseArg, BaseArg->getType(),
- OpLoc, IsArrow,
- SS, /*TemplateKWLoc=*/SourceLocation(),
- NameInfo,
- /*TemplateArgs=*/nullptr,
- /*S=*/nullptr);
+ return getSema().BuildMemberReferenceExpr(
+ BaseArg, BaseArg->getType(), OpLoc, IsArrow, SS,
+ /*TemplateKWLoc=*/SourceLocation(), NameInfo,
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
/// Build a new shuffle vector expression.
@@ -4035,16 +4020,14 @@ class TreeTransform {
}
private:
- TypeLoc TransformTypeInObjectScope(TypeLoc TL,
- QualType ObjectType,
+ TypeLoc TransformTypeInObjectScope(TypeLoc TL, QualType ObjectType,
CXXScopeSpec &SS);
TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
QualType ObjectType,
CXXScopeSpec &SS);
- TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL,
- QualType ObjectType,
+ TypeSourceInfo *TransformTSIInObjectScope(TypeLoc TL, QualType ObjectType,
CXXScopeSpec &SS);
QualType TransformDependentNameType(TypeLocBuilder &TLB,
@@ -4386,8 +4369,8 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
Q.getLocalBeginLoc(), Q.getLocalEndLoc(),
ObjectType);
if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/nullptr, IdInfo,
- /*EnteringContext=*/false,
- SS, /*ErrorRecoveryLookup=*/false))
+ /*EnteringContext=*/false, SS,
+ /*ErrorRecoveryLookup=*/false))
return NestedNameSpecifierLoc();
break;
}
@@ -4541,13 +4524,10 @@ ::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) {
llvm_unreachable("Unknown name kind.");
}
-template<typename Derived>
-TemplateName
-TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
- TemplateName Name,
- SourceLocation NameLoc,
- QualType ObjectType,
- bool AllowInjectedClassName) {
+template <typename Derived>
+TemplateName TreeTransform<Derived>::TransformTemplateName(
+ CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
+ QualType ObjectType, bool AllowInjectedClassName) {
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl();
assert(Template && "qualified template name must refer to a template");
@@ -4583,12 +4563,9 @@ TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS,
SourceLocation TemplateKWLoc = NameLoc;
if (DTN->isIdentifier()) {
- return getDerived().RebuildTemplateName(SS,
- TemplateKWLoc,
- *DTN->getIdentifier(),
- NameLoc,
- ObjectType,
- AllowInjectedClassName);
+ return getDerived().RebuildTemplateName(
+ SS, TemplateKWLoc, *DTN->getIdentifier(), NameLoc, ObjectType,
+ AllowInjectedClassName);
}
return getDerived().RebuildTemplateName(SS, TemplateKWLoc,
@@ -5132,26 +5109,22 @@ QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T,
return SemaRef.BuildQualifiedType(T, Loc, Quals);
}
-template<typename Derived>
-TypeLoc
-TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
- QualType ObjectType,
- CXXScopeSpec &SS) {
+template <typename Derived>
+TypeLoc TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL,
+ QualType ObjectType,
+ CXXScopeSpec &SS) {
if (getDerived().AlreadyTransformed(TL.getType()))
return TL;
- TypeSourceInfo *TSI =
- TransformTSIInObjectScope(TL, ObjectType, SS);
+ TypeSourceInfo *TSI = TransformTSIInObjectScope(TL, ObjectType, SS);
if (TSI)
return TSI->getTypeLoc();
return TypeLoc();
}
-template<typename Derived>
-TypeSourceInfo *
-TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo,
- QualType ObjectType,
- CXXScopeSpec &SS) {
+template <typename Derived>
+TypeSourceInfo *TreeTransform<Derived>::TransformTypeInObjectScope(
+ TypeSourceInfo *TSInfo, QualType ObjectType, CXXScopeSpec &SS) {
if (getDerived().AlreadyTransformed(TSInfo->getType()))
return TSInfo;
@@ -5183,13 +5156,11 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
DependentTemplateSpecializationTypeLoc SpecTL =
TL.castAs<DependentTemplateSpecializationTypeLoc>();
- TemplateName Template
- = getDerived().RebuildTemplateName(SS,
- SpecTL.getTemplateKeywordLoc(),
- *SpecTL.getTypePtr()->getIdentifier(),
- SpecTL.getTemplateNameLoc(),
- ObjectType,
- /*AllowInjectedClassName=*/true);
+ TemplateName Template = getDerived().RebuildTemplateName(
+ SS, SpecTL.getTemplateKeywordLoc(),
+ *SpecTL.getTypePtr()->getIdentifier(), SpecTL.getTemplateNameLoc(),
+ ObjectType,
+ /*AllowInjectedClassName=*/true);
if (Template.isNull())
return nullptr;
@@ -12242,16 +12213,11 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {
return ExprError();
}
- return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc,
- E->isArrow(),
- QualifierLoc,
- TemplateKWLoc,
- MemberNameInfo,
- Member,
- FoundDecl,
- (E->hasExplicitTemplateArgs()
- ? &TransArgs : nullptr),
- UnqualifiedLookups);
+ return getDerived().RebuildMemberExpr(
+ Base.get(), FakeOperatorLoc, E->isArrow(), QualifierLoc, TemplateKWLoc,
+ MemberNameInfo, Member, FoundDecl,
+ (E->hasExplicitTemplateArgs() ? &TransArgs : nullptr),
+ UnqualifiedLookups);
}
template<typename Derived>
@@ -13373,9 +13339,8 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
PseudoDestructorTypeStorage Destroyed;
if (E->getDestroyedTypeInfo()) {
- TypeSourceInfo *DestroyedTypeInfo
- = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(),
- ObjectType, SS);
+ TypeSourceInfo *DestroyedTypeInfo = getDerived().TransformTypeInObjectScope(
+ E->getDestroyedTypeInfo(), ObjectType, SS);
if (!DestroyedTypeInfo)
return ExprError();
Destroyed = DestroyedTypeInfo;
@@ -13401,7 +13366,7 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
if (E->getScopeTypeInfo()) {
CXXScopeSpec EmptySS;
ScopeTypeInfo = getDerived().TransformTypeInObjectScope(
- E->getScopeTypeInfo(), ObjectType, EmptySS);
+ E->getScopeTypeInfo(), ObjectType, EmptySS);
if (!ScopeTypeInfo)
return ExprError();
}
@@ -14663,28 +14628,26 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
ObjectType = BaseType->castAs<PointerType>()->getPointeeType();
}
- #if 0
+#if 0
// Transform the first part of the nested-name-specifier that qualifies
// the member name.
NamedDecl *FirstQualifierInScope
= getDerived().TransformFirstQualifierInScope(
E->getFirstQualifierFoundInScope(),
E->getQualifierLoc().getBeginLoc());
- #endif
+#endif
UnresolvedSet<4> UnqualifiedLookups;
for (auto D : E->unqualified_lookups()) {
if (NamedDecl *InstD = getDerived().TransformFirstQualifierInScope(
- D.getDecl(), E->getQualifierLoc().getBeginLoc()))
+ D.getDecl(), E->getQualifierLoc().getBeginLoc()))
UnqualifiedLookups.addDecl(InstD);
}
NestedNameSpecifierLoc QualifierLoc;
if (E->getQualifier()) {
- QualifierLoc
- = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc(),
- ObjectType,
- UnqualifiedLookups.pairs());
+ QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(
+ E->getQualifierLoc(), ObjectType, UnqualifiedLookups.pairs());
if (!QualifierLoc)
return ExprError();
}
@@ -14703,23 +14666,16 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
if (!E->hasExplicitTemplateArgs()) {
// This is a reference to a member without an explicitly-specified
// template argument list. Optimize for this common case.
- if (!getDerived().AlwaysRebuild() &&
- Base.get() == OldBase &&
- BaseType == E->getBaseType() &&
- QualifierLoc == E->getQualifierLoc() &&
+ if (!getDerived().AlwaysRebuild() && Base.get() == OldBase &&
+ BaseType == E->getBaseType() && QualifierLoc == E->getQualifierLoc() &&
NameInfo.getName() == E->getMember() &&
UnqualifiedLookups.pairs() == E->unqualified_lookups())
return E;
- return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
- BaseType,
- E->isArrow(),
- E->getOperatorLoc(),
- QualifierLoc,
- TemplateKWLoc,
- UnqualifiedLookups.pairs(),
- NameInfo,
- /*TemplateArgs*/nullptr);
+ return getDerived().RebuildCXXDependentScopeMemberExpr(
+ Base.get(), BaseType, E->isArrow(), E->getOperatorLoc(), QualifierLoc,
+ TemplateKWLoc, UnqualifiedLookups.pairs(), NameInfo,
+ /*TemplateArgs*/ nullptr);
}
TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
@@ -14728,15 +14684,9 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
TransArgs))
return ExprError();
- return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(),
- BaseType,
- E->isArrow(),
- E->getOperatorLoc(),
- QualifierLoc,
- TemplateKWLoc,
- UnqualifiedLookups.pairs(),
- NameInfo,
- &TransArgs);
+ return getDerived().RebuildCXXDependentScopeMemberExpr(
+ Base.get(), BaseType, E->isArrow(), E->getOperatorLoc(), QualifierLoc,
+ TemplateKWLoc, UnqualifiedLookups.pairs(), NameInfo, &TransArgs);
}
template <typename Derived>
@@ -16158,14 +16108,10 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
TemplateName(Template));
}
-template<typename Derived>
-TemplateName
-TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const IdentifierInfo &Name,
- SourceLocation NameLoc,
- QualType ObjectType,
- bool AllowInjectedClassName) {
+template <typename Derived>
+TemplateName TreeTransform<Derived>::RebuildTemplateName(
+ CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const IdentifierInfo &Name,
+ SourceLocation NameLoc, QualType ObjectType, bool AllowInjectedClassName) {
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
@@ -16320,12 +16266,10 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base,
}
SourceLocation TemplateKWLoc; // FIXME: retrieve it from caller.
- return getSema().BuildMemberReferenceExpr(Base, BaseType,
- OperatorLoc, isArrow,
- SS, TemplateKWLoc,
- NameInfo,
- /*TemplateArgs=*/nullptr,
- /*S=*/nullptr);
+ return getSema().BuildMemberReferenceExpr(
+ Base, BaseType, OperatorLoc, isArrow, SS, TemplateKWLoc, NameInfo,
+ /*TemplateArgs=*/nullptr,
+ /*S=*/nullptr);
}
template<typename Derived>
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 1054abf3170a1..90645b5b5eaec 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1989,11 +1989,13 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
unsigned NumUnqualifiedLookups = Record.readInt();
unsigned NumTemplateArgs = Record.readInt();
E->CXXDependentScopeMemberExprBits.HasQualifier = HasQualifier;
- E->CXXDependentScopeMemberExprBits.NumUnqualifiedLookups = NumUnqualifiedLookups;
+ E->CXXDependentScopeMemberExprBits.NumUnqualifiedLookups =
+ NumUnqualifiedLookups;
E->CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo = HasTemplateInfo;
E->BaseType = Record.readType();
- E->CXXDependentScopeMemberExprBits.IsArrow = CurrentUnpackingBits->getNextBit();
+ E->CXXDependentScopeMemberExprBits.IsArrow =
+ CurrentUnpackingBits->getNextBit();
if (CurrentUnpackingBits->getNextBit())
E->Base = Record.readSubExpr();
@@ -2010,7 +2012,9 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
for (unsigned I = 0; I != NumUnqualifiedLookups; ++I) {
auto *FoundD = Record.readDeclAs<NamedDecl>();
auto AS = (AccessSpecifier)Record.readInt();
- E->getTrailingObjects<DeclAccessPair>()[I] = DeclAccessPair::make(FoundD, AS);;
+ E->getTrailingObjects<DeclAccessPair>()[I] =
+ DeclAccessPair::make(FoundD, AS);
+ ;
}
if (HasTemplateInfo)
@@ -2018,8 +2022,7 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
-
- #if 0
+#if 0
unsigned NumTemplateArgs = Record.readInt();
CurrentUnpackingBits.emplace(Record.readInt());
bool HasTemplateKWAndArgsInfo = CurrentUnpackingBits->getNextBit();
@@ -2056,7 +2059,7 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
*E->getTrailingObjects<NamedDecl *>() = readDeclAs<NamedDecl>();
E->MemberNameInfo = Record.readDeclarationNameInfo();
- #endif
+#endif
}
void
@@ -4094,7 +4097,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: {
- #if 0
+#if 0
unsigned NumTemplateArgs = Record[ASTStmtReader::NumExprFields];
BitsUnpacker DependentScopeMemberBits(
Record[ASTStmtReader::NumExprFields + 1]);
@@ -4102,16 +4105,17 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
bool HasFirstQualifierFoundInScope =
DependentScopeMemberBits.getNextBit();
- #endif
- BitsUnpacker DependentScopeMemberBits(Record[ASTStmtReader::NumExprFields]);
+#endif
+ BitsUnpacker DependentScopeMemberBits(
+ Record[ASTStmtReader::NumExprFields]);
bool HasQualifier = DependentScopeMemberBits.getNextBit();
bool HasTemplateInfo = DependentScopeMemberBits.getNextBit();
unsigned NumUnqualifiedLookups = Record[ASTStmtReader::NumExprFields + 1];
unsigned NumTemplateArgs = Record[ASTStmtReader::NumExprFields + 2];
S = CXXDependentScopeMemberExpr::CreateEmpty(
- Context, HasQualifier, NumUnqualifiedLookups,
- HasTemplateInfo, NumTemplateArgs);
+ Context, HasQualifier, NumUnqualifiedLookups, HasTemplateInfo,
+ NumTemplateArgs);
break;
}
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index bb117d1d2a7d2..42d83cd2d8397 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2012,7 +2012,7 @@ void ASTStmtWriter::VisitCXXDependentScopeMemberExpr(
AddTemplateKWAndArgsInfo(*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
E->getTrailingObjects<TemplateArgumentLoc>());
- #if 0
+#if 0
// Don't emit anything here (or if you do you will have to update
// the corresponding deserialization function).
Record.push_back(E->getNumTemplateArgs());
@@ -2041,7 +2041,7 @@ void ASTStmtWriter::VisitCXXDependentScopeMemberExpr(
Record.AddDeclRef(E->getFirstQualifierFoundInScope());
Record.AddDeclarationNameInfo(E->MemberNameInfo);
- #endif
+#endif
Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
}
>From dd60ceb57dc1ad13729c2e8c7a781e139929b965 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 31 May 2024 14:35:35 -0400
Subject: [PATCH 05/19] [FOLD] add tests
---
.../basic.lookup.qual.general/p3-example3.cpp | 27 ++
.../basic.lookup.qual.general/p3.cpp | 71 +++++
clang/test/CXX/temp/temp.names/p3-23.cpp | 250 ++++++++++++++++++
3 files changed, 348 insertions(+)
create mode 100644 clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3-example3.cpp
create mode 100644 clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
create mode 100644 clang/test/CXX/temp/temp.names/p3-23.cpp
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3-example3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3-example3.cpp
new file mode 100644
index 0000000000000..423eacd21d441
--- /dev/null
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3-example3.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++23 %s -verify
+
+int f();
+
+struct A {
+ int B, C; // expected-note {{declared as a non-template here}}
+ template<int> using D = void;
+ using T = void;
+ void f();
+};
+
+using B = A;
+template<int> using C = A;
+template<int> using D = A;
+template<int> using X = A;
+
+template<class T>
+void g(T *p) {
+ p->X<0>::f(); // expected-error {{no member named 'X' in 'A'}}
+ p->template X<0>::f();
+ p->B::f();
+ p->template C<0>::f(); // expected-error {{'C' following the 'template' keyword does not refer to a template}}
+ p->template D<0>::f(); // expected-error {{type 'template D<0>' (aka 'void') cannot be used prior to '::' because it has no members}}
+ p->T::f(); // expected-error {{'A::T' (aka 'void') is not a class, namespace, or enumeration}}
+}
+
+template void g(A*); // expected-note {{in instantiation of}}
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
new file mode 100644
index 0000000000000..e3c4aae984aeb
--- /dev/null
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -std=c++23 -Wno-unused %s -verify
+
+struct A {
+ int x;
+
+ template<typename T>
+ using C = A;
+};
+
+using B = A;
+
+template<typename T>
+using D = A;
+
+using E = void;
+
+struct F : A {
+ void non_template() {
+ this->x;
+ this->A::x;
+ this->B::x;
+ this->C<int>::x;
+ this->D<int>::x;
+ this->E::x; // expected-error {{'E' (aka 'void') is not a class, namespace, or enumeration}}
+ }
+};
+
+template<typename T>
+void not_instantiated(T t) {
+ t.x;
+ t.A::x;
+ t.B::x;
+ t.C<int>::x; // expected-error {{use 'template' keyword to treat 'C' as a dependent template name}}
+ t.template C<int>::x;
+ t.D<int>::x; // expected-error {{use 'template' keyword to treat 'D' as a dependent template name}}
+ t.template D<int>::x;
+ t.E::x;
+}
+
+template<typename T>
+void instantiated_valid(T t) {
+ t.x;
+ t.A::x;
+ t.B::x;
+ t.template C<int>::x;
+ t.template D<int>::x;
+ t.E::x;
+}
+
+template<typename T>
+void instantiated_invalid(T t) {
+ t.x;
+ t.A::x;
+ t.B::x; // expected-error {{'Invalid::B' (aka 'void') is not a class, namespace, or enumeration}}
+ t.template C<int>::x;
+ t.template D<int>::x; // expected-error {{'D' following the 'template' keyword does not refer to a template}}
+ t.E::x; // expected-error {{'E' (aka 'void') is not a class, namespace, or enumeration}}
+}
+
+struct Valid : A {
+ using E = A;
+};
+
+template void instantiated_valid(Valid);
+
+struct Invalid : A {
+ using B = void;
+ using D = A; // expected-note {{declared as a non-template here}}
+};
+
+template void instantiated_invalid(Invalid); // expected-note {{in instantiation of}}
diff --git a/clang/test/CXX/temp/temp.names/p3-23.cpp b/clang/test/CXX/temp/temp.names/p3-23.cpp
new file mode 100644
index 0000000000000..5119cd4ecac9f
--- /dev/null
+++ b/clang/test/CXX/temp/temp.names/p3-23.cpp
@@ -0,0 +1,250 @@
+// RUN: %clang_cc1 -std=c++23 %s -verify
+
+namespace FoundNothing {
+ template<typename T>
+ void f0(T &t) {
+ t.x<0;
+ t.x<0>; // expected-error {{expected expression}}
+ t.x<0>1;
+ }
+
+ template<typename T>
+ struct A {
+ void f1() {
+ this->x<0; // expected-error {{no member named 'x' in 'A<T>'}}
+ this->x<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{no member named 'x' in 'A<T>'}}
+ this->x<0>1; // expected-error {{no member named 'x' in 'A<T>'}}
+ }
+ };
+} // namespace FoundNothing
+
+namespace FoundSingleNonTemplate {
+ void f0();
+
+ struct A0;
+
+ template<typename T>
+ void g0(T &t) {
+ t.f0<0;
+ t.f0<0>; // expected-error {{expected expression}}
+ t.f0<0> 1;
+
+ t.A0<0;
+ t.A0<0>; // expected-error {{expected expression}}
+ t.A0<0>1;
+ }
+
+ template<typename T>
+ struct B {
+ void f1();
+
+ struct A1; // expected-note 3{{member 'A1' declared here}}
+
+ void g1() {
+ this->f0<0; // expected-error {{no member named 'f0' in 'B<T>'}}
+ this->f0<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{no member named 'f0' in 'B<T>'}}
+ this->f0<0>1; // expected-error {{no member named 'f0' in 'B<T>'}}
+
+ this->A0<0; // expected-error {{no member named 'A0' in 'B<T>'}}
+ this->A0<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{no member named 'A0' in 'B<T>'}}
+ this->A0<0>1; // expected-error {{no member named 'A0' in 'B<T>'}}
+
+ this->f1<0; // expected-error {{reference to non-static member function must be called}}
+ this->f1<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{reference to non-static member function must be called}}
+ this->f1<0>1; // expected-error {{reference to non-static member function must be called}}
+
+ this->A1<0; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ this->A1<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ this->A1<0>1; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ }
+ };
+} // namespace FoundSingleNonTemplate
+
+namespace FoundSingleTemplate {
+ template<int I>
+ void f0();
+
+ template<int I>
+ struct A0;
+
+ template<typename T>
+ void g0(T &t) {
+ t.f0<0;
+ t.f0<0>; // expected-error {{expected expression}}
+ t.f0<0>1;
+
+ t.A0<0;
+ t.A0<0>; // expected-error {{expected expression}}
+ t.A0<0>1;
+ }
+
+ template<typename T>
+ struct B {
+ template<int I>
+ void f1(); // expected-note 2{{possible target for call}}
+
+ template<int I>
+ struct A1; // expected-note 2{{member 'A1' declared here}}
+
+ void g1() {
+ this->f0<0; // expected-error {{expected '>'}}
+ // expected-note at -1 {{to match this '<'}}
+ // expected-error at -2 {{expected unqualified-id}}
+ this->f0<0>; // expected-error {{no member named 'f0' in 'B<T>'}}
+ this->f0<0>1; // expected-error {{no member named 'f0' in 'B<T>'}}
+ // expected-error at -1 {{expected ';' after expression}}
+
+ this->A0<0; // expected-error {{expected '>'}}
+ // expected-note at -1 {{to match this '<'}}
+ // expected-error at -2 {{expected unqualified-id}}
+ this->A0<0>; // expected-error {{no member named 'A0' in 'B<T>'}}
+ this->A0<0>1; // expected-error {{no member named 'A0' in 'B<T>'}}
+ // expected-error at -1 {{expected ';' after expression}}
+
+
+ this->f1<0; // expected-error {{expected '>'}}
+ // expected-note at -1 {{to match this '<'}}
+ // expected-error at -2 {{expected unqualified-id}}
+ this->f1<0>; // expected-error {{reference to non-static member function must be called}}
+ this->f1<0>1; // expected-error {{reference to non-static member function must be called}}
+ // expected-error at -1 {{expected ';' after expression}}
+
+ this->A1<0; // expected-error {{expected '>'}}
+ // expected-note at -1 {{to match this '<'}}
+ // expected-error at -2 {{expected unqualified-id}}
+ this->A1<0>; // expected-error {{cannot refer to member 'A1' in 'B<T>' with '->'}}
+ this->A1<0>1; // expected-error {{cannot refer to member 'A1' in 'B<T>' with '->'}}
+ // expected-error at -1 {{expected ';' after expression}}
+ }
+ };
+} // namespace FoundSingleTemplate
+
+namespace FoundAmbiguousNonTemplate {
+ inline namespace N {
+ int f0;
+
+ struct A0;
+ } // namespace N
+
+ void f0();
+
+ struct A0;
+
+ template<typename T>
+ void g0(T &t) {
+ t.f0<0;
+ t.f0<0>; // expected-error {{expected expression}}
+ t.f0<0>1;
+
+ t.A0<0;
+ t.A0<0>; // expected-error {{expected expression}}
+ t.A0<0>1;
+ }
+
+ template<typename T>
+ struct B {
+ void f1();
+
+ struct A1; // expected-note 3{{member 'A1' declared here}}
+
+ void g1() {
+ this->f0<0; // expected-error {{no member named 'f0' in 'B<T>'}}
+ this->f0<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{no member named 'f0' in 'B<T>'}}
+ this->f0<0>1; // expected-error {{no member named 'f0' in 'B<T>'}}
+
+ this->A0<0; // expected-error {{no member named 'A0' in 'B<T>'}}
+ this->A0<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{no member named 'A0' in 'B<T>'}}
+ this->A0<0>1; // expected-error {{no member named 'A0' in 'B<T>'}}
+
+ this->f1<0; // expected-error {{reference to non-static member function must be called}}
+ this->f1<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{reference to non-static member function must be called}}
+ this->f1<0>1; // expected-error {{reference to non-static member function must be called}}
+
+ this->A1<0; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ this->A1<0>; // expected-error {{expected expression}}
+ // expected-error at -1 {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ this->A1<0>1; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ }
+ };
+} // namespace FoundAmbiguousNonTemplates
+
+namespace FoundAmbiguousTemplate {
+ inline namespace N {
+ template<int I>
+ int f0; // expected-note 3{{candidate found by name lookup is 'FoundAmbiguousTemplate::N::f0'}}
+
+ template<int I>
+ struct A0; // expected-note 3{{candidate found by name lookup is 'FoundAmbiguousTemplate::N::A0'}}
+ } // namespace N
+
+ template<int I>
+ void f0(); // expected-note 3{{candidate found by name lookup is 'FoundAmbiguousTemplate::f0'}}
+
+ template<int I>
+ struct A0; // expected-note 3{{candidate found by name lookup is 'FoundAmbiguousTemplate::A0'}}
+
+ template<typename T>
+ void g0(T &t) {
+ t.f0<0;
+ t.f0<0>; // expected-error {{expected expression}}
+ t.f0<0>1;
+
+ t.A0<0;
+ t.A0<0>; // expected-error {{expected expression}}
+ t.A0<0>1;
+ }
+
+ template<typename T>
+ struct B {
+ template<int I>
+ void f1(); // expected-note 2{{possible target for call}}
+
+ template<int I>
+ struct A1; // expected-note 2{{member 'A1' declared here}}
+
+ void g1() {
+ this->f0<0; // expected-error {{expected '>'}}
+ // expected-note at -1 {{to match this '<'}}
+ // expected-error at -2 {{expected unqualified-id}}
+ // expected-error at -3 {{reference to 'f0' is ambiguous}}
+ this->f0<0>; // expected-error {{no member named 'f0' in 'B<T>'}}
+ // expected-error at -1 {{reference to 'f0' is ambiguous}}
+ this->f0<0>1; // expected-error {{no member named 'f0' in 'B<T>'}}
+ // expected-error at -1 {{expected ';' after expression}}
+ // expected-error at -2 {{reference to 'f0' is ambiguous}}
+
+ this->A0<0; // expected-error {{expected '>'}}
+ // expected-note at -1 {{to match this '<'}}
+ // expected-error at -2 {{expected unqualified-id}}
+ // expected-error at -3 {{reference to 'A0' is ambiguous}}
+ this->A0<0>; // expected-error {{no member named 'A0' in 'B<T>'}}
+ // expected-error at -1 {{reference to 'A0' is ambiguous}}
+ this->A0<0>1; // expected-error {{no member named 'A0' in 'B<T>'}}
+ // expected-error at -1 {{expected ';' after expression}}
+ // expected-error at -2 {{reference to 'A0' is ambiguous}}
+
+
+ this->f1<0; // expected-error {{expected '>'}}
+ // expected-note at -1 {{to match this '<'}}
+ // expected-error at -2 {{expected unqualified-id}}
+ this->f1<0>; // expected-error {{reference to non-static member function must be called}}
+ this->f1<0>1; // expected-error {{reference to non-static member function must be called}}
+ // expected-error at -1 {{expected ';' after expression}}
+
+ this->A1<0; // expected-error {{expected '>'}}
+ // expected-note at -1 {{to match this '<'}}
+ // expected-error at -2 {{expected unqualified-id}}
+ this->A1<0>; // expected-error {{cannot refer to member 'A1' in 'B<T>' with '->'}}
+ this->A1<0>1; // expected-error {{cannot refer to member 'A1' in 'B<T>' with '->'}}
+ // expected-error at -1 {{expected ';' after expression}}
+ }
+ };
+} // namespace FoundAmbiguousTemplate
>From 3ea596f56d5955405fcde8b1f0085d7a3eea89e6 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 31 May 2024 14:44:10 -0400
Subject: [PATCH 06/19] [FOLD] cleanups
---
clang/include/clang/AST/ExprCXX.h | 21 +---------
clang/include/clang/AST/Stmt.h | 6 ---
clang/lib/Sema/TreeTransform.h | 9 ----
clang/lib/Serialization/ASTReaderStmt.cpp | 50 -----------------------
clang/lib/Serialization/ASTWriterStmt.cpp | 31 --------------
5 files changed, 2 insertions(+), 115 deletions(-)
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index d8f87ad4a94f3..6cd6e049ad1e9 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -3807,25 +3807,8 @@ class CXXDependentScopeMemberExpr final
return getQualifierLoc().getNestedNameSpecifier();
}
-#if 0
- /// Retrieve the first part of the nested-name-specifier that was
- /// found in the scope of the member access expression when the member access
- /// was initially parsed.
- ///
- /// This function only returns a useful result when member access expression
- /// uses a qualified member name, e.g., "x.Base::f". Here, the declaration
- /// returned by this function describes what was found by unqualified name
- /// lookup for the identifier "Base" within the scope of the member access
- /// expression itself. At template instantiation time, this information is
- /// combined with the results of name lookup into the type of the object
- /// expression itself (the class type of x).
- NamedDecl *getFirstQualifierFoundInScope() const {
- if (!hasFirstQualifierFoundInScope())
- return nullptr;
- return *getTrailingObjects<NamedDecl *>();
- }
-#endif
-
+ /// Retrieve the declarations found by unqualified lookup for the first
+ /// component name of the nested-name-specifier, if any.
ArrayRef<DeclAccessPair> unqualified_lookups() const {
if (!getNumUnqualifiedLookups())
return std::nullopt;
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 6e6221ec15fdb..257a61c97c9c6 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -1030,12 +1030,6 @@ class alignas(void *) Stmt {
LLVM_PREFERRED_TYPE(bool)
unsigned HasTemplateKWAndArgsInfo : 1;
-#if 0
- /// See getFirstQualifierFoundInScope() and the comment listing
- /// the trailing objects.
- LLVM_PREFERRED_TYPE(bool)
- unsigned HasFirstQualifierFoundInScope : 1;
-#endif
/// Number of declarations found by unqualified lookup for the
/// first component name of the nested-name-specifier.
unsigned NumUnqualifiedLookups;
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index f4e7ccdf309af..da4d8469e55cf 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14628,15 +14628,6 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
ObjectType = BaseType->castAs<PointerType>()->getPointeeType();
}
-#if 0
- // Transform the first part of the nested-name-specifier that qualifies
- // the member name.
- NamedDecl *FirstQualifierInScope
- = getDerived().TransformFirstQualifierInScope(
- E->getFirstQualifierFoundInScope(),
- E->getQualifierLoc().getBeginLoc());
-#endif
-
UnresolvedSet<4> UnqualifiedLookups;
for (auto D : E->unqualified_lookups()) {
if (NamedDecl *InstD = getDerived().TransformFirstQualifierInScope(
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 90645b5b5eaec..51fd6fdd44f5b 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2014,52 +2014,12 @@ void ASTStmtReader::VisitCXXDependentScopeMemberExpr(
auto AS = (AccessSpecifier)Record.readInt();
E->getTrailingObjects<DeclAccessPair>()[I] =
DeclAccessPair::make(FoundD, AS);
- ;
}
if (HasTemplateInfo)
ReadTemplateKWAndArgsInfo(
*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
-
-#if 0
- unsigned NumTemplateArgs = Record.readInt();
- CurrentUnpackingBits.emplace(Record.readInt());
- bool HasTemplateKWAndArgsInfo = CurrentUnpackingBits->getNextBit();
- bool HasFirstQualifierFoundInScope = CurrentUnpackingBits->getNextBit();
-
- assert((HasTemplateKWAndArgsInfo == E->hasTemplateKWAndArgsInfo()) &&
- "Wrong HasTemplateKWAndArgsInfo!");
- assert(
- (HasFirstQualifierFoundInScope == E->hasFirstQualifierFoundInScope()) &&
- "Wrong HasFirstQualifierFoundInScope!");
-
- if (HasTemplateKWAndArgsInfo)
- ReadTemplateKWAndArgsInfo(
- *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
- E->getTrailingObjects<TemplateArgumentLoc>(), NumTemplateArgs);
-
- assert((NumTemplateArgs == E->getNumTemplateArgs()) &&
- "Wrong NumTemplateArgs!");
-
- E->CXXDependentScopeMemberExprBits.IsArrow =
- CurrentUnpackingBits->getNextBit();
-
- E->BaseType = Record.readType();
- E->QualifierLoc = Record.readNestedNameSpecifierLoc();
- // not ImplicitAccess
- if (CurrentUnpackingBits->getNextBit())
- E->Base = Record.readSubExpr();
- else
- E->Base = nullptr;
-
- E->CXXDependentScopeMemberExprBits.OperatorLoc = readSourceLocation();
-
- if (HasFirstQualifierFoundInScope)
- *E->getTrailingObjects<NamedDecl *>() = readDeclAs<NamedDecl>();
-
- E->MemberNameInfo = Record.readDeclarationNameInfo();
-#endif
}
void
@@ -4096,16 +4056,6 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case EXPR_CXX_DEPENDENT_SCOPE_MEMBER: {
-
-#if 0
- unsigned NumTemplateArgs = Record[ASTStmtReader::NumExprFields];
- BitsUnpacker DependentScopeMemberBits(
- Record[ASTStmtReader::NumExprFields + 1]);
- bool HasTemplateKWAndArgsInfo = DependentScopeMemberBits.getNextBit();
-
- bool HasFirstQualifierFoundInScope =
- DependentScopeMemberBits.getNextBit();
-#endif
BitsUnpacker DependentScopeMemberBits(
Record[ASTStmtReader::NumExprFields]);
bool HasQualifier = DependentScopeMemberBits.getNextBit();
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 42d83cd2d8397..d37afd0c226a0 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2012,37 +2012,6 @@ void ASTStmtWriter::VisitCXXDependentScopeMemberExpr(
AddTemplateKWAndArgsInfo(*E->getTrailingObjects<ASTTemplateKWAndArgsInfo>(),
E->getTrailingObjects<TemplateArgumentLoc>());
-#if 0
- // Don't emit anything here (or if you do you will have to update
- // the corresponding deserialization function).
- Record.push_back(E->getNumTemplateArgs());
- CurrentPackingBits.updateBits();
- CurrentPackingBits.addBit(E->hasTemplateKWAndArgsInfo());
- CurrentPackingBits.addBit(E->hasFirstQualifierFoundInScope());
-
- if (E->hasTemplateKWAndArgsInfo()) {
- const ASTTemplateKWAndArgsInfo &ArgInfo =
- *E->getTrailingObjects<ASTTemplateKWAndArgsInfo>();
- AddTemplateKWAndArgsInfo(ArgInfo,
- E->getTrailingObjects<TemplateArgumentLoc>());
- }
-
- CurrentPackingBits.addBit(E->isArrow());
-
- Record.AddTypeRef(E->getBaseType());
- Record.AddNestedNameSpecifierLoc(E->getQualifierLoc());
- CurrentPackingBits.addBit(!E->isImplicitAccess());
- if (!E->isImplicitAccess())
- Record.AddStmt(E->getBase());
-
- Record.AddSourceLocation(E->getOperatorLoc());
-
- if (E->hasFirstQualifierFoundInScope())
- Record.AddDeclRef(E->getFirstQualifierFoundInScope());
-
- Record.AddDeclarationNameInfo(E->MemberNameInfo);
-#endif
-
Code = serialization::EXPR_CXX_DEPENDENT_SCOPE_MEMBER;
}
>From 64123aa73f59bb1e47f07df3fc3104f50565dbaa Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 31 May 2024 15:29:21 -0400
Subject: [PATCH 07/19] [FOLD] use -Wno-unused for test
---
clang/test/CXX/temp/temp.names/p3-23.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/CXX/temp/temp.names/p3-23.cpp b/clang/test/CXX/temp/temp.names/p3-23.cpp
index 5119cd4ecac9f..a7015c2d250fb 100644
--- a/clang/test/CXX/temp/temp.names/p3-23.cpp
+++ b/clang/test/CXX/temp/temp.names/p3-23.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++23 %s -verify
+// RUN: %clang_cc1 -std=c++23 -Wno-unused %s -verify
namespace FoundNothing {
template<typename T>
>From be3a1f3bd909d7f738981ffee45c3def5b78515e Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 31 May 2024 16:39:54 -0400
Subject: [PATCH 08/19] [FOLD] add additional tests
---
.../basic.lookup.qual.general/p3.cpp | 151 +++++++++++-------
1 file changed, 89 insertions(+), 62 deletions(-)
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
index e3c4aae984aeb..6798e961123c3 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
@@ -1,71 +1,98 @@
// RUN: %clang_cc1 -std=c++23 -Wno-unused %s -verify
-struct A {
- int x;
+namespace Unambiguous {
+ struct A {
+ int x;
+
+ template<typename T>
+ using C = A;
+ };
+
+ using B = A;
template<typename T>
- using C = A;
-};
+ using D = A;
+
+ using E = void;
-using B = A;
+ struct F : A {
+ void non_template() {
+ this->x;
+ this->A::x;
+ this->B::x;
+ this->C<int>::x;
+ this->D<int>::x;
+ this->E::x; // expected-error {{'Unambiguous::E' (aka 'void') is not a class, namespace, or enumeration}}
+ }
+ };
-template<typename T>
-using D = A;
+ template<typename T>
+ void not_instantiated(T t) {
+ t.x;
+ t.A::x;
+ t.B::x;
+ t.C<int>::x; // expected-error {{use 'template' keyword to treat 'C' as a dependent template name}}
+ t.template C<int>::x;
+ t.D<int>::x; // expected-error {{use 'template' keyword to treat 'D' as a dependent template name}}
+ t.template D<int>::x;
+ t.E::x;
+ }
-using E = void;
+ template<typename T>
+ void instantiated_valid(T t) {
+ t.x;
+ t.A::x;
+ t.B::x;
+ t.template C<int>::x;
+ t.template D<int>::x;
+ t.E::x;
+ }
-struct F : A {
- void non_template() {
- this->x;
- this->A::x;
- this->B::x;
- this->C<int>::x;
- this->D<int>::x;
- this->E::x; // expected-error {{'E' (aka 'void') is not a class, namespace, or enumeration}}
+ template<typename T>
+ void instantiated_invalid(T t) {
+ t.x;
+ t.A::x;
+ t.B::x; // expected-error {{'Unambiguous::Invalid::B' (aka 'void') is not a class, namespace, or enumeration}}
+ t.template C<int>::x;
+ t.template D<int>::x; // expected-error {{'D' following the 'template' keyword does not refer to a template}}
+ t.E::x; // expected-error {{'Unambiguous::E' (aka 'void') is not a class, namespace, or enumeration}}
}
-};
-
-template<typename T>
-void not_instantiated(T t) {
- t.x;
- t.A::x;
- t.B::x;
- t.C<int>::x; // expected-error {{use 'template' keyword to treat 'C' as a dependent template name}}
- t.template C<int>::x;
- t.D<int>::x; // expected-error {{use 'template' keyword to treat 'D' as a dependent template name}}
- t.template D<int>::x;
- t.E::x;
-}
-
-template<typename T>
-void instantiated_valid(T t) {
- t.x;
- t.A::x;
- t.B::x;
- t.template C<int>::x;
- t.template D<int>::x;
- t.E::x;
-}
-
-template<typename T>
-void instantiated_invalid(T t) {
- t.x;
- t.A::x;
- t.B::x; // expected-error {{'Invalid::B' (aka 'void') is not a class, namespace, or enumeration}}
- t.template C<int>::x;
- t.template D<int>::x; // expected-error {{'D' following the 'template' keyword does not refer to a template}}
- t.E::x; // expected-error {{'E' (aka 'void') is not a class, namespace, or enumeration}}
-}
-
-struct Valid : A {
- using E = A;
-};
-
-template void instantiated_valid(Valid);
-
-struct Invalid : A {
- using B = void;
- using D = A; // expected-note {{declared as a non-template here}}
-};
-
-template void instantiated_invalid(Invalid); // expected-note {{in instantiation of}}
+
+ struct Valid : A {
+ using E = A;
+ };
+
+ template void instantiated_valid(Valid);
+
+ struct Invalid : A {
+ using B = void;
+ using D = A; // expected-note {{declared as a non-template here}}
+ };
+
+ template void instantiated_invalid(Invalid); // expected-note {{in instantiation of}}
+} // namespace Unambiguous
+
+namespace Ambiguous {
+ inline namespace N {
+ struct A { }; // expected-note {{candidate found by name lookup is 'Ambiguous::N::A'}}
+ }
+
+ struct A { }; // expected-note {{candidate found by name lookup is 'Ambiguous::A'}}
+
+ template<typename T>
+ void f(T t) {
+ t.A::x; // expected-error {{reference to 'A' is ambiguous}}
+ }
+
+ struct B {
+ using A = B;
+
+ int x;
+ };
+
+ struct C { };
+
+ template void f(B);
+ template void f(C); // expected-note {{in instantiation of}}
+
+} // namespace Ambiguous
>From 5e510b862c0fad0504e29863382cb0d281b72eb6 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 3 Jun 2024 06:40:11 -0400
Subject: [PATCH 09/19] [FOLD] factor out some NFC changes
---
clang/include/clang/Sema/Sema.h | 2 +-
clang/lib/Parse/ParseDeclCXX.cpp | 2 +-
clang/lib/Parse/ParseExpr.cpp | 9 ++++-----
clang/lib/Sema/SemaExprMember.cpp | 9 ++++++---
clang/lib/Sema/SemaPseudoObject.cpp | 16 ++++++++--------
5 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4208da06db3dc..e83602af36676 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6943,7 +6943,7 @@ class Sema final : public SemaBase {
const TemplateArgumentListInfo *TemplateArgs);
ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc,
- bool IsArrow, CXXScopeSpec &SS,
+ tok::TokenKind OpKind, CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
UnqualifiedId &Member, Decl *ObjCImpDecl);
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 884e7ea8ee2de..9a4a777f575b2 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -720,7 +720,7 @@ Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(
return nullptr;
}
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ParsedType=*/nullptr,
/*ObectHasErrors=*/false,
/*EnteringConttext=*/false,
/*MayBePseudoDestructor=*/nullptr,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index b3c25f88b403d..eb7447fa038e4 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2254,7 +2254,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
break;
}
-
ParseOptionalCXXScopeSpecifier(
SS, ObjectType, LHS.get() && LHS.get()->containsErrors(),
/*EnteringContext=*/false, &MayBePseudoDestructor);
@@ -2329,10 +2328,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(
- getCurScope(), LHS.get(), OpLoc, OpKind == tok::arrow, SS,
- TemplateKWLoc, Name,
- CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr);
+ LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc,
+ OpKind, SS, TemplateKWLoc, Name,
+ CurParsedObjCImpl ? CurParsedObjCImpl->Dcl
+ : nullptr);
if (!LHS.isInvalid()) {
if (Tok.is(tok::less))
checkPotentialAngleBracket(LHS);
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index 038b3e9ceadb3..c45cbfe017de9 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -1046,7 +1046,7 @@ ExprResult Sema::BuildMemberReferenceExpr(
if (RetryExpr.isUsable() && !Trap.hasErrorOccurred()) {
CXXScopeSpec TempSS(SS);
RetryExpr = ActOnMemberAccessExpr(
- ExtraArgs->S, RetryExpr.get(), OpLoc, /*IsArrow=*/true, TempSS,
+ ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS,
TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl);
}
if (Trap.hasErrorOccurred())
@@ -1760,10 +1760,12 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
/// decl; this is an ugly hack around the fact that Objective-C
/// \@implementations aren't properly put in the context chain
ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
- SourceLocation OpLoc, bool IsArrow,
+ SourceLocation OpLoc,
+ tok::TokenKind OpKind,
CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
- UnqualifiedId &Id, Decl *ObjCImpDecl) {
+ UnqualifiedId &Id,
+ Decl *ObjCImpDecl) {
if (SS.isSet() && SS.isInvalid())
return ExprError();
@@ -1780,6 +1782,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
const TemplateArgumentListInfo *TemplateArgs;
DecomposeUnqualifiedId(Id, TemplateArgsBuffer,
NameInfo, TemplateArgs);
+ bool IsArrow = OpKind == tok::arrow;
if (getLangOpts().HLSL && IsArrow)
return ExprError(Diag(OpLoc, diag::err_hlsl_operator_unsupported) << 2);
diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp
index 86c303e67bc1d..fdb584ceb8105 100644
--- a/clang/lib/Sema/SemaPseudoObject.cpp
+++ b/clang/lib/Sema/SemaPseudoObject.cpp
@@ -1395,10 +1395,10 @@ ExprResult MSPropertyOpBuilder::buildGet() {
GetterName.setIdentifier(II, RefExpr->getMemberLoc());
CXXScopeSpec SS;
SS.Adopt(RefExpr->getQualifierLoc());
- ExprResult GetterExpr = S.ActOnMemberAccessExpr(
- S.getCurScope(), InstanceBase, /*OpLoc=*/SourceLocation(),
- RefExpr->isArrow(), SS, /*TemplateKWLoc=*/SourceLocation(), GetterName,
- /*ObjCImpDecl=*/nullptr);
+ ExprResult GetterExpr =
+ S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
+ RefExpr->isArrow() ? tok::arrow : tok::period, SS,
+ SourceLocation(), GetterName, nullptr);
if (GetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::err_cannot_find_suitable_accessor) << 0 /* getter */
@@ -1424,10 +1424,10 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl,
SetterName.setIdentifier(II, RefExpr->getMemberLoc());
CXXScopeSpec SS;
SS.Adopt(RefExpr->getQualifierLoc());
- ExprResult SetterExpr = S.ActOnMemberAccessExpr(
- S.getCurScope(), InstanceBase, /*OpLoc=*/SourceLocation(),
- RefExpr->isArrow(), SS, /*TemplateKWLoc=*/SourceLocation(), SetterName,
- /*ObjCImpDecl=*/nullptr);
+ ExprResult SetterExpr =
+ S.ActOnMemberAccessExpr(S.getCurScope(), InstanceBase, SourceLocation(),
+ RefExpr->isArrow() ? tok::arrow : tok::period, SS,
+ SourceLocation(), SetterName, nullptr);
if (SetterExpr.isInvalid()) {
S.Diag(RefExpr->getMemberLoc(),
diag::err_cannot_find_suitable_accessor) << 1 /* setter */
>From ead6a19efcd058a15150f5dc25805a4b3251b985 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 3 Jun 2024 06:44:35 -0400
Subject: [PATCH 10/19] [FOLD] remove fixme from test
---
clang/test/CXX/drs/cwg1xx.cpp | 1 -
clang/test/CXX/temp/temp.names/p3-23.cpp | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/test/CXX/drs/cwg1xx.cpp b/clang/test/CXX/drs/cwg1xx.cpp
index ea38bff0d8d34..b59e70260e1e0 100644
--- a/clang/test/CXX/drs/cwg1xx.cpp
+++ b/clang/test/CXX/drs/cwg1xx.cpp
@@ -615,7 +615,6 @@ namespace cwg141 { // cwg141: 3.1
// cxx98-note@#cwg141-S {{lookup from the current scope refers here}}
// expected-error@#cwg141-a {{no member named 'n' in 'cwg141::A::S<int>'; did you mean '::cwg141::S<int>::n'?}}
// expected-note@#cwg141-S {{'::cwg141::S<int>::n' declared here}}
- // FIXME: we issue a useful diagnostic first, then some bogus ones.
b.f<int>();
// expected-error at -1 {{no member named 'f' in 'cwg141::B'}}
(void)b.S<int>::n;
diff --git a/clang/test/CXX/temp/temp.names/p3-23.cpp b/clang/test/CXX/temp/temp.names/p3-23.cpp
index a7015c2d250fb..f652a81101162 100644
--- a/clang/test/CXX/temp/temp.names/p3-23.cpp
+++ b/clang/test/CXX/temp/temp.names/p3-23.cpp
@@ -28,7 +28,7 @@ namespace FoundSingleNonTemplate {
void g0(T &t) {
t.f0<0;
t.f0<0>; // expected-error {{expected expression}}
- t.f0<0> 1;
+ t.f0<0>1;
t.A0<0;
t.A0<0>; // expected-error {{expected expression}}
>From 2c9d45c9df80c202c43ea00147b518815613fefe Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 3 Jun 2024 08:36:13 -0400
Subject: [PATCH 11/19] [FOLD] make missing 'template' keyword an extension
---
.../clang/Basic/DiagnosticParseKinds.td | 4 +---
clang/lib/Parse/ParseExprCXX.cpp | 8 ++------
.../basic.lookup.qual.general/p3.cpp | 4 ++--
.../class.derived/class.member.lookup/p8.cpp | 4 ++--
clang/test/CXX/temp/temp.res/p3.cpp | 2 +-
clang/test/FixIt/fixit.cpp | 4 ++--
clang/test/Misc/warning-flags.c | 2 +-
.../Parser/cxx2a-concepts-requires-expr.cpp | 2 +-
.../SemaTemplate/dependent-base-classes.cpp | 20 +++++++++----------
.../dependent-template-recover.cpp | 12 +++++------
clang/test/SemaTemplate/template-id-expr.cpp | 14 ++++++-------
.../SemaTemplate/typename-specifier-3.cpp | 2 +-
12 files changed, 36 insertions(+), 42 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index d8c3fee7841f4..f52ed78fd4eac 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -892,9 +892,7 @@ def missing_template_arg_list_after_template_kw : Extension<
"keyword">, InGroup<DiagGroup<"missing-template-arg-list-after-template-kw">>,
DefaultError;
-def err_missing_dependent_template_keyword : Error<
- "use 'template' keyword to treat '%0' as a dependent template name">;
-def warn_missing_dependent_template_keyword : ExtWarn<
+def ext_missing_dependent_template_keyword : ExtWarn<
"use 'template' keyword to treat '%0' as a dependent template name">;
def ext_extern_template : Extension<
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 1558e3dcb8974..804c1b2d4c1ff 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -566,11 +566,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
// member of an unknown specialization. However, this will only
// parse correctly as a template, so suggest the keyword 'template'
// before 'getAs' and treat this as a dependent template name.
- unsigned DiagID = diag::err_missing_dependent_template_keyword;
- if (getLangOpts().MicrosoftExt)
- DiagID = diag::warn_missing_dependent_template_keyword;
-
- Diag(Tok.getLocation(), DiagID)
+ Diag(Tok.getLocation(), diag::ext_missing_dependent_template_keyword)
<< II.getName()
<< FixItHint::CreateInsertion(Tok.getLocation(), "template ");
}
@@ -2577,7 +2573,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(
else
Name += Id.Identifier->getName();
}
- Diag(Id.StartLocation, diag::err_missing_dependent_template_keyword)
+ Diag(Id.StartLocation, diag::ext_missing_dependent_template_keyword)
<< Name
<< FixItHint::CreateInsertion(Id.StartLocation, "template ");
}
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
index 6798e961123c3..7d843649c3f30 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/basic.lookup.qual.general/p3.cpp
@@ -31,9 +31,9 @@ namespace Unambiguous {
t.x;
t.A::x;
t.B::x;
- t.C<int>::x; // expected-error {{use 'template' keyword to treat 'C' as a dependent template name}}
+ t.C<int>::x; // expected-warning {{use 'template' keyword to treat 'C' as a dependent template name}}
t.template C<int>::x;
- t.D<int>::x; // expected-error {{use 'template' keyword to treat 'D' as a dependent template name}}
+ t.D<int>::x; // expected-warning {{use 'template' keyword to treat 'D' as a dependent template name}}
t.template D<int>::x;
t.E::x;
}
diff --git a/clang/test/CXX/class.derived/class.member.lookup/p8.cpp b/clang/test/CXX/class.derived/class.member.lookup/p8.cpp
index e9a57f739cc35..97d3587881bbc 100644
--- a/clang/test/CXX/class.derived/class.member.lookup/p8.cpp
+++ b/clang/test/CXX/class.derived/class.member.lookup/p8.cpp
@@ -47,8 +47,8 @@ template<typename T>
void DerivedT<T>::Inner() {
Derived1T<T>::Foo();
Derived2T<T>::Member = 42;
- this->Derived1T<T>::Foo(); // expected-error{{use 'template' keyword to treat 'Derived1T' as a dependent template name}}
- this->Derived2T<T>::Member = 42; // expected-error{{use 'template' keyword to treat 'Derived2T' as a dependent template name}}
+ this->Derived1T<T>::Foo(); // expected-warning{{use 'template' keyword to treat 'Derived1T' as a dependent template name}}
+ this->Derived2T<T>::Member = 42; // expected-warning{{use 'template' keyword to treat 'Derived2T' as a dependent template name}}
this->Foo(); // expected-error{{non-static member 'Foo' found in multiple base-class subobjects of type 'BaseT<int>'}}
}
diff --git a/clang/test/CXX/temp/temp.res/p3.cpp b/clang/test/CXX/temp/temp.res/p3.cpp
index 37ab93559e369..a4d735e05e9b8 100644
--- a/clang/test/CXX/temp/temp.res/p3.cpp
+++ b/clang/test/CXX/temp/temp.res/p3.cpp
@@ -30,6 +30,6 @@ template<typename T> int A<T>::template C<int>::*f5() {} // expected-error {{has
template<typename T> template<typename U> struct A<T>::B {
friend A<T>::C<T> f6(); // ok, same as 'friend T f6();'
- friend A<U>::C<T> f7(); // expected-error {{use 'template' keyword to treat 'C' as a dependent template name}} expected-warning {{missing 'typename'}}
+ friend A<U>::C<T> f7(); // expected-warning {{use 'template' keyword to treat 'C' as a dependent template name}} expected-warning {{missing 'typename'}}
friend A<U>::template C<T> f8(); // expected-warning {{missing 'typename'}}
};
diff --git a/clang/test/FixIt/fixit.cpp b/clang/test/FixIt/fixit.cpp
index 605c2d0bd0235..144eefb3ae4bd 100644
--- a/clang/test/FixIt/fixit.cpp
+++ b/clang/test/FixIt/fixit.cpp
@@ -158,12 +158,12 @@ class F1 {
template<class T>
class F2 {
- typename F1<T>:: /*template*/ Iterator<0> Mypos; // expected-error {{use 'template' keyword to treat 'Iterator' as a dependent template name}}
+ typename F1<T>:: /*template*/ Iterator<0> Mypos; // expected-warning {{use 'template' keyword to treat 'Iterator' as a dependent template name}}
};
template <class T>
void f(){
- typename F1<T>:: /*template*/ Iterator<0> Mypos; // expected-error {{use 'template' keyword to treat 'Iterator' as a dependent template name}}
+ typename F1<T>:: /*template*/ Iterator<0> Mypos; // expected-warning {{use 'template' keyword to treat 'Iterator' as a dependent template name}}
}
// Tests for &/* fixits
diff --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c
index dd73331913c6f..147fc088b6681 100644
--- a/clang/test/Misc/warning-flags.c
+++ b/clang/test/Misc/warning-flags.c
@@ -22,6 +22,7 @@ CHECK: Warnings without flags (66):
CHECK-NEXT: ext_expected_semi_decl_list
CHECK-NEXT: ext_explicit_specialization_storage_class
+CHECK-NEXT: ext_missing_dependent_template_keyword
CHECK-NEXT: ext_missing_whitespace_after_macro_name
CHECK-NEXT: ext_new_paren_array_nonconst
CHECK-NEXT: ext_plain_complex
@@ -62,7 +63,6 @@ CHECK-NEXT: warn_invalid_cpu_supports
CHECK-NEXT: warn_maynot_respond
CHECK-NEXT: warn_method_param_redefinition
CHECK-NEXT: warn_missing_case_for_condition
-CHECK-NEXT: warn_missing_dependent_template_keyword
CHECK-NEXT: warn_missing_whitespace_after_macro_name
CHECK-NEXT: warn_mt_message
CHECK-NEXT: warn_no_constructor_for_refconst
diff --git a/clang/test/Parser/cxx2a-concepts-requires-expr.cpp b/clang/test/Parser/cxx2a-concepts-requires-expr.cpp
index 971591afb08db..980493b777b12 100644
--- a/clang/test/Parser/cxx2a-concepts-requires-expr.cpp
+++ b/clang/test/Parser/cxx2a-concepts-requires-expr.cpp
@@ -78,7 +78,7 @@ bool r22 = requires { typename s::~s; };
template<typename T>
bool r23 = requires { typename identity<T>::temp<T>; };
-// expected-error at -1 {{use 'template' keyword to treat 'temp' as a dependent template name}}
+// expected-warning at -1 {{use 'template' keyword to treat 'temp' as a dependent template name}}
template<typename T>
bool r24 = requires {
diff --git a/clang/test/SemaTemplate/dependent-base-classes.cpp b/clang/test/SemaTemplate/dependent-base-classes.cpp
index 92a37efaa7e73..4cb88a5b4070a 100644
--- a/clang/test/SemaTemplate/dependent-base-classes.cpp
+++ b/clang/test/SemaTemplate/dependent-base-classes.cpp
@@ -1,12 +1,12 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename T, typename U>
-struct X0 : T::template apply<U> {
+struct X0 : T::template apply<U> {
X0(U u) : T::template apply<U>(u) { }
};
template<typename T, typename U>
-struct X1 : T::apply<U> { }; // expected-error{{use 'template' keyword to treat 'apply' as a dependent template name}}
+struct X1 : T::apply<U> { }; // expected-warning{{use 'template' keyword to treat 'apply' as a dependent template name}}
template<typename T>
struct X2 : vector<T> { }; // expected-error{{no template named 'vector'}}
@@ -85,7 +85,7 @@ namespace PR6081 {
struct A { };
template<typename T>
- class B : public A<T>
+ class B : public A<T>
{
public:
template< class X >
@@ -109,9 +109,9 @@ namespace PR6081 {
namespace PR6413 {
template <typename T> class Base_A { };
-
+
class Base_B { };
-
+
template <typename T>
class Derived
: public virtual Base_A<T>
@@ -120,12 +120,12 @@ namespace PR6413 {
}
namespace PR5812 {
- template <class T> struct Base {
- Base* p;
- };
+ template <class T> struct Base {
+ Base* p;
+ };
- template <class T> struct Derived: public Base<T> {
- typename Derived::Base* p; // meaning Derived::Base<T>
+ template <class T> struct Derived: public Base<T> {
+ typename Derived::Base* p; // meaning Derived::Base<T>
};
Derived<int> di;
diff --git a/clang/test/SemaTemplate/dependent-template-recover.cpp b/clang/test/SemaTemplate/dependent-template-recover.cpp
index c7e27e8da25f1..c763989e6dadb 100644
--- a/clang/test/SemaTemplate/dependent-template-recover.cpp
+++ b/clang/test/SemaTemplate/dependent-template-recover.cpp
@@ -2,15 +2,15 @@
template<typename T, typename U, int N>
struct X {
void f(T* t) {
- t->f0<U>(); // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}}
- t->f0<int>(); // expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}}
+ t->f0<U>(); // expected-warning{{use 'template' keyword to treat 'f0' as a dependent template name}}
+ t->f0<int>(); // expected-warning{{use 'template' keyword to treat 'f0' as a dependent template name}}
- t->operator+<U const, 1>(1); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}}
- t->f1<int const, 2>(1); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}}
+ t->operator+<U const, 1>(1); // expected-warning{{use 'template' keyword to treat 'operator +' as a dependent template name}}
+ t->f1<int const, 2>(1); // expected-warning{{use 'template' keyword to treat 'f1' as a dependent template name}}
t->f1<3, int const>(1); // expected-error{{missing 'template' keyword prior to dependent template name 'f1'}}
- T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}}
- t->T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}}
+ T::getAs<U>(); // expected-warning{{use 'template' keyword to treat 'getAs' as a dependent template name}}
+ t->T::getAs<U>(); // expected-warning{{use 'template' keyword to treat 'getAs' as a dependent template name}}
(*t).f2<N>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
(*t).f2<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f2'}}
diff --git a/clang/test/SemaTemplate/template-id-expr.cpp b/clang/test/SemaTemplate/template-id-expr.cpp
index 6c98e29cdaa95..fe2d22848f342 100644
--- a/clang/test/SemaTemplate/template-id-expr.cpp
+++ b/clang/test/SemaTemplate/template-id-expr.cpp
@@ -19,7 +19,7 @@ template<typename T>
struct X0 {
template<typename U>
void f1();
-
+
template<typename U>
void f2(U) {
f1<U>();
@@ -39,9 +39,9 @@ struct Y {
template<int I>
struct X {
X(int, int);
- void f() {
- Y<X<I> >(X<I>(0, 0));
- Y<X<I> >(::X<I>(0, 0));
+ void f() {
+ Y<X<I> >(X<I>(0, 0));
+ Y<X<I> >(::X<I>(0, 0));
}
};
@@ -149,11 +149,11 @@ struct Y2 : Y1<T> {
int x;
x = Y1::f4(0);
- x = Y1::f4<int>(0); // expected-error {{use 'template'}} expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = Y1::f4<int>(0); // expected-warning {{use 'template'}} expected-error {{assigning to 'int' from incompatible type 'void'}}
x = Y1::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
x = p->f4(0);
- x = p->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{use 'template'}}
+ x = p->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-warning {{use 'template'}}
x = p->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
}
};
@@ -184,7 +184,7 @@ class E {
#if __cplusplus <= 199711L
// expected-warning at +2 {{extension}}
#endif
-template<typename T> using D = int; // expected-note {{declared here}}
+template<typename T> using D = int; // expected-note {{declared here}}
E<D> ed; // expected-note {{instantiation of}}
namespace non_functions {
diff --git a/clang/test/SemaTemplate/typename-specifier-3.cpp b/clang/test/SemaTemplate/typename-specifier-3.cpp
index 714830f0032d2..a9010969322e5 100644
--- a/clang/test/SemaTemplate/typename-specifier-3.cpp
+++ b/clang/test/SemaTemplate/typename-specifier-3.cpp
@@ -46,7 +46,7 @@ namespace PR12884_half_fixed {
typedef int arg;
};
struct C {
- typedef typename B::X<typename B::arg> x; // expected-error {{use 'template'}} expected-error {{refers to non-type}}
+ typedef typename B::X<typename B::arg> x; // expected-warning {{use 'template'}} expected-error {{refers to non-type}}
};
};
>From 4331d55090f2a21882c526f02066a1180df18383 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Mon, 3 Jun 2024 12:07:39 -0400
Subject: [PATCH 12/19] [FOLD] fix missing 'template' keyword in libc++
---
libcxx/include/regex | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/regex b/libcxx/include/regex
index b3869d36de1df..2fa1854710392 100644
--- a/libcxx/include/regex
+++ b/libcxx/include/regex
@@ -4219,7 +4219,7 @@ public:
_NOEXCEPT(__is_nothrow_swappable<_BidirectionalIterator>::value)
#endif // _LIBCPP_CXX03_LANG
{
- this->pair<_BidirectionalIterator, _BidirectionalIterator>::swap(__s);
+ this->template pair<_BidirectionalIterator, _BidirectionalIterator>::swap(__s);
std::swap(matched, __s.matched);
}
};
>From 61d1af8ca973273f59544313eb0a6942e6cea7f2 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 4 Jun 2024 07:52:12 -0400
Subject: [PATCH 13/19] [FOLD] experimental improved recovery
---
clang/include/clang/Parse/Parser.h | 3 +-
clang/include/clang/Sema/Sema.h | 9 ++-
clang/lib/Parse/ParseExprCXX.cpp | 68 +++++++++++++++++-----
clang/lib/Sema/SemaTemplate.cpp | 20 ++++---
clang/lib/Sema/SemaTemplateInstantiate.cpp | 7 ++-
clang/lib/Sema/TreeTransform.h | 22 ++++---
clang/test/CXX/drs/cwg3xx.cpp | 10 ++--
clang/test/CXX/drs/cwg4xx.cpp | 2 +-
8 files changed, 96 insertions(+), 45 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index d054b8cf0d240..fb43b2d958f49 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3372,7 +3372,8 @@ class Parser : public CodeCompletionHandler {
SourceLocation NameLoc,
bool EnteringContext,
UnqualifiedId &Id,
- bool AssumeTemplateId);
+ bool AssumeTemplateId,
+ bool ForDestructor);
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
ParsedType ObjectType,
UnqualifiedId &Result);
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e83602af36676..162e1207070c3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8807,7 +8807,8 @@ class Sema final : public SemaBase {
QualType ObjectType, bool EnteringContext,
RequiredTemplateKind RequiredTemplate = SourceLocation(),
AssumedTemplateKind *ATK = nullptr,
- bool AllowTypoCorrection = true);
+ bool AllowTypoCorrection = true,
+ bool MayBeNNS = false);
TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
bool hasTemplateKeyword,
@@ -8815,7 +8816,8 @@ class Sema final : public SemaBase {
ParsedType ObjectType, bool EnteringContext,
TemplateTy &Template,
bool &MemberOfUnknownSpecialization,
- bool Disambiguation = false);
+ bool Disambiguation = false,
+ bool MayBeNNS = false);
/// Try to resolve an undeclared template name as a type template.
///
@@ -9030,7 +9032,8 @@ class Sema final : public SemaBase {
const UnqualifiedId &Name,
ParsedType ObjectType,
bool EnteringContext, TemplateTy &Template,
- bool AllowInjectedClassName = false);
+ bool AllowInjectedClassName = false,
+ bool MayBeNNS = false);
DeclResult ActOnClassTemplateSpecialization(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 804c1b2d4c1ff..ff379799a32be 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -100,7 +100,8 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType,
bool MemberOfUnknownSpecialization;
if (!Actions.isTemplateName(getCurScope(), SS, /*hasTemplateKeyword=*/false,
TemplateName, ObjectType, EnteringContext,
- Template, MemberOfUnknownSpecialization))
+ Template, MemberOfUnknownSpecialization,
+ /*Disambiguation=*/false, /*MayBeNNS=*/true))
return;
FixDigraph(*this, PP, Next, SecondToken, tok::unknown,
@@ -353,7 +354,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
TemplateTy Template;
TemplateNameKind TNK = Actions.ActOnTemplateName(
getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType,
- EnteringContext, Template, /*AllowInjectedClassName*/ true);
+ EnteringContext, Template, /*AllowInjectedClassName*/true,
+ /*MayBeNNS=*/true);
if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateKWLoc,
TemplateName, false))
return true;
@@ -405,7 +407,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
: TemplateId->TemplateNameLoc;
SS.SetInvalid(SourceRange(StartLoc, CCLoc));
}
-
continue;
}
@@ -534,12 +535,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
ObjectType,
EnteringContext,
Template,
- MemberOfUnknownSpecialization)) {
+ MemberOfUnknownSpecialization,
+ /*Disambiguation=*/false,
+ /*MayBeNNS=*/true)) {
// If lookup didn't find anything, we treat the name as a template-name
// anyway. C++20 requires this, and in prior language modes it improves
// error recovery. But before we commit to this, check that we actually
// have something that looks like a template-argument-list next.
- if (!IsTypename && TNK == TNK_Undeclared_template &&
+ if (!IsTypename && (TNK == TNK_Undeclared_template ||
+ (!HasScopeSpecifier && ObjectType)) &&
isTemplateArgumentList(1) == TPResult::False)
break;
@@ -1914,12 +1918,35 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
// void f(auto *p) { p->~X<int>(); }
// ... but there's no ambiguity, and nowhere to write 'template' in such an
// example, so we accept it anyway.
+ #if 1
if (Tok.is(tok::less) &&
ParseUnqualifiedIdTemplateId(
SS, ObjectType, Base && Base->containsErrors(), SourceLocation(),
Name, NameLoc, false, SecondTypeName,
- /*AssumeTemplateId=*/true))
+ /*AssumeTemplateId=*/true, /*ForDestructor=*/true))
return ExprError();
+ #endif
+ #if 0
+ if (Tok.is(tok::less)) {
+ TemplateTy Template;
+ TemplateNameKind TNK = Actions.ActOnTemplateName(
+ getCurScope(), SS, /*TemplateKWLoc=*/SourceLocation(),
+ SecondTypeName, ObjectType,
+ /*EnteringContext=*/false, Template,
+ /*AllowInjectedClassName*/true,
+ /*MayBeNNS=*/true);
+ if (TNK == TNK_Non_template)
+ return ExprError();
+
+ if (AnnotateTemplateIdToken(Template, TNK, SS,
+ /*TemplateKWLoc=*/SourceLocation(),
+ SecondTypeName, /*AllowTypeAnnotation=*/false))
+ return ExprError();
+ assert(Tok.is(tok::annot_template_id));
+ SecondTypeName.setTemplateId(takeTemplateIdAnnotation(Tok));
+ ConsumeAnnotationToken();
+ }
+ #endif
return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind,
SS, FirstTypeName, CCLoc, TildeLoc,
@@ -2526,7 +2553,8 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS, DeclaratorContext Context) {
bool Parser::ParseUnqualifiedIdTemplateId(
CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
SourceLocation TemplateKWLoc, IdentifierInfo *Name, SourceLocation NameLoc,
- bool EnteringContext, UnqualifiedId &Id, bool AssumeTemplateId) {
+ bool EnteringContext, UnqualifiedId &Id, bool AssumeTemplateId,
+ bool ForDestructor) {
assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
TemplateTy Template;
@@ -2540,13 +2568,16 @@ bool Parser::ParseUnqualifiedIdTemplateId(
// this template-id is used to form a nested-name-specifier or not.
TNK = Actions.ActOnTemplateName(getCurScope(), SS, TemplateKWLoc, Id,
ObjectType, EnteringContext, Template,
- /*AllowInjectedClassName*/ true);
+ /*AllowInjectedClassName=*/true,
+ ForDestructor);
} else {
bool MemberOfUnknownSpecialization;
TNK = Actions.isTemplateName(getCurScope(), SS,
TemplateKWLoc.isValid(), Id,
ObjectType, EnteringContext, Template,
- MemberOfUnknownSpecialization);
+ MemberOfUnknownSpecialization,
+ /*Disambiguation=*/false,
+ ForDestructor);
// If lookup found nothing but we're assuming that this is a template
// name, double-check that makes sense syntactically before committing
// to it.
@@ -2579,7 +2610,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(
}
TNK = Actions.ActOnTemplateName(
getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext,
- Template, /*AllowInjectedClassName*/ true);
+ Template, /*AllowInjectedClassName=*/true, ForDestructor);
} else if (TNK == TNK_Non_template) {
return false;
}
@@ -2606,12 +2637,15 @@ bool Parser::ParseUnqualifiedIdTemplateId(
if (ObjectType) {
TNK = Actions.ActOnTemplateName(
getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType,
- EnteringContext, Template, /*AllowInjectedClassName*/ true);
+ EnteringContext, Template, /*AllowInjectedClassName=*/true,
+ /*MayBeNNS=*/true);
} else {
TNK = Actions.isTemplateName(getCurScope(), SS, TemplateKWLoc.isValid(),
TemplateName, ObjectType,
EnteringContext, Template,
- MemberOfUnknownSpecialization);
+ MemberOfUnknownSpecialization,
+ /*Disambiguation=*/false,
+ /*MayBeNNS=*/true);
if (TNK == TNK_Non_template && !Id.DestructorName.get()) {
Diag(NameLoc, diag::err_destructor_template_id)
@@ -3022,7 +3056,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
return ParseUnqualifiedIdTemplateId(
SS, ObjectType, ObjectHadErrors,
TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc,
- EnteringContext, Result, TemplateSpecified);
+ EnteringContext, Result, TemplateSpecified, /*ForDestructor=*/false);
if (TemplateSpecified) {
TemplateNameKind TNK =
@@ -3118,12 +3152,13 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
return ParseUnqualifiedIdTemplateId(
SS, ObjectType, ObjectHadErrors,
TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), nullptr,
- SourceLocation(), EnteringContext, Result, TemplateSpecified);
+ SourceLocation(), EnteringContext, Result, TemplateSpecified,
+ /*ForDestructor=*/false);
else if (TemplateSpecified &&
Actions.ActOnTemplateName(
getCurScope(), SS, *TemplateKWLoc, Result, ObjectType,
EnteringContext, Template,
- /*AllowInjectedClassName*/ true) == TNK_Non_template)
+ /*AllowInjectedClassName=*/true) == TNK_Non_template)
return true;
return false;
@@ -3214,7 +3249,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
return ParseUnqualifiedIdTemplateId(
SS, ObjectType, ObjectHadErrors,
TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), ClassName,
- ClassNameLoc, EnteringContext, Result, TemplateSpecified);
+ ClassNameLoc, EnteringContext, Result, TemplateSpecified,
+ /*ForDestructor=*/true);
}
// Note that this is a destructor name.
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 4f38af1187896..57dc19c5353fe 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -181,7 +181,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
bool EnteringContext,
TemplateTy &TemplateResult,
bool &MemberOfUnknownSpecialization,
- bool Disambiguation) {
+ bool Disambiguation,
+ bool MayBeNNS) {
assert(getLangOpts().CPlusPlus && "No template names in C!");
DeclarationName TName;
@@ -212,7 +213,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
/*RequiredTemplate=*/SourceLocation(),
&AssumedTemplate,
- /*AllowTypoCorrection=*/!Disambiguation))
+ /*AllowTypoCorrection=*/!Disambiguation,
+ MayBeNNS))
return TNK_Non_template;
MemberOfUnknownSpecialization = R.wasNotFoundInCurrentInstantiation();
@@ -380,7 +382,8 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
QualType ObjectType, bool EnteringContext,
RequiredTemplateKind RequiredTemplate,
AssumedTemplateKind *ATK,
- bool AllowTypoCorrection) {
+ bool AllowTypoCorrection,
+ bool MayBeNNS) {
if (ATK)
*ATK = AssumedTemplateKind::None;
@@ -453,7 +456,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
}
bool LookupFirstQualifierInScope =
- Found.getLookupKind() != LookupMemberName && Found.empty() &&
+ MayBeNNS && Found.empty() &&
!ObjectType.isNull() && !IsDependent;
// FIXME: We should still do the lookup if the object expression is dependent,
@@ -5801,7 +5804,8 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
ParsedType ObjectType,
bool EnteringContext,
TemplateTy &Result,
- bool AllowInjectedClassName) {
+ bool AllowInjectedClassName,
+ bool MayBeNNS) {
if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TemplateKWLoc,
getLangOpts().CPlusPlus11 ?
@@ -5838,7 +5842,8 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
bool MemberOfUnknownSpecialization;
TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name,
ObjectType, EnteringContext, Result,
- MemberOfUnknownSpecialization);
+ MemberOfUnknownSpecialization,
+ /*Disambiguation=*/false, MayBeNNS);
if (TNK != TNK_Non_template) {
// We resolved this to a (non-dependent) template name. Return it.
auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
@@ -5877,7 +5882,8 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
? RequiredTemplateKind(TemplateKWLoc)
: TemplateNameIsRequired;
if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, RTK,
- /*ATK=*/nullptr, /*AllowTypoCorrection=*/false) &&
+ /*ATK=*/nullptr, /*AllowTypoCorrection=*/false,
+ MayBeNNS) &&
!R.isAmbiguous()) {
if (LookupCtx)
Diag(Name.getBeginLoc(), diag::err_no_member)
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index dcbe8aff6127d..bceea77955af3 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1548,7 +1548,8 @@ namespace {
TemplateName TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
- bool AllowInjectedClassName = false);
+ bool AllowInjectedClassName = false,
+ bool MayBeNNS = false);
const CXXAssumeAttr *TransformCXXAssumeAttr(const CXXAssumeAttr *AA);
const LoopHintAttr *TransformLoopHintAttr(const LoopHintAttr *LH);
@@ -1980,7 +1981,7 @@ TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc,
TemplateName TemplateInstantiator::TransformTemplateName(
CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
- QualType ObjectType, bool AllowInjectedClassName) {
+ QualType ObjectType, bool AllowInjectedClassName, bool MayBeNNS) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
@@ -2054,7 +2055,7 @@ TemplateName TemplateInstantiator::TransformTemplateName(
}
return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType,
- AllowInjectedClassName);
+ AllowInjectedClassName, MayBeNNS);
}
ExprResult
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index da4d8469e55cf..7b24ff6aa024f 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -587,7 +587,8 @@ class TreeTransform {
TemplateName TransformTemplateName(CXXScopeSpec &SS, TemplateName Name,
SourceLocation NameLoc,
QualType ObjectType = QualType(),
- bool AllowInjectedClassName = false);
+ bool AllowInjectedClassName = false,
+ bool MayBeNNS = false);
/// Transform the given template argument.
///
@@ -1137,7 +1138,8 @@ class TreeTransform {
CXXScopeSpec SS;
SS.Adopt(QualifierLoc);
TemplateName InstName = getDerived().RebuildTemplateName(
- SS, TemplateKWLoc, *Name, NameLoc, QualType(), AllowInjectedClassName);
+ SS, TemplateKWLoc, *Name, NameLoc, QualType(), AllowInjectedClassName,
+ /*MayBeNNS=*/false);
if (InstName.isNull())
return QualType();
@@ -1308,7 +1310,8 @@ class TreeTransform {
SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,
SourceLocation NameLoc, QualType ObjectType,
- bool AllowInjectedClassName);
+ bool AllowInjectedClassName,
+ bool MayBeNNS);
/// Build a new template name given a nested name specifier and the
/// overloaded operator name that is referred to as a template.
@@ -4527,7 +4530,7 @@ ::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) {
template <typename Derived>
TemplateName TreeTransform<Derived>::TransformTemplateName(
CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc,
- QualType ObjectType, bool AllowInjectedClassName) {
+ QualType ObjectType, bool AllowInjectedClassName, bool MayBeNNS) {
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl();
assert(Template && "qualified template name must refer to a template");
@@ -4565,7 +4568,7 @@ TemplateName TreeTransform<Derived>::TransformTemplateName(
if (DTN->isIdentifier()) {
return getDerived().RebuildTemplateName(
SS, TemplateKWLoc, *DTN->getIdentifier(), NameLoc, ObjectType,
- AllowInjectedClassName);
+ AllowInjectedClassName, MayBeNNS);
}
return getDerived().RebuildTemplateName(SS, TemplateKWLoc,
@@ -5146,7 +5149,7 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
TemplateName Template = getDerived().TransformTemplateName(
SS, SpecTL.getTypePtr()->getTemplateName(), SpecTL.getTemplateNameLoc(),
- ObjectType, /*AllowInjectedClassName=*/true);
+ ObjectType, /*AllowInjectedClassName=*/true, /*MayBeNNS=*/true);
if (Template.isNull())
return nullptr;
@@ -5160,7 +5163,7 @@ TypeSourceInfo *TreeTransform<Derived>::TransformTSIInObjectScope(
SS, SpecTL.getTemplateKeywordLoc(),
*SpecTL.getTypePtr()->getIdentifier(), SpecTL.getTemplateNameLoc(),
ObjectType,
- /*AllowInjectedClassName=*/true);
+ /*AllowInjectedClassName=*/true, /*MayBeNNS=*/true);
if (Template.isNull())
return nullptr;
@@ -16102,14 +16105,15 @@ TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
template <typename Derived>
TemplateName TreeTransform<Derived>::RebuildTemplateName(
CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const IdentifierInfo &Name,
- SourceLocation NameLoc, QualType ObjectType, bool AllowInjectedClassName) {
+ SourceLocation NameLoc, QualType ObjectType, bool AllowInjectedClassName,
+ bool MayBeNNS) {
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&Name, NameLoc);
Sema::TemplateTy Template;
getSema().ActOnTemplateName(/*Scope=*/nullptr, SS, TemplateKWLoc,
TemplateName, ParsedType::make(ObjectType),
/*EnteringContext=*/false, Template,
- AllowInjectedClassName);
+ AllowInjectedClassName, MayBeNNS);
return Template.get();
}
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index 94227dc031c6a..b82de77712124 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -443,7 +443,7 @@ namespace cwg329 { // cwg329: 3.5
// expected-note@#cwg329-b {{in instantiation of template class 'cwg329::A<char>' requested here}}
// expected-note@#cwg329-i {{previous definition is here}}
};
- A<int> a;
+ A<int> a;
A<char> b; // #cwg329-b
void test() {
@@ -684,9 +684,9 @@ namespace cwg341 { // cwg341: sup 1708
namespace B {
extern "C" int &cwg341_a = cwg341_a;
// expected-error at -1 {{redefinition of 'cwg341_a'}}
- // expected-note@#cwg341_a {{previous definition is here}}
+ // expected-note@#cwg341_a {{previous definition is here}}
}
- extern "C" void cwg341_b(); // #cwg341_b
+ extern "C" void cwg341_b(); // #cwg341_b
}
int cwg341_a;
// expected-error at -1 {{declaration of 'cwg341_a' in global scope conflicts with declaration with C language linkage}}
@@ -704,7 +704,7 @@ namespace cwg341 {
// expected-error at -1 {{declaration of 'cwg341_d' with C language linkage conflicts with declaration in global scope}}
// expected-note@#cwg341_d {{declared in global scope here}}
- namespace A { extern "C" int cwg341_e; } // #cwg341_e
+ namespace A { extern "C" int cwg341_e; } // #cwg341_e
namespace B { extern "C" void cwg341_e(); }
// expected-error at -1 {{redefinition of 'cwg341_e' as different kind of symbol}}
// expected-note@#cwg341_e {{previous definition is here}}
@@ -1106,7 +1106,7 @@ namespace cwg364 { // cwg364: yes
}
// cwg366: yes
-#if "foo" // expected-error {{invalid token at start of a preprocessor expression}}
+#if "foo" // expected-error {{invalid token at start of a preprocessor expression}}
#endif
namespace cwg367 { // cwg367: yes
diff --git a/clang/test/CXX/drs/cwg4xx.cpp b/clang/test/CXX/drs/cwg4xx.cpp
index 07162cc28f6b6..84998b16f068f 100644
--- a/clang/test/CXX/drs/cwg4xx.cpp
+++ b/clang/test/CXX/drs/cwg4xx.cpp
@@ -20,7 +20,7 @@ namespace cwg400 { // cwg400: yes
struct A { int a; struct a {}; }; // #cwg400-A
struct B { int a; struct a {}; }; // #cwg400-B
struct C : A, B { using A::a; struct a b; };
- struct D : A, B {
+ struct D : A, B {
using A::a;
// FIXME: we should issue a single diagnostic
using B::a; // #cwg400-using-B-a
>From a5f25e2fed01e5c5f6d1634f517d2617a2440f3c Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 4 Jun 2024 08:34:10 -0400
Subject: [PATCH 14/19] [FOLD] pass TildeLoc instead of bool
---
clang/include/clang/Parse/Parser.h | 4 ++--
clang/lib/Parse/ParseExprCXX.cpp | 36 ++++++++++++++++--------------
2 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index fb43b2d958f49..c9d973b54fcea 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3368,12 +3368,12 @@ class Parser : public CodeCompletionHandler {
ParsedType ObjectType,
bool ObjectHadErrors,
SourceLocation TemplateKWLoc,
+ SourceLocation TildeLoc,
IdentifierInfo *Name,
SourceLocation NameLoc,
bool EnteringContext,
UnqualifiedId &Id,
- bool AssumeTemplateId,
- bool ForDestructor);
+ bool AssumeTemplateId);
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
ParsedType ObjectType,
UnqualifiedId &Result);
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index ff379799a32be..aca43e61c7212 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1909,6 +1909,7 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
IdentifierInfo *Name = Tok.getIdentifierInfo();
SourceLocation NameLoc = ConsumeToken();
SecondTypeName.setIdentifier(Name, NameLoc);
+ // SecondTypeName.setDestructorName(TildeLoc, nullptr, NameLoc);
// If there is a '<', the second type name is a template-id. Parse
// it as such.
@@ -1921,9 +1922,10 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
#if 1
if (Tok.is(tok::less) &&
ParseUnqualifiedIdTemplateId(
- SS, ObjectType, Base && Base->containsErrors(), SourceLocation(),
+ SS, ObjectType, Base && Base->containsErrors(),
+ /*TemplateKWLoc=*/SourceLocation(), TildeLoc,
Name, NameLoc, false, SecondTypeName,
- /*AssumeTemplateId=*/true, /*ForDestructor=*/true))
+ /*AssumeTemplateId=*/true))
return ExprError();
#endif
#if 0
@@ -2552,9 +2554,9 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS, DeclaratorContext Context) {
/// \returns true if a parse error occurred, false otherwise.
bool Parser::ParseUnqualifiedIdTemplateId(
CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
- SourceLocation TemplateKWLoc, IdentifierInfo *Name, SourceLocation NameLoc,
- bool EnteringContext, UnqualifiedId &Id, bool AssumeTemplateId,
- bool ForDestructor) {
+ SourceLocation TemplateKWLoc, SourceLocation TildeLoc,
+ IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext,
+ UnqualifiedId &Id, bool AssumeTemplateId) {
assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
TemplateTy Template;
@@ -2569,7 +2571,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(
TNK = Actions.ActOnTemplateName(getCurScope(), SS, TemplateKWLoc, Id,
ObjectType, EnteringContext, Template,
/*AllowInjectedClassName=*/true,
- ForDestructor);
+ TildeLoc.isValid());
} else {
bool MemberOfUnknownSpecialization;
TNK = Actions.isTemplateName(getCurScope(), SS,
@@ -2577,7 +2579,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(
ObjectType, EnteringContext, Template,
MemberOfUnknownSpecialization,
/*Disambiguation=*/false,
- ForDestructor);
+ TildeLoc.isValid());
// If lookup found nothing but we're assuming that this is a template
// name, double-check that makes sense syntactically before committing
// to it.
@@ -2610,7 +2612,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(
}
TNK = Actions.ActOnTemplateName(
getCurScope(), SS, TemplateKWLoc, Id, ObjectType, EnteringContext,
- Template, /*AllowInjectedClassName=*/true, ForDestructor);
+ Template, /*AllowInjectedClassName=*/true, TildeLoc.isValid());
} else if (TNK == TNK_Non_template) {
return false;
}
@@ -2707,7 +2709,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(
if (Id.getKind() == UnqualifiedIdKind::IK_ConstructorName)
Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
else
- Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
+ Id.setDestructorName(TildeLoc, Type.get(), RAngleLoc);
return false;
}
@@ -3055,8 +3057,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
if (Tok.is(tok::less))
return ParseUnqualifiedIdTemplateId(
SS, ObjectType, ObjectHadErrors,
- TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc,
- EnteringContext, Result, TemplateSpecified, /*ForDestructor=*/false);
+ TemplateKWLoc ? *TemplateKWLoc : SourceLocation(),
+ /*TildeLoc=*/SourceLocation(), Id, IdLoc,
+ EnteringContext, Result, TemplateSpecified);
if (TemplateSpecified) {
TemplateNameKind TNK =
@@ -3151,9 +3154,9 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
Tok.is(tok::less))
return ParseUnqualifiedIdTemplateId(
SS, ObjectType, ObjectHadErrors,
- TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), nullptr,
- SourceLocation(), EnteringContext, Result, TemplateSpecified,
- /*ForDestructor=*/false);
+ TemplateKWLoc ? *TemplateKWLoc : SourceLocation(),
+ /*TildeLoc=*/SourceLocation(), /*Name=*/nullptr,
+ /*NameLoc=*/SourceLocation(), EnteringContext, Result, TemplateSpecified);
else if (TemplateSpecified &&
Actions.ActOnTemplateName(
getCurScope(), SS, *TemplateKWLoc, Result, ObjectType,
@@ -3248,9 +3251,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
Result.setDestructorName(TildeLoc, nullptr, ClassNameLoc);
return ParseUnqualifiedIdTemplateId(
SS, ObjectType, ObjectHadErrors,
- TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), ClassName,
- ClassNameLoc, EnteringContext, Result, TemplateSpecified,
- /*ForDestructor=*/true);
+ TemplateKWLoc ? *TemplateKWLoc : SourceLocation(),
+ TildeLoc, ClassName, ClassNameLoc, EnteringContext, Result, TemplateSpecified);
}
// Note that this is a destructor name.
>From 4087c486132bccd9bb52bfbc6886586ffa16e0ee Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 4 Jun 2024 09:27:48 -0400
Subject: [PATCH 15/19] [FOLD] update tests
---
.../basic.lookup.classref/p1-cxx11.cpp | 4 +--
.../basic.lookup/basic.lookup.classref/p1.cpp | 4 +--
clang/test/CXX/temp/temp.names/p3-23.cpp | 25 +++++--------------
3 files changed, 8 insertions(+), 25 deletions(-)
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1-cxx11.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1-cxx11.cpp
index 476745537f691..11eb67fb4f159 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1-cxx11.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1-cxx11.cpp
@@ -65,9 +65,7 @@ namespace PR11856 {
if (it1->end < it1->end) { }
X *x;
- if (x->end < 7) { } // expected-error{{expected '>'}}
- // expected-note at -1{{to match this '<'}}
- // expected-error at -2{{expected unqualified-id}}
+ if (x->end < 7) { } // expected-error{{no member named 'end' in 'PR11856::X'}}
Y *y;
if (y->end < 7) { }
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
index cabf3f73830bc..5221b883f046c 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.classref/p1.cpp
@@ -96,9 +96,7 @@ namespace PR11856 {
if (it1->end < it1->end) { }
X *x;
- if (x->end < 7) { } // expected-error{{expected '>'}}
- // expected-note at -1{{to match this '<'}}
- // expected-error at -2{{expected unqualified-id}}
+ if (x->end < 7) { } // expected-error{{no member named 'end' in 'PR11856::X'}}
Y *y;
if (y->end < 7) { }
diff --git a/clang/test/CXX/temp/temp.names/p3-23.cpp b/clang/test/CXX/temp/temp.names/p3-23.cpp
index f652a81101162..b041bef88416d 100644
--- a/clang/test/CXX/temp/temp.names/p3-23.cpp
+++ b/clang/test/CXX/temp/temp.names/p3-23.cpp
@@ -92,16 +92,12 @@ namespace FoundSingleTemplate {
struct A1; // expected-note 2{{member 'A1' declared here}}
void g1() {
- this->f0<0; // expected-error {{expected '>'}}
- // expected-note at -1 {{to match this '<'}}
- // expected-error at -2 {{expected unqualified-id}}
+ this->f0<0; // expected-error {{no member named 'f0' in 'B<T>'}}
this->f0<0>; // expected-error {{no member named 'f0' in 'B<T>'}}
this->f0<0>1; // expected-error {{no member named 'f0' in 'B<T>'}}
// expected-error at -1 {{expected ';' after expression}}
- this->A0<0; // expected-error {{expected '>'}}
- // expected-note at -1 {{to match this '<'}}
- // expected-error at -2 {{expected unqualified-id}}
+ this->A0<0; // expected-error {{no member named 'A0' in 'B<T>'}}
this->A0<0>; // expected-error {{no member named 'A0' in 'B<T>'}}
this->A0<0>1; // expected-error {{no member named 'A0' in 'B<T>'}}
// expected-error at -1 {{expected ';' after expression}}
@@ -109,14 +105,12 @@ namespace FoundSingleTemplate {
this->f1<0; // expected-error {{expected '>'}}
// expected-note at -1 {{to match this '<'}}
- // expected-error at -2 {{expected unqualified-id}}
this->f1<0>; // expected-error {{reference to non-static member function must be called}}
this->f1<0>1; // expected-error {{reference to non-static member function must be called}}
// expected-error at -1 {{expected ';' after expression}}
this->A1<0; // expected-error {{expected '>'}}
// expected-note at -1 {{to match this '<'}}
- // expected-error at -2 {{expected unqualified-id}}
this->A1<0>; // expected-error {{cannot refer to member 'A1' in 'B<T>' with '->'}}
this->A1<0>1; // expected-error {{cannot refer to member 'A1' in 'B<T>' with '->'}}
// expected-error at -1 {{expected ';' after expression}}
@@ -211,37 +205,30 @@ namespace FoundAmbiguousTemplate {
struct A1; // expected-note 2{{member 'A1' declared here}}
void g1() {
- this->f0<0; // expected-error {{expected '>'}}
- // expected-note at -1 {{to match this '<'}}
- // expected-error at -2 {{expected unqualified-id}}
- // expected-error at -3 {{reference to 'f0' is ambiguous}}
+ this->f0<0; // expected-error {{no member named 'f0' in 'B<T>'}}
+ // expected-error at -1 {{reference to 'f0' is ambiguous}}
this->f0<0>; // expected-error {{no member named 'f0' in 'B<T>'}}
// expected-error at -1 {{reference to 'f0' is ambiguous}}
this->f0<0>1; // expected-error {{no member named 'f0' in 'B<T>'}}
// expected-error at -1 {{expected ';' after expression}}
// expected-error at -2 {{reference to 'f0' is ambiguous}}
- this->A0<0; // expected-error {{expected '>'}}
- // expected-note at -1 {{to match this '<'}}
- // expected-error at -2 {{expected unqualified-id}}
- // expected-error at -3 {{reference to 'A0' is ambiguous}}
+ this->A0<0; // expected-error {{no member named 'A0' in 'B<T>'}}
+ // expected-error at -1 {{reference to 'A0' is ambiguous}}
this->A0<0>; // expected-error {{no member named 'A0' in 'B<T>'}}
// expected-error at -1 {{reference to 'A0' is ambiguous}}
this->A0<0>1; // expected-error {{no member named 'A0' in 'B<T>'}}
// expected-error at -1 {{expected ';' after expression}}
// expected-error at -2 {{reference to 'A0' is ambiguous}}
-
this->f1<0; // expected-error {{expected '>'}}
// expected-note at -1 {{to match this '<'}}
- // expected-error at -2 {{expected unqualified-id}}
this->f1<0>; // expected-error {{reference to non-static member function must be called}}
this->f1<0>1; // expected-error {{reference to non-static member function must be called}}
// expected-error at -1 {{expected ';' after expression}}
this->A1<0; // expected-error {{expected '>'}}
// expected-note at -1 {{to match this '<'}}
- // expected-error at -2 {{expected unqualified-id}}
this->A1<0>; // expected-error {{cannot refer to member 'A1' in 'B<T>' with '->'}}
this->A1<0>1; // expected-error {{cannot refer to member 'A1' in 'B<T>' with '->'}}
// expected-error at -1 {{expected ';' after expression}}
>From 17eff0637f064a9f9e00df3da4d794c778cb1c68 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 4 Jun 2024 09:28:06 -0400
Subject: [PATCH 16/19] [FOLD] format
---
clang/include/clang/Parse/Parser.h | 15 ++---
clang/include/clang/Sema/Sema.h | 31 ++++------
clang/lib/Parse/ParseExprCXX.cpp | 99 ++++++++++++++----------------
clang/lib/Sema/SemaTemplate.cpp | 46 +++++---------
clang/lib/Sema/TreeTransform.h | 3 +-
5 files changed, 83 insertions(+), 111 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index c9d973b54fcea..a71724502fbef 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3364,16 +3364,11 @@ class Parser : public CodeCompletionHandler {
BaseResult ParseBaseSpecifier(Decl *ClassDecl);
AccessSpecifier getAccessSpecifierIfPresent() const;
- bool ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
- ParsedType ObjectType,
- bool ObjectHadErrors,
- SourceLocation TemplateKWLoc,
- SourceLocation TildeLoc,
- IdentifierInfo *Name,
- SourceLocation NameLoc,
- bool EnteringContext,
- UnqualifiedId &Id,
- bool AssumeTemplateId);
+ bool ParseUnqualifiedIdTemplateId(
+ CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
+ SourceLocation TemplateKWLoc, SourceLocation TildeLoc,
+ IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext,
+ UnqualifiedId &Id, bool AssumeTemplateId);
bool ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
ParsedType ObjectType,
UnqualifiedId &Result);
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 162e1207070c3..caf05c7918c6a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8807,17 +8807,14 @@ class Sema final : public SemaBase {
QualType ObjectType, bool EnteringContext,
RequiredTemplateKind RequiredTemplate = SourceLocation(),
AssumedTemplateKind *ATK = nullptr,
- bool AllowTypoCorrection = true,
- bool MayBeNNS = false);
-
- TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
- bool hasTemplateKeyword,
- const UnqualifiedId &Name,
- ParsedType ObjectType, bool EnteringContext,
- TemplateTy &Template,
- bool &MemberOfUnknownSpecialization,
- bool Disambiguation = false,
- bool MayBeNNS = false);
+ bool AllowTypoCorrection = true, bool MayBeNNS = false);
+
+ TemplateNameKind
+ isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword,
+ const UnqualifiedId &Name, ParsedType ObjectType,
+ bool EnteringContext, TemplateTy &Template,
+ bool &MemberOfUnknownSpecialization,
+ bool Disambiguation = false, bool MayBeNNS = false);
/// Try to resolve an undeclared template name as a type template.
///
@@ -9027,13 +9024,11 @@ class Sema final : public SemaBase {
const TemplateArgumentListInfo *TemplateArgs,
bool IsAddressOfOperand);
- TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const UnqualifiedId &Name,
- ParsedType ObjectType,
- bool EnteringContext, TemplateTy &Template,
- bool AllowInjectedClassName = false,
- bool MayBeNNS = false);
+ TemplateNameKind
+ ActOnTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ const UnqualifiedId &Name, ParsedType ObjectType,
+ bool EnteringContext, TemplateTy &Template,
+ bool AllowInjectedClassName = false, bool MayBeNNS = false);
DeclResult ActOnClassTemplateSpecialization(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index aca43e61c7212..d39ab31407414 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -354,7 +354,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
TemplateTy Template;
TemplateNameKind TNK = Actions.ActOnTemplateName(
getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType,
- EnteringContext, Template, /*AllowInjectedClassName*/true,
+ EnteringContext, Template, /*AllowInjectedClassName*/ true,
/*MayBeNNS=*/true);
if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateKWLoc,
TemplateName, false))
@@ -529,21 +529,19 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
UnqualifiedId TemplateName;
TemplateName.setIdentifier(&II, Tok.getLocation());
bool MemberOfUnknownSpecialization;
- if (TemplateNameKind TNK = Actions.isTemplateName(getCurScope(), SS,
- /*hasTemplateKeyword=*/false,
- TemplateName,
- ObjectType,
- EnteringContext,
- Template,
- MemberOfUnknownSpecialization,
- /*Disambiguation=*/false,
- /*MayBeNNS=*/true)) {
+ if (TemplateNameKind TNK = Actions.isTemplateName(
+ getCurScope(), SS,
+ /*hasTemplateKeyword=*/false, TemplateName, ObjectType,
+ EnteringContext, Template, MemberOfUnknownSpecialization,
+ /*Disambiguation=*/false,
+ /*MayBeNNS=*/true)) {
// If lookup didn't find anything, we treat the name as a template-name
// anyway. C++20 requires this, and in prior language modes it improves
// error recovery. But before we commit to this, check that we actually
// have something that looks like a template-argument-list next.
- if (!IsTypename && (TNK == TNK_Undeclared_template ||
- (!HasScopeSpecifier && ObjectType)) &&
+ if (!IsTypename &&
+ (TNK == TNK_Undeclared_template ||
+ (!HasScopeSpecifier && ObjectType)) &&
isTemplateArgumentList(1) == TPResult::False)
break;
@@ -1909,26 +1907,25 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
IdentifierInfo *Name = Tok.getIdentifierInfo();
SourceLocation NameLoc = ConsumeToken();
SecondTypeName.setIdentifier(Name, NameLoc);
- // SecondTypeName.setDestructorName(TildeLoc, nullptr, NameLoc);
+// SecondTypeName.setDestructorName(TildeLoc, nullptr, NameLoc);
- // If there is a '<', the second type name is a template-id. Parse
- // it as such.
- //
- // FIXME: This is not a context in which a '<' is assumed to start a template
- // argument list. This affects examples such as
- // void f(auto *p) { p->~X<int>(); }
- // ... but there's no ambiguity, and nowhere to write 'template' in such an
- // example, so we accept it anyway.
- #if 1
- if (Tok.is(tok::less) &&
- ParseUnqualifiedIdTemplateId(
- SS, ObjectType, Base && Base->containsErrors(),
- /*TemplateKWLoc=*/SourceLocation(), TildeLoc,
- Name, NameLoc, false, SecondTypeName,
- /*AssumeTemplateId=*/true))
+// If there is a '<', the second type name is a template-id. Parse
+// it as such.
+//
+// FIXME: This is not a context in which a '<' is assumed to start a template
+// argument list. This affects examples such as
+// void f(auto *p) { p->~X<int>(); }
+// ... but there's no ambiguity, and nowhere to write 'template' in such an
+// example, so we accept it anyway.
+#if 1
+ if (Tok.is(tok::less) && ParseUnqualifiedIdTemplateId(
+ SS, ObjectType, Base && Base->containsErrors(),
+ /*TemplateKWLoc=*/SourceLocation(), TildeLoc,
+ Name, NameLoc, false, SecondTypeName,
+ /*AssumeTemplateId=*/true))
return ExprError();
- #endif
- #if 0
+#endif
+#if 0
if (Tok.is(tok::less)) {
TemplateTy Template;
TemplateNameKind TNK = Actions.ActOnTemplateName(
@@ -1948,7 +1945,7 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
SecondTypeName.setTemplateId(takeTemplateIdAnnotation(Tok));
ConsumeAnnotationToken();
}
- #endif
+#endif
return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind,
SS, FirstTypeName, CCLoc, TildeLoc,
@@ -2554,9 +2551,9 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS, DeclaratorContext Context) {
/// \returns true if a parse error occurred, false otherwise.
bool Parser::ParseUnqualifiedIdTemplateId(
CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
- SourceLocation TemplateKWLoc, SourceLocation TildeLoc,
- IdentifierInfo *Name, SourceLocation NameLoc, bool EnteringContext,
- UnqualifiedId &Id, bool AssumeTemplateId) {
+ SourceLocation TemplateKWLoc, SourceLocation TildeLoc, IdentifierInfo *Name,
+ SourceLocation NameLoc, bool EnteringContext, UnqualifiedId &Id,
+ bool AssumeTemplateId) {
assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
TemplateTy Template;
@@ -2574,12 +2571,10 @@ bool Parser::ParseUnqualifiedIdTemplateId(
TildeLoc.isValid());
} else {
bool MemberOfUnknownSpecialization;
- TNK = Actions.isTemplateName(getCurScope(), SS,
- TemplateKWLoc.isValid(), Id,
- ObjectType, EnteringContext, Template,
- MemberOfUnknownSpecialization,
- /*Disambiguation=*/false,
- TildeLoc.isValid());
+ TNK = Actions.isTemplateName(
+ getCurScope(), SS, TemplateKWLoc.isValid(), Id, ObjectType,
+ EnteringContext, Template, MemberOfUnknownSpecialization,
+ /*Disambiguation=*/false, TildeLoc.isValid());
// If lookup found nothing but we're assuming that this is a template
// name, double-check that makes sense syntactically before committing
// to it.
@@ -2637,15 +2632,14 @@ bool Parser::ParseUnqualifiedIdTemplateId(
bool MemberOfUnknownSpecialization;
TemplateName.setIdentifier(Name, NameLoc);
if (ObjectType) {
- TNK = Actions.ActOnTemplateName(
- getCurScope(), SS, TemplateKWLoc, TemplateName, ObjectType,
- EnteringContext, Template, /*AllowInjectedClassName=*/true,
- /*MayBeNNS=*/true);
+ TNK = Actions.ActOnTemplateName(getCurScope(), SS, TemplateKWLoc,
+ TemplateName, ObjectType, EnteringContext,
+ Template, /*AllowInjectedClassName=*/true,
+ /*MayBeNNS=*/true);
} else {
TNK = Actions.isTemplateName(getCurScope(), SS, TemplateKWLoc.isValid(),
- TemplateName, ObjectType,
- EnteringContext, Template,
- MemberOfUnknownSpecialization,
+ TemplateName, ObjectType, EnteringContext,
+ Template, MemberOfUnknownSpecialization,
/*Disambiguation=*/false,
/*MayBeNNS=*/true);
@@ -3058,8 +3052,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
return ParseUnqualifiedIdTemplateId(
SS, ObjectType, ObjectHadErrors,
TemplateKWLoc ? *TemplateKWLoc : SourceLocation(),
- /*TildeLoc=*/SourceLocation(), Id, IdLoc,
- EnteringContext, Result, TemplateSpecified);
+ /*TildeLoc=*/SourceLocation(), Id, IdLoc, EnteringContext, Result,
+ TemplateSpecified);
if (TemplateSpecified) {
TemplateNameKind TNK =
@@ -3156,7 +3150,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
SS, ObjectType, ObjectHadErrors,
TemplateKWLoc ? *TemplateKWLoc : SourceLocation(),
/*TildeLoc=*/SourceLocation(), /*Name=*/nullptr,
- /*NameLoc=*/SourceLocation(), EnteringContext, Result, TemplateSpecified);
+ /*NameLoc=*/SourceLocation(), EnteringContext, Result,
+ TemplateSpecified);
else if (TemplateSpecified &&
Actions.ActOnTemplateName(
getCurScope(), SS, *TemplateKWLoc, Result, ObjectType,
@@ -3251,8 +3246,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
Result.setDestructorName(TildeLoc, nullptr, ClassNameLoc);
return ParseUnqualifiedIdTemplateId(
SS, ObjectType, ObjectHadErrors,
- TemplateKWLoc ? *TemplateKWLoc : SourceLocation(),
- TildeLoc, ClassName, ClassNameLoc, EnteringContext, Result, TemplateSpecified);
+ TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), TildeLoc,
+ ClassName, ClassNameLoc, EnteringContext, Result, TemplateSpecified);
}
// Note that this is a destructor name.
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 57dc19c5353fe..d41d9e903bf49 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -173,16 +173,12 @@ bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R,
return false;
}
-TemplateNameKind Sema::isTemplateName(Scope *S,
- CXXScopeSpec &SS,
- bool hasTemplateKeyword,
- const UnqualifiedId &Name,
- ParsedType ObjectTypePtr,
- bool EnteringContext,
- TemplateTy &TemplateResult,
- bool &MemberOfUnknownSpecialization,
- bool Disambiguation,
- bool MayBeNNS) {
+TemplateNameKind
+Sema::isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword,
+ const UnqualifiedId &Name, ParsedType ObjectTypePtr,
+ bool EnteringContext, TemplateTy &TemplateResult,
+ bool &MemberOfUnknownSpecialization, bool Disambiguation,
+ bool MayBeNNS) {
assert(getLangOpts().CPlusPlus && "No template names in C!");
DeclarationName TName;
@@ -213,8 +209,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
/*RequiredTemplate=*/SourceLocation(),
&AssumedTemplate,
- /*AllowTypoCorrection=*/!Disambiguation,
- MayBeNNS))
+ /*AllowTypoCorrection=*/!Disambiguation, MayBeNNS))
return TNK_Non_template;
MemberOfUnknownSpecialization = R.wasNotFoundInCurrentInstantiation();
@@ -382,8 +377,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
QualType ObjectType, bool EnteringContext,
RequiredTemplateKind RequiredTemplate,
AssumedTemplateKind *ATK,
- bool AllowTypoCorrection,
- bool MayBeNNS) {
+ bool AllowTypoCorrection, bool MayBeNNS) {
if (ATK)
*ATK = AssumedTemplateKind::None;
@@ -456,8 +450,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
}
bool LookupFirstQualifierInScope =
- MayBeNNS && Found.empty() &&
- !ObjectType.isNull() && !IsDependent;
+ MayBeNNS && Found.empty() && !ObjectType.isNull() && !IsDependent;
// FIXME: We should still do the lookup if the object expression is dependent,
// but instead of using them we should store them via
@@ -5797,15 +5790,10 @@ ExprResult Sema::BuildQualifiedTemplateIdExpr(
/// For example, given "x.MetaFun::template apply", the scope specifier
/// \p SS will be "MetaFun::", \p TemplateKWLoc contains the location
/// of the "template" keyword, and "apply" is the \p Name.
-TemplateNameKind Sema::ActOnTemplateName(Scope *S,
- CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const UnqualifiedId &Name,
- ParsedType ObjectType,
- bool EnteringContext,
- TemplateTy &Result,
- bool AllowInjectedClassName,
- bool MayBeNNS) {
+TemplateNameKind Sema::ActOnTemplateName(
+ Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext,
+ TemplateTy &Result, bool AllowInjectedClassName, bool MayBeNNS) {
if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent())
Diag(TemplateKWLoc,
getLangOpts().CPlusPlus11 ?
@@ -5840,10 +5828,10 @@ TemplateNameKind Sema::ActOnTemplateName(Scope *S,
// "template" keyword is now permitted). We follow the C++0x
// rules, even in C++03 mode with a warning, retroactively applying the DR.
bool MemberOfUnknownSpecialization;
- TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name,
- ObjectType, EnteringContext, Result,
- MemberOfUnknownSpecialization,
- /*Disambiguation=*/false, MayBeNNS);
+ TemplateNameKind TNK =
+ isTemplateName(S, SS, TemplateKWLoc.isValid(), Name, ObjectType,
+ EnteringContext, Result, MemberOfUnknownSpecialization,
+ /*Disambiguation=*/false, MayBeNNS);
if (TNK != TNK_Non_template) {
// We resolved this to a (non-dependent) template name. Return it.
auto *LookupRD = dyn_cast_or_null<CXXRecordDecl>(LookupCtx);
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 7b24ff6aa024f..27c953ec6cf44 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1310,8 +1310,7 @@ class TreeTransform {
SourceLocation TemplateKWLoc,
const IdentifierInfo &Name,
SourceLocation NameLoc, QualType ObjectType,
- bool AllowInjectedClassName,
- bool MayBeNNS);
+ bool AllowInjectedClassName, bool MayBeNNS);
/// Build a new template name given a nested name specifier and the
/// overloaded operator name that is referred to as a template.
>From 0f0b09a31e7b6c4f66f433ee03d0ed5195abfccd Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 4 Jun 2024 09:33:30 -0400
Subject: [PATCH 17/19] [FOLD] reorder diags
---
clang/test/CXX/temp/temp.names/p3-23.cpp | 36 ++++++++++++------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/clang/test/CXX/temp/temp.names/p3-23.cpp b/clang/test/CXX/temp/temp.names/p3-23.cpp
index b041bef88416d..27c24e1d61706 100644
--- a/clang/test/CXX/temp/temp.names/p3-23.cpp
+++ b/clang/test/CXX/temp/temp.names/p3-23.cpp
@@ -12,8 +12,8 @@ namespace FoundNothing {
struct A {
void f1() {
this->x<0; // expected-error {{no member named 'x' in 'A<T>'}}
- this->x<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{no member named 'x' in 'A<T>'}}
+ this->x<0>; // expected-error {{no member named 'x' in 'A<T>'}}
+ // expected-error at -1 {{expected expression}}
this->x<0>1; // expected-error {{no member named 'x' in 'A<T>'}}
}
};
@@ -43,23 +43,23 @@ namespace FoundSingleNonTemplate {
void g1() {
this->f0<0; // expected-error {{no member named 'f0' in 'B<T>'}}
- this->f0<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{no member named 'f0' in 'B<T>'}}
+ this->f0<0>; // expected-error {{no member named 'f0' in 'B<T>'}}
+ // expected-error at -1 {{expected expression}}
this->f0<0>1; // expected-error {{no member named 'f0' in 'B<T>'}}
this->A0<0; // expected-error {{no member named 'A0' in 'B<T>'}}
- this->A0<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{no member named 'A0' in 'B<T>'}}
+ this->A0<0>; // expected-error {{no member named 'A0' in 'B<T>'}}
+ // expected-error at -1 {{expected expression}}
this->A0<0>1; // expected-error {{no member named 'A0' in 'B<T>'}}
this->f1<0; // expected-error {{reference to non-static member function must be called}}
- this->f1<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{reference to non-static member function must be called}}
+ this->f1<0>; // expected-error {{reference to non-static member function must be called}}
+ // expected-error at -1 {{expected expression}}
this->f1<0>1; // expected-error {{reference to non-static member function must be called}}
this->A1<0; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
- this->A1<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ this->A1<0>; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ // expected-error at -1 {{expected expression}}
this->A1<0>1; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
}
};
@@ -148,23 +148,23 @@ namespace FoundAmbiguousNonTemplate {
void g1() {
this->f0<0; // expected-error {{no member named 'f0' in 'B<T>'}}
- this->f0<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{no member named 'f0' in 'B<T>'}}
+ this->f0<0>; // expected-error {{no member named 'f0' in 'B<T>'}}
+ // expected-error at -1 {{expected expression}}
this->f0<0>1; // expected-error {{no member named 'f0' in 'B<T>'}}
this->A0<0; // expected-error {{no member named 'A0' in 'B<T>'}}
- this->A0<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{no member named 'A0' in 'B<T>'}}
+ this->A0<0>; // expected-error {{no member named 'A0' in 'B<T>'}}
+ // expected-error at -1 {{expected expression}}
this->A0<0>1; // expected-error {{no member named 'A0' in 'B<T>'}}
this->f1<0; // expected-error {{reference to non-static member function must be called}}
- this->f1<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{reference to non-static member function must be called}}
+ this->f1<0>; // expected-error {{reference to non-static member function must be called}}
+ // expected-error at -1 {{expected expression}}
this->f1<0>1; // expected-error {{reference to non-static member function must be called}}
this->A1<0; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
- this->A1<0>; // expected-error {{expected expression}}
- // expected-error at -1 {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ this->A1<0>; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
+ // expected-error at -1 {{expected expression}}
this->A1<0>1; // expected-error {{cannot refer to type member 'A1' in 'B<T>' with '->'}}
}
};
>From 33685f9242bd039a512e758947566102e338717f Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 4 Jun 2024 10:19:18 -0400
Subject: [PATCH 18/19] [FOLD] fix warning
---
clang/lib/AST/ExprCXX.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 826f66fe1624c..dbc69416e3f81 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -1447,8 +1447,8 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
const TemplateArgumentListInfo *TemplateArgs)
: Expr(CXXDependentScopeMemberExprClass, Ctx.DependentTy, VK_LValue,
OK_Ordinary),
- Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc),
- MemberNameInfo(MemberNameInfo) {
+ Base(Base), BaseType(BaseType), MemberNameInfo(MemberNameInfo),
+ OperatorLoc(OperatorLoc) {
CXXDependentScopeMemberExprBits.IsArrow = IsArrow;
CXXDependentScopeMemberExprBits.HasQualifier = QualifierLoc.hasQualifier();
CXXDependentScopeMemberExprBits.NumUnqualifiedLookups =
>From bcca785cf7e4266cdb8062e4fd20732bac462d29 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 4 Jun 2024 10:22:13 -0400
Subject: [PATCH 19/19] [FOLD] cleanups
---
clang/lib/Parse/ParseExprCXX.cpp | 40 +++++++-------------------------
1 file changed, 8 insertions(+), 32 deletions(-)
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index d39ab31407414..2c8274350c455 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1907,45 +1907,21 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc,
IdentifierInfo *Name = Tok.getIdentifierInfo();
SourceLocation NameLoc = ConsumeToken();
SecondTypeName.setIdentifier(Name, NameLoc);
-// SecondTypeName.setDestructorName(TildeLoc, nullptr, NameLoc);
-// If there is a '<', the second type name is a template-id. Parse
-// it as such.
-//
-// FIXME: This is not a context in which a '<' is assumed to start a template
-// argument list. This affects examples such as
-// void f(auto *p) { p->~X<int>(); }
-// ... but there's no ambiguity, and nowhere to write 'template' in such an
-// example, so we accept it anyway.
-#if 1
+ // If there is a '<', the second type name is a template-id. Parse
+ // it as such.
+ //
+ // FIXME: This is not a context in which a '<' is assumed to start a template
+ // argument list. This affects examples such as
+ // void f(auto *p) { p->~X<int>(); }
+ // ... but there's no ambiguity, and nowhere to write 'template' in such an
+ // example, so we accept it anyway
if (Tok.is(tok::less) && ParseUnqualifiedIdTemplateId(
SS, ObjectType, Base && Base->containsErrors(),
/*TemplateKWLoc=*/SourceLocation(), TildeLoc,
Name, NameLoc, false, SecondTypeName,
/*AssumeTemplateId=*/true))
return ExprError();
-#endif
-#if 0
- if (Tok.is(tok::less)) {
- TemplateTy Template;
- TemplateNameKind TNK = Actions.ActOnTemplateName(
- getCurScope(), SS, /*TemplateKWLoc=*/SourceLocation(),
- SecondTypeName, ObjectType,
- /*EnteringContext=*/false, Template,
- /*AllowInjectedClassName*/true,
- /*MayBeNNS=*/true);
- if (TNK == TNK_Non_template)
- return ExprError();
-
- if (AnnotateTemplateIdToken(Template, TNK, SS,
- /*TemplateKWLoc=*/SourceLocation(),
- SecondTypeName, /*AllowTypeAnnotation=*/false))
- return ExprError();
- assert(Tok.is(tok::annot_template_id));
- SecondTypeName.setTemplateId(takeTemplateIdAnnotation(Tok));
- ConsumeAnnotationToken();
- }
-#endif
return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind,
SS, FirstTypeName, CCLoc, TildeLoc,
More information about the cfe-commits
mailing list