-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts #91498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: Krystian Stasiowski (sdkrystian) ChangesFixes this crash caused by #90152. Will add tests shortly. Full diff: https://github.com/llvm/llvm-project/pull/91498.diff 2 Files Affected:
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;
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
few little things? Mostly looks ok.
DeclContext *LookupContext) { | ||
auto *LookupRecord = dyn_cast_if_present<CXXRecordDecl>(LookupContext); | ||
return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord && | ||
!LookupRecord->isBeingDefined() && LookupRecord->isDependentContext(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the !isBeingDefined
? That seems weird given the name of this function.
Also, instead of making it static, can you just toss it in the anonymous NS above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason operator=
is dependent when the current class is a templated entity is because each specialization declares its own set of special member functions, and according to [special] p1, they are "declared at the closing }
of the class-specifier". When instantiating a templated class, they are declared after all other member declarations are instantiated.
If the lookup context is the current instantiation and the current instantiation is incomplete (e.g. because operator=
is named outside a complete-class context), we will never find the implicitly declared copy/move assignment operators because they are always declared last (neither in the template definition context, nor in the template instantiation context). So, we just treat it like any other unqualified name during lookup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I'll add a test which calls operator=
with a non-dependent argument -- in that case it will be diagnosed before the template is instantiated)
fa3eb50
to
02c05a2
Compare
This caused some breakage in something completely unrelated to operator= O_o This is from webrtc code in Firefox:
The lines with error are: https://searchfox.org/mozilla-central/rev/c34cf367c29601ed56ae4ea51e20b28cd8331f9c/third_party/libwebrtc/rtc_base/containers/flat_map.h#331,343 The corresponding declarations are: I don't see how they differ. |
Reverting just the SemaTemplate.cpp change fixes it. |
@glandium I've reduced it to the following: template<typename T>
struct A
{
static constexpr bool B = true;
};
template<bool V>
struct C { };
template<typename T>
struct D
{
C<A<T>::B> f();
};
template<typename T>
auto D<T>::f() -> C<A<T>::B> { } The problem is that we build a Since we have no idea whether |
Chromium is also seeing similar breakages. @sdkrystian is this breaking valid code? I can't tell from your latest comment. (if it is breaking valid code we should revert) |
@aeubanks I think I'm going to revert this & maybe partially revert the changes in #90152 which cause |
…mplete-class contexts (llvm#91498)" This reverts commit 62b5b61.
Its sad to do so, but I think it makes the most sense. We've got a good amount of feedback of the breakages, and I think figuring them out and reapplying these changes in a followup patch is a perfectly reasonable way forward. |
cherry-picked: 8009bbe [email protected] Tue Apr 30 14:25:09 2024 -0400 Reapply "[Clang][Sema] Diagnose class member access expressions naming non-existent members of the current instantiation prior to instantiation in the absence of dependent base classes (llvm#84050)" (llvm#90152) 3191e0b [email protected] Fri May 3 17:07:52 2024 -0400 [Clang][Sema] Fix template name lookup for operator= (llvm#90999) 62b5b61 [email protected] Wed May 8 20:49:59 2024 -0400 [Clang][Sema] Fix lookup of dependent operator= outside of complete-class contexts (llvm#91498) 75ebcbf [email protected] Thu May 9 16:34:40 2024 -0400 [Clang][Sema] Revert changes to operator= lookup in templated classes from llvm#91498, llvm#90999, and llvm#90152 (llvm#91620) 596a9c1 [email protected] Mon May 13 12:24:46 2024 -0400 [Clang][Sema] Fix bug where operator-> typo corrects in the current instantiation (llvm#91972) fd87d76 [email protected] Mon May 20 13:55:01 2024 -0400 [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions (llvm#92318) e75b58c [email protected] Mon May 20 14:50:58 2024 -0400 [Clang][Sema] Do not add implicit 'const' when matching constexpr function template explicit specializations after C++14 (llvm#92449) bae2c54 [email protected] Mon Jul 1 20:55:57 2024 +0300 [clang][NFC] Move documentation of `Sema` functions into `Sema.h` e6d305e [email protected] Mon Sep 4 16:54:42 2023 +0200 Add support of Windows Trace Logging macros Change-Id: I521b2ebabd7eb9a0df78c577992bfd8508ba44fd
… lookup (llvm#91620) This patch cherry-pick missing part of 75ebcbf. Fixes: SWDEV-520199 The original commit message is: [Clang][Sema] Revert changes to operator= lookup in templated classes from llvm#91498, llvm#90999, and llvm#90152 (llvm#91620) This reverts changes in llvm#91498, llvm#90999, and llvm#90152 which make `operator=` dependent whenever the current class is templated. Change-Id: I352db5cc20ecf4a0ccdbb921c63da0867651ffc4
… lookup (llvm#91620) This patch cherry-pick missing part of 75ebcbf. Fixes: SWDEV-520199 The original commit message is: [Clang][Sema] Revert changes to operator= lookup in templated classes from llvm#91498, llvm#90999, and llvm#90152 (llvm#91620) This reverts changes in llvm#91498, llvm#90999, and llvm#90152 which make `operator=` dependent whenever the current class is templated. Change-Id: I352db5cc20ecf4a0ccdbb921c63da0867651ffc4
Fixes this crash caused by #90152.
Will add tests shortly.