From 13d44a8f5647819efd3ef57af384a3666f99d066 Mon Sep 17 00:00:00 2001 From: Alexander Shaposhnikov Date: Fri, 7 Apr 2023 18:32:49 +0000 Subject: [PATCH] Revert "[Clang][Sema] Fix comparison of constraint expressions" This temporarily reverts commit 60bee9ff544541e83ffbd4be31923d0e8b644690. The diff will be recommitted once the newly discovered regressions are fixed. --- clang/lib/Sema/SemaConcept.cpp | 51 +++---- clang/lib/Sema/SemaOverload.cpp | 2 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 6 - clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 60 ++++----- .../test/SemaTemplate/concepts-out-of-line-def.cpp | 150 --------------------- clang/test/SemaTemplate/concepts.cpp | 9 -- 6 files changed, 47 insertions(+), 231 deletions(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 4e7033c..2882b10 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -260,9 +260,6 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, return SubstitutedAtomicExpr; } - if (SubstitutedAtomicExpr.get()->isValueDependent()) - return SubstitutedAtomicExpr; - EnterExpressionEvaluationContext ConstantEvaluated( S, Sema::ExpressionEvaluationContext::ConstantEvaluated); SmallVector EvaluationDiags; @@ -755,43 +752,27 @@ namespace { }; } // namespace -static const Expr *SubstituteConstraintExpression(Sema &S, const NamedDecl *ND, - const Expr *ConstrExpr) { - MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( - ND, /*Final=*/false, /*Innermost=*/nullptr, - /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/true, /*SkipForSpecialization*/ false); - if (MLTAL.getNumSubstitutedLevels() == 0) - return ConstrExpr; - Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false); - std::optional ThisScope; - if (auto *RD = dyn_cast(ND->getDeclContext())) - ThisScope.emplace(S, const_cast(RD), Qualifiers()); - ExprResult SubstConstr = - S.SubstConstraintExpr(const_cast(ConstrExpr), MLTAL); - if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable()) - return nullptr; - return SubstConstr.get(); -} - bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const NamedDecl *New, const Expr *NewConstr) { - if (OldConstr == NewConstr) - return true; if (Old && New && Old != New) { - if (const Expr *SubstConstr = - SubstituteConstraintExpression(*this, Old, OldConstr)) - OldConstr = SubstConstr; - else - return false; - if (const Expr *SubstConstr = - SubstituteConstraintExpression(*this, New, NewConstr)) - NewConstr = SubstConstr; - else - return false; + unsigned Depth1 = CalculateTemplateDepthForConstraints( + *this, Old); + unsigned Depth2 = CalculateTemplateDepthForConstraints( + *this, New); + + // Adjust the 'shallowest' verison of this to increase the depth to match + // the 'other'. + if (Depth2 > Depth1) { + OldConstr = AdjustConstraintDepth(*this, Depth2 - Depth1) + .TransformExpr(const_cast(OldConstr)) + .get(); + } else if (Depth1 > Depth2) { + NewConstr = AdjustConstraintDepth(*this, Depth1 - Depth2) + .TransformExpr(const_cast(NewConstr)) + .get(); + } } llvm::FoldingSetNodeID ID1, ID2; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index aa40bff4..ab43005 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1294,7 +1294,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, // We check the return type and template parameter lists for function // templates first; the remaining checks follow. bool SameTemplateParameterList = TemplateParameterListsAreEqual( - NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate, + NewTemplate->getTemplateParameters(), OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch); bool SameReturnType = Context.hasSameType(Old->getDeclaredReturnType(), New->getDeclaredReturnType()); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index bdcee77..526f19b 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -208,10 +208,6 @@ Response HandleFunction(const FunctionDecl *Function, return Response::UseNextDecl(Function); } -Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) { - return Response::ChangeDecl(FTD->getLexicalDeclContext()); -} - Response HandleRecordDecl(const CXXRecordDecl *Rec, MultiLevelTemplateArgumentList &Result, ASTContext &Context, @@ -322,8 +318,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( } else if (const auto *CSD = dyn_cast(CurDecl)) { R = HandleImplicitConceptSpecializationDecl(CSD, Result); - } else if (const auto *FTD = dyn_cast(CurDecl)) { - R = HandleFunctionTemplateDecl(FTD); } else if (!isa(CurDecl)) { R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl); if (CurDecl->getDeclContext()->isTranslationUnit()) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f941882..e749c24 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1653,12 +1653,33 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { << QualifierLoc.getSourceRange(); return nullptr; } + + if (PrevClassTemplate) { + const ClassTemplateDecl *MostRecentPrevCT = + PrevClassTemplate->getMostRecentDecl(); + TemplateParameterList *PrevParams = + MostRecentPrevCT->getTemplateParameters(); + + // Make sure the parameter lists match. + if (!SemaRef.TemplateParameterListsAreEqual( + D->getTemplatedDecl(), InstParams, + MostRecentPrevCT->getTemplatedDecl(), PrevParams, true, + Sema::TPL_TemplateMatch)) + return nullptr; + + // Do some additional validation, then merge default arguments + // from the existing declarations. + if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams, + Sema::TPC_ClassTemplate)) + return nullptr; + } } CXXRecordDecl *RecordInst = CXXRecordDecl::Create( SemaRef.Context, Pattern->getTagKind(), DC, Pattern->getBeginLoc(), Pattern->getLocation(), Pattern->getIdentifier(), PrevDecl, /*DelayTypeCreation=*/true); + if (QualifierLoc) RecordInst->setQualifierInfo(QualifierLoc); @@ -1668,37 +1689,16 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { ClassTemplateDecl *Inst = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getIdentifier(), InstParams, RecordInst); + assert(!(isFriend && Owner->isDependentContext())); + Inst->setPreviousDecl(PrevClassTemplate); + RecordInst->setDescribedClassTemplate(Inst); if (isFriend) { - assert(!Owner->isDependentContext()); - Inst->setLexicalDeclContext(Owner); - RecordInst->setLexicalDeclContext(Owner); - - if (PrevClassTemplate) { - RecordInst->setTypeForDecl( - PrevClassTemplate->getTemplatedDecl()->getTypeForDecl()); - const ClassTemplateDecl *MostRecentPrevCT = - PrevClassTemplate->getMostRecentDecl(); - TemplateParameterList *PrevParams = - MostRecentPrevCT->getTemplateParameters(); - - // Make sure the parameter lists match. - if (!SemaRef.TemplateParameterListsAreEqual( - RecordInst, InstParams, MostRecentPrevCT->getTemplatedDecl(), - PrevParams, true, Sema::TPL_TemplateMatch)) - return nullptr; - - // Do some additional validation, then merge default arguments - // from the existing declarations. - if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams, - Sema::TPC_ClassTemplate)) - return nullptr; - + if (PrevClassTemplate) Inst->setAccess(PrevClassTemplate->getAccess()); - } else { + else Inst->setAccess(D->getAccess()); - } Inst->setObjectOfFriendDecl(); // TODO: do we want to track the instantiation progeny of this @@ -1709,15 +1709,15 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Inst->setInstantiatedFromMemberTemplate(D); } - Inst->setPreviousDecl(PrevClassTemplate); - // Trigger creation of the type for the instantiation. - SemaRef.Context.getInjectedClassNameType( - RecordInst, Inst->getInjectedClassNameSpecialization()); + SemaRef.Context.getInjectedClassNameType(RecordInst, + Inst->getInjectedClassNameSpecialization()); // Finish handling of friends. if (isFriend) { DC->makeDeclVisibleInContext(Inst); + Inst->setLexicalDeclContext(Owner); + RecordInst->setLexicalDeclContext(Owner); return Inst; } diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp index a0fb1c3..222b78e 100644 --- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp +++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp @@ -127,153 +127,3 @@ static_assert(S::specialization("str") == SPECIALIZATION_CONCEPT); static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES); } // namespace multiple_template_parameter_lists - -static constexpr int CONSTRAINED_METHOD_1 = 1; -static constexpr int CONSTRAINED_METHOD_2 = 2; - -namespace constrained_members { - -template -struct S { - template - static constexpr int constrained_method(); -}; - -template <> -template -constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; } - -template <> -template -constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; } - -static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1); -static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2); - - -template -concept ConceptT1T2 = true; - -template -struct S12 { - template T4> - static constexpr int constrained_method(); -}; - -template<> -template T5> -constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; } - -template<> -template T5> -constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; } - -static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1); -static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2); - -} // namespace constrained members - -namespace constrained_members_of_nested_types { - -template -struct S { - struct Inner0 { - struct Inner1 { - template - static constexpr int constrained_method(); - }; - }; -}; - -template <> -template -constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; } - -template <> -template -constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; } - -static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1); -static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2); - - -template -concept ConceptT1T2 = true; - -template -struct S12 { - struct Inner0 { - struct Inner1 { - template T4> - static constexpr int constrained_method(); - }; - }; -}; - -template<> -template T5> -constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; } - -template<> -template T5> -constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; } - -static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1); -static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2); - -} // namespace constrained_members_of_nested_types - -namespace constrained_member_sfinae { - -template struct S { - template - static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) { - return CONSTRAINED_METHOD_1; - } - - template - static constexpr int constrained_method() requires (sizeof(int[N]) == 16); -}; - -template<> -template -constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) { - return CONSTRAINED_METHOD_2; -} - -// Verify that there is no amiguity in this case. -static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2); - -} // namespace constrained_member_sfinae - -namespace requires_expression_references_members { - -void accept1(int x); -void accept2(XY xy); - -template struct S { - T Field = T(); - - constexpr int constrained_method() - requires requires { accept1(Field); }; - - constexpr int constrained_method() - requires requires { accept2(Field); }; -}; - -template -constexpr int S::constrained_method() - requires requires { accept1(Field); } { - return CONSTRAINED_METHOD_1; -} - -template -constexpr int S::constrained_method() - requires requires { accept2(Field); } { - return CONSTRAINED_METHOD_2; -} - -static_assert(S().constrained_method() == CONSTRAINED_METHOD_1); -static_assert(S().constrained_method() == CONSTRAINED_METHOD_2); - -} // namespace requires_expression_references_members diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 19638bb..d28c2b2 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -816,12 +816,3 @@ static_assert(Parent::TakesBinary::i == 0); static_assert(Parent::TakesBinary::i == 0); } -namespace TemplateInsideNonTemplateClass { -template concept C = true; - -template auto L = [] U>() {}; - -struct Q { - template U> friend constexpr auto decltype(L)::operator()() const; -}; -} // namespace TemplateInsideNonTemplateClass -- 2.7.4