[clang] 13d44a8 - Revert "[Clang][Sema] Fix comparison of constraint expressions"
Alexander Shaposhnikov via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 7 11:43:06 PDT 2023
Author: Alexander Shaposhnikov
Date: 2023-04-07T18:41:57Z
New Revision: 13d44a8f5647819efd3ef57af384a3666f99d066
URL: https://github.com/llvm/llvm-project/commit/13d44a8f5647819efd3ef57af384a3666f99d066
DIFF: https://github.com/llvm/llvm-project/commit/13d44a8f5647819efd3ef57af384a3666f99d066.diff
LOG: 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.
Added:
Modified:
clang/lib/Sema/SemaConcept.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/SemaTemplate/concepts-out-of-line-def.cpp
clang/test/SemaTemplate/concepts.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 4e7033c9d588..2882b10613fd 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<PartialDiagnosticAt, 2> 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<Sema::CXXThisScopeRAII> ThisScope;
- if (auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext()))
- ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
- ExprResult SubstConstr =
- S.SubstConstraintExpr(const_cast<clang::Expr *>(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<Expr *>(OldConstr))
+ .get();
+ } else if (Depth1 > Depth2) {
+ NewConstr = AdjustConstraintDepth(*this, Depth1 - Depth2)
+ .TransformExpr(const_cast<Expr *>(NewConstr))
+ .get();
+ }
}
llvm::FoldingSetNodeID ID1, ID2;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index aa40bff4c575..ab4300518ecf 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 bdcee77ce67c..526f19b8aedc 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<ImplicitConceptSpecializationDecl>(CurDecl)) {
R = HandleImplicitConceptSpecializationDecl(CSD, Result);
- } else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CurDecl)) {
- R = HandleFunctionTemplateDecl(FTD);
} else if (!isa<DeclContext>(CurDecl)) {
R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl);
if (CurDecl->getDeclContext()->isTranslationUnit()) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f9418829186e..e749c24e7f70 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 a0fb1c397303..222b78e0d22f 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<XY>::specialization("str") == SPECIALIZATION_CONCEPT);
static_assert(S<int>::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 <int>
-struct S {
- template <Concept C>
- static constexpr int constrained_method();
-};
-
-template <>
-template <Concept C>
-constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
-
-template <>
-template <Concept C>
-constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
-
-static_assert(S<1>::constrained_method<XY>() == CONSTRAINED_METHOD_1);
-static_assert(S<2>::constrained_method<XY>() == CONSTRAINED_METHOD_2);
-
-
-template <class T1, class T2>
-concept ConceptT1T2 = true;
-
-template<typename T3>
-struct S12 {
- template<ConceptT1T2<T3> T4>
- static constexpr int constrained_method();
-};
-
-template<>
-template<ConceptT1T2<int> T5>
-constexpr int S12<int>::constrained_method() { return CONSTRAINED_METHOD_1; }
-
-template<>
-template<ConceptT1T2<double> T5>
-constexpr int S12<double>::constrained_method() { return CONSTRAINED_METHOD_2; }
-
-static_assert(S12<int>::constrained_method<XY>() == CONSTRAINED_METHOD_1);
-static_assert(S12<double>::constrained_method<XY>() == CONSTRAINED_METHOD_2);
-
-} // namespace constrained members
-
-namespace constrained_members_of_nested_types {
-
-template <int>
-struct S {
- struct Inner0 {
- struct Inner1 {
- template <Concept C>
- static constexpr int constrained_method();
- };
- };
-};
-
-template <>
-template <Concept C>
-constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
-
-template <>
-template <Concept C>
-constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
-
-static_assert(S<1>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1);
-static_assert(S<2>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2);
-
-
-template <class T1, class T2>
-concept ConceptT1T2 = true;
-
-template<typename T3>
-struct S12 {
- struct Inner0 {
- struct Inner1 {
- template<ConceptT1T2<T3> T4>
- static constexpr int constrained_method();
- };
- };
-};
-
-template<>
-template<ConceptT1T2<int> T5>
-constexpr int S12<int>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
-
-template<>
-template<ConceptT1T2<double> T5>
-constexpr int S12<double>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
-
-static_assert(S12<int>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_1);
-static_assert(S12<double>::Inner0::Inner1::constrained_method<XY>() == CONSTRAINED_METHOD_2);
-
-} // namespace constrained_members_of_nested_types
-
-namespace constrained_member_sfinae {
-
-template<int N> struct S {
- template<class T>
- static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
- return CONSTRAINED_METHOD_1;
- }
-
- template<class T>
- static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
-};
-
-template<>
-template<typename T>
-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<double>() == CONSTRAINED_METHOD_2);
-
-} // namespace constrained_member_sfinae
-
-namespace requires_expression_references_members {
-
-void accept1(int x);
-void accept2(XY xy);
-
-template <class T> struct S {
- T Field = T();
-
- constexpr int constrained_method()
- requires requires { accept1(Field); };
-
- constexpr int constrained_method()
- requires requires { accept2(Field); };
-};
-
-template <class T>
-constexpr int S<T>::constrained_method()
- requires requires { accept1(Field); } {
- return CONSTRAINED_METHOD_1;
-}
-
-template <class T>
-constexpr int S<T>::constrained_method()
- requires requires { accept2(Field); } {
- return CONSTRAINED_METHOD_2;
-}
-
-static_assert(S<int>().constrained_method() == CONSTRAINED_METHOD_1);
-static_assert(S<XY>().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 19638bba3072..d28c2b22bd04 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -816,12 +816,3 @@ static_assert(Parent<int>::TakesBinary<int, 0>::i == 0);
static_assert(Parent<int>::TakesBinary<int, 0ULL>::i == 0);
}
-namespace TemplateInsideNonTemplateClass {
-template<typename T, typename U> concept C = true;
-
-template<typename T> auto L = []<C<T> U>() {};
-
-struct Q {
- template<C<int> U> friend constexpr auto decltype(L<int>)::operator()() const;
-};
-} // namespace TemplateInsideNonTemplateClass
More information about the cfe-commits
mailing list