[clang] [Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (PR #91498)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Wed May 8 13:04:07 PDT 2024
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/91498
>From 60d2030216403c7cfa8272396497d31aed314288 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 8 May 2024 12:18:49 -0400
Subject: [PATCH 1/4] [Clang][Sema] Fix lookup of dependent operator= outside
of complete-class contexts
---
clang/lib/Sema/SemaLookup.cpp | 28 +++++++++++++---------------
clang/lib/Sema/SemaTemplate.cpp | 7 ++-----
2 files changed, 15 insertions(+), 20 deletions(-)
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index e63da5875d2c9..6bd5932212b92 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1269,19 +1269,19 @@ struct FindLocalExternScope {
};
} // end anonymous namespace
+static bool isDependentAssignmentOperator(DeclarationName Name,
+ DeclContext *LookupContext) {
+ auto *LookupRecord = dyn_cast_if_present<CXXRecordDecl>(LookupContext);
+ return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord &&
+ !LookupRecord->isBeingDefined() && LookupRecord->isDependentContext();
+}
+
bool Sema::CppLookupName(LookupResult &R, Scope *S) {
assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup");
DeclarationName Name = R.getLookupName();
Sema::LookupNameKind NameKind = R.getLookupKind();
- // If this is the name of an implicitly-declared special member function,
- // go through the scope stack to implicitly declare
- if (isImplicitlyDeclaredMemberFunctionName(Name)) {
- for (Scope *PreS = S; PreS; PreS = PreS->getParent())
- if (DeclContext *DC = PreS->getEntity())
- DeclareImplicitMemberFunctionsWithName(*this, Name, R.getNameLoc(), DC);
- }
// C++23 [temp.dep.general]p2:
// The component name of an unqualified-id is dependent if
// - it is a conversion-function-id whose conversion-type-id
@@ -1299,9 +1299,8 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
if (isImplicitlyDeclaredMemberFunctionName(Name)) {
for (Scope *PreS = S; PreS; PreS = PreS->getParent())
if (DeclContext *DC = PreS->getEntity()) {
- if (DC->isDependentContext() && isa<CXXRecordDecl>(DC) &&
- Name.getCXXOverloadedOperator() == OO_Equal &&
- !R.isTemplateNameLookup()) {
+ if (!R.isTemplateNameLookup() &&
+ isDependentAssignmentOperator(Name, DC)) {
R.setNotFoundInCurrentInstantiation();
return false;
}
@@ -2472,8 +2471,6 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
}
} QL(LookupCtx);
- bool TemplateNameLookup = R.isTemplateNameLookup();
- CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
if (!InUnqualifiedLookup && !R.isForRedeclaration()) {
// C++23 [temp.dep.type]p5:
// A qualified name is dependent if
@@ -2486,13 +2483,14 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
if (DeclarationName Name = R.getLookupName();
(Name.getNameKind() == DeclarationName::CXXConversionFunctionName &&
Name.getCXXNameType()->isDependentType()) ||
- (Name.getCXXOverloadedOperator() == OO_Equal && LookupRec &&
- LookupRec->isDependentContext() && !TemplateNameLookup)) {
+ (!R.isTemplateNameLookup() &&
+ isDependentAssignmentOperator(Name, LookupCtx))) {
R.setNotFoundInCurrentInstantiation();
return false;
}
}
+ CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
if (LookupDirect(*this, R, LookupCtx)) {
R.resolveKind();
if (LookupRec)
@@ -2604,7 +2602,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// template, and if the name is used as a template-name, the
// reference refers to the class template itself and not a
// specialization thereof, and is not ambiguous.
- if (TemplateNameLookup)
+ if (R.isTemplateNameLookup())
if (auto *TD = getAsTemplateNameDecl(ND))
ND = TD;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 7e57fa0696725..480bc74c2001a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -726,7 +726,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
const DeclarationNameInfo &NameInfo,
bool isAddressOfOperand,
const TemplateArgumentListInfo *TemplateArgs) {
- DeclContext *DC = getFunctionLevelDeclContext();
+ QualType ThisType = getCurrentThisType();
// C++11 [expr.prim.general]p12:
// An id-expression that denotes a non-static data member or non-static
@@ -748,10 +748,7 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS,
IsEnum = isa_and_nonnull<EnumType>(NNS->getAsType());
if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum &&
- isa<CXXMethodDecl>(DC) &&
- cast<CXXMethodDecl>(DC)->isImplicitObjectMemberFunction()) {
- QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType().getNonReferenceType();
-
+ !ThisType.isNull()) {
// Since the 'this' expression is synthesized, we don't need to
// perform the double-lookup check.
NamedDecl *FirstQualifierInScope = nullptr;
>From 75c5e42ebc01299924c26b9fc03eaa2621696c8e Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 8 May 2024 15:11:02 -0400
Subject: [PATCH 2/4] [FOLD] add test
---
.../test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
index 46dd52f8c4c13..00507261406fb 100644
--- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
@@ -471,6 +471,14 @@ namespace N3 {
this->C::operator=(*this);
}
};
+
+ template<typename T>
+ struct D {
+ auto instantiated(D& d) -> decltype(operator=(d)); // expected-error {{use of undeclared 'operator='}}
+ };
+
+ template struct D<int>; // expected-note {{in instantiation of template class 'D<int>' requested here}}
+
} // namespace N3
namespace N4 {
>From 1fa4a767e4abdd514d6d515e2c8c09be4e9ea03c Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 8 May 2024 16:02:08 -0400
Subject: [PATCH 3/4] [FOLD] add test where template is not instantiated
---
.../test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
index 00507261406fb..1a62fe688658f 100644
--- a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp
@@ -474,10 +474,15 @@ namespace N3 {
template<typename T>
struct D {
- auto instantiated(D& d) -> decltype(operator=(d)); // expected-error {{use of undeclared 'operator='}}
+ auto not_instantiated() -> decltype(operator=(0)); // expected-error {{use of undeclared 'operator='}}
};
- template struct D<int>; // expected-note {{in instantiation of template class 'D<int>' requested here}}
+ template<typename T>
+ struct E {
+ auto instantiated(E& e) -> decltype(operator=(e)); // expected-error {{use of undeclared 'operator='}}
+ };
+
+ template struct E<int>; // expected-note {{in instantiation of template class 'E<int>' requested here}}
} // namespace N3
>From 3731d0a3ff7dfb27b06e969fdc1610bfa1b2d94e Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Wed, 8 May 2024 16:03:55 -0400
Subject: [PATCH 4/4] [FOLD] address review comments
---
clang/lib/Sema/SemaLookup.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 6bd5932212b92..100249450d5ce 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1248,6 +1248,13 @@ static DeclContext *findOuterContext(Scope *S) {
return nullptr;
}
+static bool isDependentAssignmentOperator(DeclarationName Name,
+ DeclContext *LookupContext) {
+ const auto *LookupRecord = dyn_cast_if_present<CXXRecordDecl>(LookupContext);
+ return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord &&
+ !LookupRecord->isBeingDefined() && LookupRecord->isDependentContext();
+}
+
namespace {
/// An RAII object to specify that we want to find block scope extern
/// declarations.
@@ -1269,13 +1276,6 @@ struct FindLocalExternScope {
};
} // end anonymous namespace
-static bool isDependentAssignmentOperator(DeclarationName Name,
- DeclContext *LookupContext) {
- auto *LookupRecord = dyn_cast_if_present<CXXRecordDecl>(LookupContext);
- return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord &&
- !LookupRecord->isBeingDefined() && LookupRecord->isDependentContext();
-}
-
bool Sema::CppLookupName(LookupResult &R, Scope *S) {
assert(getLangOpts().CPlusPlus && "Can perform only C++ lookup");
More information about the cfe-commits
mailing list