aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp93
1 files changed, 61 insertions, 32 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 2bf1511..dcf2876 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -9,6 +9,7 @@
//===----------------------------------------------------------------------===//
#include "TreeTransform.h"
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -1222,8 +1223,9 @@ static ExprResult formImmediatelyDeclaredConstraint(
if (auto *CD = dyn_cast<ConceptDecl>(NamedConcept)) {
ImmediatelyDeclaredConstraint = S.CheckConceptTemplateId(
SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo,
- /*FoundDecl=*/FoundDecl ? FoundDecl : NamedConcept, CD,
- &ConstraintArgs);
+ /*FoundDecl=*/FoundDecl ? FoundDecl : CD, CD, &ConstraintArgs,
+ /*DoCheckConstraintSatisfaction=*/
+ !S.inParameterMappingSubstitution());
}
// We have a template template parameter
else {
@@ -4850,13 +4852,11 @@ void Sema::diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
diagnoseMissingTemplateArguments(Name, Loc);
}
-ExprResult
-Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
- SourceLocation TemplateKWLoc,
- const DeclarationNameInfo &ConceptNameInfo,
- NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept,
- const TemplateArgumentListInfo *TemplateArgs) {
+ExprResult Sema::CheckConceptTemplateId(
+ const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+ const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl,
+ TemplateDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs,
+ bool DoCheckConstraintSatisfaction) {
assert(NamedConcept && "A concept template id without a template?");
if (NamedConcept->isInvalidDecl())
@@ -4873,33 +4873,48 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
DiagnoseUseOfDecl(NamedConcept, ConceptNameInfo.getLoc());
+ // There's a bug with CTAI.CanonicalConverted.
+ // If the template argument contains a DependentDecltypeType that includes a
+ // TypeAliasType, and the same written type had occurred previously in the
+ // source, then the DependentDecltypeType would be canonicalized to that
+ // previous type which would mess up the substitution.
+ // FIXME: Reland https://github.com/llvm/llvm-project/pull/101782 properly!
auto *CSD = ImplicitConceptSpecializationDecl::Create(
Context, NamedConcept->getDeclContext(), NamedConcept->getLocation(),
- CTAI.CanonicalConverted);
+ CTAI.SugaredConverted);
ConstraintSatisfaction Satisfaction;
bool AreArgsDependent =
TemplateSpecializationType::anyDependentTemplateArguments(
- *TemplateArgs, CTAI.CanonicalConverted);
- MultiLevelTemplateArgumentList MLTAL(NamedConcept, CTAI.CanonicalConverted,
+ *TemplateArgs, CTAI.SugaredConverted);
+ MultiLevelTemplateArgumentList MLTAL(NamedConcept, CTAI.SugaredConverted,
/*Final=*/false);
- LocalInstantiationScope Scope(*this);
-
- EnterExpressionEvaluationContext EECtx{
- *this, ExpressionEvaluationContext::Unevaluated, CSD};
-
- if (!AreArgsDependent &&
- CheckConstraintSatisfaction(
- NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()),
- MLTAL,
- SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
- TemplateArgs->getRAngleLoc()),
- Satisfaction))
- return ExprError();
auto *CL = ConceptReference::Create(
Context,
SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{},
TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs));
+
+ bool Error = false;
+ if (const auto *Concept = dyn_cast<ConceptDecl>(NamedConcept);
+ Concept && Concept->getConstraintExpr() && !AreArgsDependent &&
+ DoCheckConstraintSatisfaction) {
+
+ LocalInstantiationScope Scope(*this);
+
+ EnterExpressionEvaluationContext EECtx{
+ *this, ExpressionEvaluationContext::Unevaluated, CSD};
+
+ Error = CheckConstraintSatisfaction(
+ NamedConcept, AssociatedConstraint(Concept->getConstraintExpr()), MLTAL,
+ SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
+ TemplateArgs->getRAngleLoc()),
+ Satisfaction, CL);
+ Satisfaction.ContainsErrors = Error;
+ }
+
+ if (Error)
+ return ExprError();
+
return ConceptSpecializationExpr::Create(
Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction);
}
@@ -5217,10 +5232,11 @@ bool Sema::CheckTemplateTypeArgument(
}
default: {
// We allow instantiating a template with template argument packs when
- // building deduction guides.
+ // building deduction guides or mapping constraint template parameters.
if (Arg.getKind() == TemplateArgument::Pack &&
- CodeSynthesisContexts.back().Kind ==
- Sema::CodeSynthesisContext::BuildingDeductionGuides) {
+ (CodeSynthesisContexts.back().Kind ==
+ Sema::CodeSynthesisContext::BuildingDeductionGuides ||
+ inParameterMappingSubstitution())) {
SugaredConverted.push_back(Arg);
CanonicalConverted.push_back(Arg);
return false;
@@ -5813,6 +5829,20 @@ bool Sema::CheckTemplateArgumentList(
TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs,
bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI,
bool UpdateArgsWithConversions, bool *ConstraintsNotSatisfied) {
+ return CheckTemplateArgumentList(
+ Template, GetTemplateParameterList(Template), TemplateLoc, TemplateArgs,
+ DefaultArgs, PartialTemplateArgs, CTAI, UpdateArgsWithConversions,
+ ConstraintsNotSatisfied);
+}
+
+/// Check that the given template argument list is well-formed
+/// for specializing the given template.
+bool Sema::CheckTemplateArgumentList(
+ TemplateDecl *Template, TemplateParameterList *Params,
+ SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs,
+ const DefaultArguments &DefaultArgs, bool PartialTemplateArgs,
+ CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions,
+ bool *ConstraintsNotSatisfied) {
if (ConstraintsNotSatisfied)
*ConstraintsNotSatisfied = false;
@@ -5822,8 +5852,6 @@ bool Sema::CheckTemplateArgumentList(
// template.
TemplateArgumentListInfo NewArgs = TemplateArgs;
- TemplateParameterList *Params = GetTemplateParameterList(Template);
-
SourceLocation RAngleLoc = NewArgs.getRAngleLoc();
// C++23 [temp.arg.general]p1:
@@ -6163,11 +6191,12 @@ bool Sema::CheckTemplateArgumentList(
CXXThisScopeRAII Scope(*this, RD, ThisQuals, RD != nullptr);
MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
- Template, NewContext, /*Final=*/false, CTAI.CanonicalConverted,
+ Template, NewContext, /*Final=*/true, CTAI.SugaredConverted,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConceptInstantiation=*/true);
- if (EnsureTemplateArgumentListConstraints(
+ if (!isa<ConceptDecl>(Template) &&
+ EnsureTemplateArgumentListConstraints(
Template, MLTAL,
SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) {
if (ConstraintsNotSatisfied)