Author: Krystian Stasiowski Date: 2024-05-09T16:34:40-04:00 New Revision: 75ebcbf24abb2e5b045ec920bc86f667516e4cc6
URL: https://github.com/llvm/llvm-project/commit/75ebcbf24abb2e5b045ec920bc86f667516e4cc6 DIFF: https://github.com/llvm/llvm-project/commit/75ebcbf24abb2e5b045ec920bc86f667516e4cc6.diff LOG: [Clang][Sema] Revert changes to operator= lookup in templated classes from #91498, #90999, and #90152 (#91620) This reverts changes in #91498, #90999, and #90152 which make `operator=` dependent whenever the current class is templated. Added: Modified: clang/lib/Sema/SemaExprMember.cpp clang/lib/Sema/SemaLookup.cpp clang/lib/Sema/SemaTemplate.cpp clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 5facb14a18b7c..9fa69da4f9685 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -996,7 +996,10 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // build a CXXDependentScopeMemberExpr. if (R.wasNotFoundInCurrentInstantiation() || (IsArrow && !BaseExprType->isPointerType() && - BaseExprType->isDependentType())) + BaseExprType->isDependentType()) || + (R.getLookupName().getCXXOverloadedOperator() == OO_Equal && + (SS.isSet() ? SS.getScopeRep()->isDependent() + : BaseExprType->isDependentType()))) return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS, TemplateKWLoc, FirstQualifierInScope, R.getLookupNameInfo(), TemplateArgs); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e20de338ebb16..7251aabc6af21 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1267,20 +1267,6 @@ struct FindLocalExternScope { LookupResult &R; bool OldFindLocalExtern; }; - -/// Returns true if 'operator=' should be treated as a dependent name. -bool isDependentAssignmentOperator(DeclarationName Name, - DeclContext *LookupContext) { - const auto *LookupRecord = dyn_cast_if_present<CXXRecordDecl>(LookupContext); - // If the lookup context is the current instantiation but we are outside a - // complete-class context, we will never find the implicitly declared - // copy/move assignment operators because they are declared at the closing '}' - // of the class specifier. In such cases, we treat 'operator=' like any other - // unqualified name because the results of name lookup in the template - // definition/instantiation context will always be the same. - return Name.getCXXOverloadedOperator() == OO_Equal && LookupRecord && - !LookupRecord->isBeingDefined() && LookupRecord->isDependentContext(); -} } // end anonymous namespace bool Sema::CppLookupName(LookupResult &R, Scope *S) { @@ -1289,6 +1275,14 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { 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 @@ -1301,20 +1295,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { return false; } - // 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()) { - if (!R.isTemplateNameLookup() && - isDependentAssignmentOperator(Name, DC)) { - R.setNotFoundInCurrentInstantiation(); - return false; - } - DeclareImplicitMemberFunctionsWithName(*this, Name, R.getNameLoc(), DC); - } - } - // Implicitly declare member functions with the name we're looking for, if in // fact we are in a scope where it matters. @@ -2478,6 +2458,10 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, } } QL(LookupCtx); + CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx); + // FIXME: Per [temp.dep.general]p2, an unqualified name is also dependent + // if it's a dependent conversion-function-id or operator= where the current + // class is a templated entity. This should be handled in LookupName. if (!InUnqualifiedLookup && !R.isForRedeclaration()) { // C++23 [temp.dep.type]p5: // A qualified name is dependent if @@ -2488,16 +2472,13 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // is operator=, or // - [...] if (DeclarationName Name = R.getLookupName(); - (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && - Name.getCXXNameType()->isDependentType()) || - (!R.isTemplateNameLookup() && - isDependentAssignmentOperator(Name, LookupCtx))) { + Name.getNameKind() == DeclarationName::CXXConversionFunctionName && + Name.getCXXNameType()->isDependentType()) { R.setNotFoundInCurrentInstantiation(); return false; } } - CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx); if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (LookupRec) @@ -2588,6 +2569,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, return true; }; + bool TemplateNameLookup = R.isTemplateNameLookup(); + // Determine whether two sets of members contain the same members, as // required by C++ [class.member.lookup]p6. auto HasSameDeclarations = [&](DeclContext::lookup_iterator A, @@ -2609,7 +2592,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 (R.isTemplateNameLookup()) + if (TemplateNameLookup) if (auto *TD = getAsTemplateNameDecl(ND)) ND = TD; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 480bc74c2001a..2fce2238f9c10 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) { - QualType ThisType = getCurrentThisType(); + DeclContext *DC = getFunctionLevelDeclContext(); // C++11 [expr.prim.general]p12: // An id-expression that denotes a non-static data member or non-static @@ -748,7 +748,11 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, IsEnum = isa_and_nonnull<EnumType>(NNS->getAsType()); if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum && - !ThisType.isNull()) { + isa<CXXMethodDecl>(DC) && + cast<CXXMethodDecl>(DC)->isImplicitObjectMemberFunction()) { + QualType ThisType = + cast<CXXMethodDecl>(DC)->getThisType().getNonReferenceType(); + // Since the 'this' expression is synthesized, we don't need to // perform the double-lookup check. NamedDecl *FirstQualifierInScope = nullptr; 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 43053c18c5076..1adbc33a701c1 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 @@ -483,7 +483,6 @@ namespace N3 { }; template struct E<int>; // expected-note {{in instantiation of template class 'N3::E<int>' requested here}} - } // namespace N3 namespace N4 { @@ -551,4 +550,5 @@ namespace N4 { }; template void D<B>::instantiated(D); // expected-note {{in instantiation of}} + } // namespace N4 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits