summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--[-rwxr-xr-x]clang/lib/Sema/SemaConcept.cpp360
-rw-r--r--[-rwxr-xr-x]clang/lib/Sema/SemaTemplate.cpp30
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp231
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp42
-rw-r--r--[-rwxr-xr-x]clang/lib/Sema/SemaTemplateInstantiateDecl.cpp5
5 files changed, 49 insertions, 619 deletions
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 63b8e06a7ae..f917d9c7e5a 100755..100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -17,7 +17,6 @@
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/Template.h"
#include "clang/AST/ExprCXX.h"
-#include "clang/AST/RecursiveASTVisitor.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
using namespace clang;
@@ -415,363 +414,4 @@ void Sema::DiagnoseUnsatisfiedConstraint(
diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
First = false;
}
-}
-
-namespace {
-struct AtomicConstraint {
- const Expr *ConstraintExpr;
- llvm::Optional<llvm::SmallVector<TemplateArgumentLoc, 3>> ParameterMapping;
-
- AtomicConstraint(Sema &S, const Expr *ConstraintExpr) :
- ConstraintExpr(ConstraintExpr) { };
-
- bool hasMatchingParameterMapping(ASTContext &C,
- const AtomicConstraint &Other) const {
- if (!ParameterMapping != !Other.ParameterMapping)
- return false;
- if (!ParameterMapping)
- return true;
- if (ParameterMapping->size() != Other.ParameterMapping->size())
- return false;
-
- for (unsigned I = 0, S = ParameterMapping->size(); I < S; ++I)
- if (!C.getCanonicalTemplateArgument((*ParameterMapping)[I].getArgument())
- .structurallyEquals(C.getCanonicalTemplateArgument(
- (*Other.ParameterMapping)[I].getArgument())))
- return false;
- return true;
- }
-
- bool subsumes(ASTContext &C, const AtomicConstraint &Other) const {
- // C++ [temp.constr.order] p2
- // - an atomic constraint A subsumes another atomic constraint B
- // if and only if the A and B are identical [...]
- //
- // C++ [temp.constr.atomic] p2
- // Two atomic constraints are identical if they are formed from the
- // same expression and the targets of the parameter mappings are
- // equivalent according to the rules for expressions [...]
-
- // We do not actually substitute the parameter mappings into the
- // constraint expressions, therefore the constraint expressions are
- // the originals, and comparing them will suffice.
- if (ConstraintExpr != Other.ConstraintExpr)
- return false;
-
- // Check that the parameter lists are identical
- return hasMatchingParameterMapping(C, Other);
- }
-};
-
-/// \brief A normalized constraint, as defined in C++ [temp.constr.normal], is
-/// either an atomic constraint, a conjunction of normalized constraints or a
-/// disjunction of normalized constraints.
-struct NormalizedConstraint {
- enum CompoundConstraintKind { CCK_Conjunction, CCK_Disjunction };
-
- using CompoundConstraint = llvm::PointerIntPair<
- std::pair<NormalizedConstraint, NormalizedConstraint> *, 1,
- CompoundConstraintKind>;
-
- llvm::PointerUnion<AtomicConstraint *, CompoundConstraint> Constraint;
-
- NormalizedConstraint(AtomicConstraint *C): Constraint{C} { };
- NormalizedConstraint(ASTContext &C, NormalizedConstraint LHS,
- NormalizedConstraint RHS, CompoundConstraintKind Kind)
- : Constraint{CompoundConstraint{
- new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{LHS,
- RHS},
- Kind}} { };
-
- CompoundConstraintKind getCompoundKind() const {
- assert(!isAtomic() && "getCompoundKind called on atomic constraint.");
- return Constraint.get<CompoundConstraint>().getInt();
- }
-
- bool isAtomic() const { return Constraint.is<AtomicConstraint *>(); }
-
- NormalizedConstraint &getLHS() const {
- assert(!isAtomic() && "getLHS called on atomic constraint.");
- return Constraint.get<CompoundConstraint>().getPointer()->first;
- }
-
- NormalizedConstraint &getRHS() const {
- assert(!isAtomic() && "getRHS called on atomic constraint.");
- return Constraint.get<CompoundConstraint>().getPointer()->second;
- }
-
- AtomicConstraint *getAtomicConstraint() const {
- assert(isAtomic() &&
- "getAtomicConstraint called on non-atomic constraint.");
- return Constraint.get<AtomicConstraint *>();
- }
-
- static llvm::Optional<NormalizedConstraint>
- fromConstraintExprs(Sema &S, NamedDecl *D, ArrayRef<const Expr *> E) {
- assert(E.size() != 0);
- auto First = fromConstraintExpr(S, D, E[0]);
- if (E.size() == 1)
- return First;
- auto Second = fromConstraintExpr(S, D, E[1]);
- if (!Second)
- return llvm::Optional<NormalizedConstraint>{};
- llvm::Optional<NormalizedConstraint> Conjunction;
- Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
- CCK_Conjunction);
- for (unsigned I = 2; I < E.size(); ++I) {
- auto Next = fromConstraintExpr(S, D, E[I]);
- if (!Next)
- return llvm::Optional<NormalizedConstraint>{};
- NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
- std::move(*Next), CCK_Conjunction);
- *Conjunction = std::move(NewConjunction);
- }
- return Conjunction;
- }
-
-private:
- static llvm::Optional<NormalizedConstraint> fromConstraintExpr(Sema &S,
- NamedDecl *D,
- const Expr *E);
-};
-
-static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
- ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
- const ASTTemplateArgumentListInfo *ArgsAsWritten) {
- if (!N.isAtomic()) {
- if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
- ArgsAsWritten))
- return true;
- return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
- ArgsAsWritten);
- }
- TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
-
- AtomicConstraint &Atomic = *N.getAtomicConstraint();
- TemplateArgumentListInfo SubstArgs;
- MultiLevelTemplateArgumentList MLTAL;
- MLTAL.addOuterTemplateArguments(TemplateArgs);
- if (!Atomic.ParameterMapping) {
- llvm::SmallBitVector OccurringIndices;
- S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
- /*Depth=*/0, OccurringIndices);
- Atomic.ParameterMapping.emplace();
- Atomic.ParameterMapping->reserve(OccurringIndices.size());
- for (unsigned I = 0, C = TemplateParams->size(); I != C; ++I)
- if (I < OccurringIndices.size() && OccurringIndices[I])
- Atomic.ParameterMapping->push_back(
- S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
- // Here we assume we do not support things like
- // template<typename A, typename B>
- // concept C = ...;
- //
- // template<typename... Ts> requires C<Ts...>
- // struct S { };
- // The above currently yields a diagnostic.
- // We still might have default arguments for concept parameters.
- ArgsAsWritten->NumTemplateArgs > I ?
- ArgsAsWritten->arguments()[I].getLocation() :
- SourceLocation()));
- }
- Sema::InstantiatingTemplate Inst(
- S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
- Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
- SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
- ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
- if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
- return true;
- std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
- N.getAtomicConstraint()->ParameterMapping->begin());
- return false;
-}
-
-llvm::Optional<NormalizedConstraint>
-NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
- assert(E != nullptr);
-
- // C++ [temp.constr.normal]p1.1
- // [...]
- // - The normal form of an expression (E) is the normal form of E.
- // [...]
- E = E->IgnoreParenImpCasts();
- if (auto *BO = dyn_cast<const BinaryOperator>(E)) {
- if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
- auto LHS = fromConstraintExpr(S, D, BO->getLHS());
- if (!LHS)
- return None;
- auto RHS = fromConstraintExpr(S, D, BO->getRHS());
- if (!RHS)
- return None;
-
- return NormalizedConstraint(
- S.Context, *LHS, *RHS,
- BO->getOpcode() == BO_LAnd ? CCK_Conjunction : CCK_Disjunction);
- }
- } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
- Optional<NormalizedConstraint> SubNF;
- {
- Sema::InstantiatingTemplate Inst(
- S, CSE->getExprLoc(),
- Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
- CSE->getSourceRange());
- // C++ [temp.constr.normal]p1.1
- // [...]
- // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
- // where C names a concept, is the normal form of the
- // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
- // respective template parameters in the parameter mappings in each atomic
- // constraint. If any such substitution results in an invalid type or
- // expression, the program is ill-formed; no diagnostic is required.
- // [...]
- SubNF = fromConstraintExpr(S, CSE->getNamedConcept(),
- CSE->getNamedConcept()->getConstraintExpr());
- if (!SubNF)
- return None;
- }
-
- if (substituteParameterMappings(
- S, *SubNF, CSE->getNamedConcept(),
- CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
- return None;
-
- return SubNF;
- }
- return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
-}
-
-} // namespace
-
-using NormalForm =
- llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
-
-static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
- if (Normalized.isAtomic())
- return {{Normalized.getAtomicConstraint()}};
-
- NormalForm LCNF = makeCNF(Normalized.getLHS());
- NormalForm RCNF = makeCNF(Normalized.getRHS());
- if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
- LCNF.reserve(LCNF.size() + RCNF.size());
- while (!RCNF.empty())
- LCNF.push_back(RCNF.pop_back_val());
- return LCNF;
- }
-
- // Disjunction
- NormalForm Res;
- Res.reserve(LCNF.size() * RCNF.size());
- for (auto &LDisjunction : LCNF)
- for (auto &RDisjunction : RCNF) {
- NormalForm::value_type Combined;
- Combined.reserve(LDisjunction.size() + RDisjunction.size());
- std::copy(LDisjunction.begin(), LDisjunction.end(),
- std::back_inserter(Combined));
- std::copy(RDisjunction.begin(), RDisjunction.end(),
- std::back_inserter(Combined));
- Res.emplace_back(Combined);
- }
- return Res;
-}
-
-static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
- if (Normalized.isAtomic())
- return {{Normalized.getAtomicConstraint()}};
-
- NormalForm LDNF = makeDNF(Normalized.getLHS());
- NormalForm RDNF = makeDNF(Normalized.getRHS());
- if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
- LDNF.reserve(LDNF.size() + RDNF.size());
- while (!RDNF.empty())
- LDNF.push_back(RDNF.pop_back_val());
- return LDNF;
- }
-
- // Conjunction
- NormalForm Res;
- Res.reserve(LDNF.size() * RDNF.size());
- for (auto &LConjunction : LDNF) {
- for (auto &RConjunction : RDNF) {
- NormalForm::value_type Combined;
- Combined.reserve(LConjunction.size() + RConjunction.size());
- std::copy(LConjunction.begin(), LConjunction.end(),
- std::back_inserter(Combined));
- std::copy(RConjunction.begin(), RConjunction.end(),
- std::back_inserter(Combined));
- Res.emplace_back(Combined);
- }
- }
- return Res;
-}
-
-static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
- NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes) {
- // C++ [temp.constr.order] p2
- // In order to determine if a constraint P subsumes a constraint Q, P is
- // transformed into disjunctive normal form, and Q is transformed into
- // conjunctive normal form. [...]
- auto PNormalized = NormalizedConstraint::fromConstraintExprs(S, DP, P);
- if (!PNormalized)
- return true;
- const NormalForm PDNF = makeDNF(*PNormalized);
-
- auto QNormalized = NormalizedConstraint::fromConstraintExprs(S, DQ, Q);
- if (!QNormalized)
- return true;
- const NormalForm QCNF = makeCNF(*QNormalized);
-
- // C++ [temp.constr.order] p2
- // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
- // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
- // the conjuctive normal form of Q, where [...]
- for (const auto &Pi : PDNF) {
- for (const auto &Qj : QCNF) {
- // C++ [temp.constr.order] p2
- // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
- // and only if there exists an atomic constraint Pia in Pi for which
- // there exists an atomic constraint, Qjb, in Qj such that Pia
- // subsumes Qjb.
- bool Found = false;
- for (const AtomicConstraint *Pia : Pi) {
- for (const AtomicConstraint *Qjb : Qj) {
- if (Pia->subsumes(S.Context, *Qjb)) {
- Found = true;
- break;
- }
- }
- if (Found)
- break;
- }
- if (!Found) {
- Subsumes = false;
- return false;
- }
- }
- }
- Subsumes = true;
- return false;
-}
-
-bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
- NamedDecl *D2, ArrayRef<const Expr *> AC2,
- bool &Result) {
- if (AC1.empty()) {
- Result = AC2.empty();
- return false;
- }
- if (AC2.empty()) {
- // TD1 has associated constraints and TD2 does not.
- Result = true;
- return false;
- }
-
- std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
- auto CacheEntry = SubsumptionCache.find(Key);
- if (CacheEntry != SubsumptionCache.end()) {
- Result = CacheEntry->second;
- return false;
- }
- if (subsumes(*this, D1, AC1, D2, AC2, Result))
- return true;
- SubsumptionCache.try_emplace(Key, Result);
- return false;
} \ No newline at end of file
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index ade8a5a6ac1..699895568b7 100755..100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1120,11 +1120,11 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
// Check that we have valid decl-specifiers specified.
auto CheckValidDeclSpecifiers = [this, &D] {
// C++ [temp.param]
- // p1
+ // p1
// template-parameter:
// ...
// parameter-declaration
- // p2
+ // p2
// ... A storage class shall not be specified in a template-parameter
// declaration.
// [dcl.typedef]p1:
@@ -3900,9 +3900,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
}
if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(),
- Converted) &&
- (!Context.getLangOpts().ConceptsTS ||
- !TemplateParams->hasAssociatedConstraints())) {
+ Converted)) {
// C++ [temp.class.spec]p9b3:
//
// -- The argument list of the specialization shall not be identical
@@ -3921,8 +3919,8 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
VarTemplateSpecializationDecl *PrevDecl = nullptr;
if (IsPartialSpecialization)
- PrevDecl = VarTemplate->findPartialSpecialization(Converted, TemplateParams,
- InsertPos);
+ // FIXME: Template parameter list matters too
+ PrevDecl = VarTemplate->findPartialSpecialization(Converted, InsertPos);
else
PrevDecl = VarTemplate->findSpecialization(Converted, InsertPos);
@@ -5275,16 +5273,12 @@ bool Sema::CheckTemplateArgumentList(
bool PackExpansionIntoNonPack =
NewArgs[ArgIdx].getArgument().isPackExpansion() &&
(!(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param));
- if (PackExpansionIntoNonPack && (isa<TypeAliasTemplateDecl>(Template) ||
- isa<ConceptDecl>(Template))) {
+ if (PackExpansionIntoNonPack && isa<TypeAliasTemplateDecl>(Template)) {
// Core issue 1430: we have a pack expansion as an argument to an
// alias template, and it's not part of a parameter pack. This
// can't be canonicalized, so reject it now.
- // As for concepts - we cannot normalize constraints where this
- // situation exists.
Diag(NewArgs[ArgIdx].getLocation(),
- diag::err_template_expansion_into_fixed_list)
- << (isa<ConceptDecl>(Template) ? 1 : 0)
+ diag::err_alias_template_expansion_into_fixed_list)
<< NewArgs[ArgIdx].getSourceRange();
Diag((*Param)->getLocation(), diag::note_template_param_here);
return true;
@@ -7118,7 +7112,6 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
bool Complain,
Sema::TemplateParameterListEqualKind Kind,
SourceLocation TemplateArgLoc) {
- // TODO: Concepts: Check constrained-parameter constraints here.
// Check the actual kind (type, non-type, template).
if (Old->getKind() != New->getKind()) {
if (Complain) {
@@ -7820,9 +7813,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
ClassTemplateSpecializationDecl *PrevDecl = nullptr;
if (isPartialSpecialization)
- PrevDecl = ClassTemplate->findPartialSpecialization(Converted,
- TemplateParams,
- InsertPos);
+ // FIXME: Template parameter list matters, too
+ PrevDecl = ClassTemplate->findPartialSpecialization(Converted, InsertPos);
else
PrevDecl = ClassTemplate->findSpecialization(Converted, InsertPos);
@@ -7846,9 +7838,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
Converted);
if (Context.hasSameType(CanonType,
- ClassTemplate->getInjectedClassNameSpecialization()) &&
- (!Context.getLangOpts().ConceptsTS ||
- !TemplateParams->hasAssociatedConstraints())) {
+ ClassTemplate->getInjectedClassNameSpecialization())) {
// C++ [temp.class.spec]p9b3:
//
// -- The argument list of the specialization shall not be identical
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index df4f6f647b2..327447746c3 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -24,7 +24,6 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/NestedNameSpecifier.h"
-#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
@@ -2502,30 +2501,6 @@ Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
llvm_unreachable("Invalid TemplateArgument Kind!");
}
-TemplateArgumentLoc
-Sema::getIdentityTemplateArgumentLoc(Decl *TemplateParm,
- SourceLocation Location) {
- if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParm))
- return getTrivialTemplateArgumentLoc(
- TemplateArgument(
- Context.getTemplateTypeParmType(TTP->getDepth(), TTP->getIndex(),
- TTP->isParameterPack(), TTP)),
- QualType(), Location.isValid() ? Location : TTP->getLocation());
- else if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParm))
- return getTrivialTemplateArgumentLoc(TemplateArgument(TemplateName(TTP)),
- QualType(),
- Location.isValid() ? Location :
- TTP->getLocation());
- auto *NTTP = cast<NonTypeTemplateParmDecl>(TemplateParm);
- CXXScopeSpec SS;
- DeclarationNameInfo Info(NTTP->getDeclName(),
- Location.isValid() ? Location : NTTP->getLocation());
- Expr *E = BuildDeclarationNameExpr(SS, Info, NTTP).get();
- return getTrivialTemplateArgumentLoc(TemplateArgument(E), NTTP->getType(),
- Location.isValid() ? Location :
- NTTP->getLocation());
-}
-
/// Convert the given deduced template argument and add it to the set of
/// fully-converted template arguments.
static bool
@@ -2616,6 +2591,23 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
return ConvertArg(Arg, 0);
}
+template<typename TemplateDeclT>
+static Sema::TemplateDeductionResult
+CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
+ ArrayRef<TemplateArgument> DeducedArgs,
+ TemplateDeductionInfo &Info) {
+ llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
+ Template->getAssociatedConstraints(AssociatedConstraints);
+ if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints,
+ DeducedArgs, Info.getLocation(),
+ Info.AssociatedConstraintsSatisfaction) ||
+ !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
+ Info.reset(TemplateArgumentList::CreateCopy(S.Context, DeducedArgs));
+ return Sema::TDK_ConstraintsNotSatisfied;
+ }
+ return Sema::TDK_Success;
+}
+
// FIXME: This should not be a template, but
// ClassTemplatePartialSpecializationDecl sadly does not derive from
// TemplateDecl.
@@ -2713,6 +2705,10 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
// If we get here, we successfully used the default template argument.
}
+ if (Sema::TemplateDeductionResult Result
+ = CheckDeducedArgumentConstraints(S, Template, Builder, Info))
+ return Result;
+
return Sema::TDK_Success;
}
@@ -2734,23 +2730,6 @@ struct IsPartialSpecialization<VarTemplatePartialSpecializationDecl> {
static constexpr bool value = true;
};
-template<typename TemplateDeclT>
-static Sema::TemplateDeductionResult
-CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
- ArrayRef<TemplateArgument> DeducedArgs,
- TemplateDeductionInfo& Info) {
- llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
- Template->getAssociatedConstraints(AssociatedConstraints);
- if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints,
- DeducedArgs, Info.getLocation(),
- Info.AssociatedConstraintsSatisfaction) ||
- !Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
- Info.reset(TemplateArgumentList::CreateCopy(S.Context, DeducedArgs));
- return Sema::TDK_ConstraintsNotSatisfied;
- }
- return Sema::TDK_Success;
-}
-
/// Complete template argument deduction for a partial specialization.
template <typename T>
static typename std::enable_if<IsPartialSpecialization<T>::value,
@@ -2832,9 +2811,6 @@ FinishTemplateArgumentDeduction(
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
- if (auto Result = CheckDeducedArgumentConstraints(S, Partial, Builder, Info))
- return Result;
-
return Sema::TDK_Success;
}
@@ -2877,10 +2853,6 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
if (Trap.hasErrorOccurred())
return Sema::TDK_SubstitutionFailure;
- if (auto Result = CheckDeducedArgumentConstraints(S, Template, Builder,
- Info))
- return Result;
-
return Sema::TDK_Success;
}
@@ -3392,11 +3364,6 @@ Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
PartialOverloading))
return Result;
- if (TemplateDeductionResult Result
- = CheckDeducedArgumentConstraints(*this, FunctionTemplate, Builder,
- Info))
- return Result;
-
// C++ [temp.deduct.call]p10: [DR1391]
// If deduction succeeds for all parameters that contain
// template-parameters that participate in template argument deduction,
@@ -4962,21 +4929,6 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
TemplatePartialOrderingContext TPOC,
unsigned NumCallArguments1,
unsigned NumCallArguments2) {
-
- auto JudgeByConstraints = [&] () -> FunctionTemplateDecl * {
- llvm::SmallVector<const Expr *, 3> AC1, AC2;
- FT1->getAssociatedConstraints(AC1);
- FT2->getAssociatedConstraints(AC2);
- bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (IsAtLeastAsConstrained(FT1, AC1, FT2, AC2, AtLeastAsConstrained1))
- return nullptr;
- if (IsAtLeastAsConstrained(FT2, AC2, FT1, AC1, AtLeastAsConstrained2))
- return nullptr;
- if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
- return nullptr;
- return AtLeastAsConstrained1 ? FT1 : FT2;
- };
-
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
NumCallArguments1);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
@@ -4986,7 +4938,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
return Better1 ? FT1 : FT2;
if (!Better1 && !Better2) // Neither is better than the other
- return JudgeByConstraints();
+ return nullptr;
// FIXME: This mimics what GCC implements, but doesn't match up with the
// proposed resolution for core issue 692. This area needs to be sorted out,
@@ -4996,7 +4948,7 @@ Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1,
if (Variadic1 != Variadic2)
return Variadic1? FT2 : FT1;
- return JudgeByConstraints();
+ return nullptr;
}
/// Determine if the two templates are equivalent.
@@ -5121,6 +5073,7 @@ template<typename TemplateLikeDecl>
static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,
TemplateLikeDecl *P2,
TemplateDeductionInfo &Info) {
+ // TODO: Concepts: Regard constraints
// C++ [temp.class.order]p1:
// For two class template partial specializations, the first is at least as
// specialized as the second if, given the following rewrite to two
@@ -5191,21 +5144,8 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info);
bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info);
- if (!Better1 && !Better2)
- return nullptr;
- if (Better1 && Better2) {
- llvm::SmallVector<const Expr *, 3> AC1, AC2;
- PS1->getAssociatedConstraints(AC1);
- PS2->getAssociatedConstraints(AC2);
- bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (IsAtLeastAsConstrained(PS1, AC1, PS2, AC2, AtLeastAsConstrained1))
- return nullptr;
- if (IsAtLeastAsConstrained(PS2, AC2, PS1, AC1, AtLeastAsConstrained2))
- return nullptr;
- if (AtLeastAsConstrained1 == AtLeastAsConstrained2)
- return nullptr;
- return AtLeastAsConstrained1 ? PS1 : PS2;
- }
+ if (Better1 == Better2)
+ return nullptr;
return Better1 ? PS1 : PS2;
}
@@ -5217,22 +5157,11 @@ bool Sema::isMoreSpecializedThanPrimary(
QualType PartialT = Spec->getInjectedSpecializationType();
if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, Info))
return false;
- if (!isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info))
- return true;
- Info.clearSFINAEDiagnostic();
- llvm::SmallVector<const Expr *, 3> PrimaryAC, SpecAC;
- Primary->getAssociatedConstraints(PrimaryAC);
- Spec->getAssociatedConstraints(SpecAC);
- bool AtLeastAsConstrainedPrimary, AtLeastAsConstrainedSpec;
- if (IsAtLeastAsConstrained(Spec, SpecAC, Primary, PrimaryAC,
- AtLeastAsConstrainedSpec))
- return false;
- if (!AtLeastAsConstrainedSpec)
- return false;
- if (IsAtLeastAsConstrained(Primary, PrimaryAC, Spec, SpecAC,
- AtLeastAsConstrainedPrimary))
+ if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) {
+ Info.clearSFINAEDiagnostic();
return false;
- return !AtLeastAsConstrainedPrimary;
+ }
+ return true;
}
VarTemplatePartialSpecializationDecl *
@@ -5255,22 +5184,8 @@ Sema::getMoreSpecializedPartialSpecialization(
bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info);
bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info);
- if (!Better1 && !Better2)
+ if (Better1 == Better2)
return nullptr;
- if (Better1 && Better2) {
- llvm::SmallVector<const Expr *, 3> AC1, AC2;
- PS1->getAssociatedConstraints(AC1);
- PS2->getAssociatedConstraints(AC2);
- bool AtLeastAsConstrained1, AtLeastAsConstrained2;
- if (IsAtLeastAsConstrained(PS1, AC1, PS2, AC2, AtLeastAsConstrained1))
- return nullptr;
- if (IsAtLeastAsConstrained(PS2, AC2, PS1, AC1, AtLeastAsConstrained2))
- return nullptr;
- if (AtLeastAsConstrained1 == AtLeastAsConstrained2) {
- return nullptr;
- }
- return AtLeastAsConstrained1 ? PS1 : PS2;
- }
return Better1 ? PS1 : PS2;
}
@@ -5290,25 +5205,13 @@ bool Sema::isMoreSpecializedThanPrimary(
CanonTemplate, PrimaryArgs);
QualType PartialT = Context.getTemplateSpecializationType(
CanonTemplate, Spec->getTemplateArgs().asArray());
-
if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, Info))
return false;
- if (!isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info))
- return true;
- Info.clearSFINAEDiagnostic();
- llvm::SmallVector<const Expr *, 3> PrimaryAC, SpecAC;
- Primary->getAssociatedConstraints(PrimaryAC);
- Spec->getAssociatedConstraints(SpecAC);
- bool AtLeastAsConstrainedPrimary, AtLeastAsConstrainedSpec;
- if (IsAtLeastAsConstrained(Spec, SpecAC, Primary, PrimaryAC,
- AtLeastAsConstrainedSpec))
- return false;
- if (!AtLeastAsConstrainedSpec)
+ if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) {
+ Info.clearSFINAEDiagnostic();
return false;
- if (IsAtLeastAsConstrained(Primary, PrimaryAC, Spec, SpecAC,
- AtLeastAsConstrainedPrimary))
- return false;
- return !AtLeastAsConstrainedPrimary;
+ }
+ return true;
}
bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
@@ -5374,49 +5277,6 @@ bool Sema::isTemplateTemplateParameterAtLeastAsSpecializedAs(
return isAtLeastAsSpecializedAs(*this, PType, AType, AArg, Info);
}
-struct OccurringTemplateParameterFinder :
- RecursiveASTVisitor<OccurringTemplateParameterFinder> {
- llvm::SmallBitVector &OccurringIndices;
-
- OccurringTemplateParameterFinder(llvm::SmallBitVector &OccurringIndices)
- : OccurringIndices(OccurringIndices) { }
-
- bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
- assert(T->getDepth() == 0 && "This assumes that we allow concepts at "
- "namespace scope only");
- noteParameter(T->getIndex());
- return true;
- }
-
- bool TraverseTemplateName(TemplateName Template) {
- if (auto *TTP =
- dyn_cast<TemplateTemplateParmDecl>(Template.getAsTemplateDecl())) {
- assert(TTP->getDepth() == 0 && "This assumes that we allow concepts at "
- "namespace scope only");
- noteParameter(TTP->getIndex());
- }
- RecursiveASTVisitor<OccurringTemplateParameterFinder>::
- TraverseTemplateName(Template);
- return true;
- }
-
- bool VisitDeclRefExpr(DeclRefExpr *E) {
- if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
- assert(NTTP->getDepth() == 0 && "This assumes that we allow concepts at "
- "namespace scope only");
- noteParameter(NTTP->getIndex());
- }
- return true;
- }
-
-protected:
- void noteParameter(unsigned Index) {
- if (OccurringIndices.size() >= Index)
- OccurringIndices.resize(Index + 1, false);
- OccurringIndices.set(Index);
- }
-};
-
/// Mark the template parameters that are used by the given
/// expression.
static void
@@ -5425,11 +5285,6 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
bool OnlyDeduced,
unsigned Depth,
llvm::SmallBitVector &Used) {
- if (!OnlyDeduced) {
- OccurringTemplateParameterFinder(Used).TraverseStmt(const_cast<Expr *>(E));
- return;
- }
-
// We can deduce from a pack expansion.
if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
E = Expansion->getPattern();
@@ -5448,6 +5303,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
break;
}
+ // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to
+ // find other occurrences of template parameters.
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
if (!DRE)
return;
@@ -5827,20 +5684,6 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
}
}
-/// Mark which template parameters are used in a given expression.
-///
-/// \param E the expression from which template parameters will be deduced.
-///
-/// \param Used a bit vector whose elements will be set to \c true
-/// to indicate when the corresponding template parameter will be
-/// deduced.
-void
-Sema::MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
- unsigned Depth,
- llvm::SmallBitVector &Used) {
- ::MarkUsedTemplateParameters(Context, E, OnlyDeduced, Depth, Used);
-}
-
/// Mark which template parameters can be deduced from a given
/// template argument list.
///
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 770c07d41b1..6db8eb3e5ed 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -207,8 +207,6 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case DefiningSynthesizedFunction:
case ExceptionSpecEvaluation:
case ConstraintSubstitution:
- case ParameterMappingSubstitution:
- case ConstraintNormalization:
case RewritingOperatorAsSpaceship:
return false;
@@ -382,22 +380,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
PointOfInstantiation, InstantiationRange, Template, nullptr,
{}, &DeductionInfo) {}
-Sema::InstantiatingTemplate::InstantiatingTemplate(
- Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintNormalization, NamedDecl *Template,
- SourceRange InstantiationRange)
- : InstantiatingTemplate(
- SemaRef, CodeSynthesisContext::ConstraintNormalization,
- PointOfInstantiation, InstantiationRange, Template) {}
-
-Sema::InstantiatingTemplate::InstantiatingTemplate(
- Sema &SemaRef, SourceLocation PointOfInstantiation,
- ParameterMappingSubstitution, NamedDecl *Template,
- SourceRange InstantiationRange)
- : InstantiatingTemplate(
- SemaRef, CodeSynthesisContext::ParameterMappingSubstitution,
- PointOfInstantiation, InstantiationRange, Template) {}
-
void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
InNonInstantiationSFINAEContext = false;
@@ -751,17 +733,6 @@ void Sema::PrintInstantiationStack() {
diag::note_constraint_substitution_here)
<< Active->InstantiationRange;
break;
- case CodeSynthesisContext::ConstraintNormalization:
- Diags.Report(Active->PointOfInstantiation,
- diag::note_constraint_normalization_here)
- << cast<NamedDecl>(Active->Entity)->getName()
- << Active->InstantiationRange;
- break;
- case CodeSynthesisContext::ParameterMappingSubstitution:
- Diags.Report(Active->PointOfInstantiation,
- diag::note_parameter_mapping_substitution_here)
- << Active->InstantiationRange;
- break;
}
}
}
@@ -786,8 +757,6 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
case CodeSynthesisContext::ExceptionSpecInstantiation:
case CodeSynthesisContext::ConstraintsCheck:
- case CodeSynthesisContext::ParameterMappingSubstitution:
- case CodeSynthesisContext::ConstraintNormalization:
// This is a template instantiation, so there is no SFINAE.
return None;
@@ -2957,17 +2926,6 @@ Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
return Instantiator.TransformStmt(S);
}
-bool Sema::SubstTemplateArguments(
- ArrayRef<TemplateArgumentLoc> Args,
- const MultiLevelTemplateArgumentList &TemplateArgs,
- TemplateArgumentListInfo &Out) {
- TemplateInstantiator Instantiator(*this, TemplateArgs,
- SourceLocation(),
- DeclarationName());
- return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(),
- Out);
-}
-
ExprResult
Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!E)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a8fc77fff7d..0bff0747df3 100755..100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3706,8 +3706,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// in the member template's set of class template partial specializations.
void *InsertPos = nullptr;
ClassTemplateSpecializationDecl *PrevDecl
- = ClassTemplate->findPartialSpecialization(Converted, InstParams,
- InsertPos);
+ = ClassTemplate->findPartialSpecialization(Converted, InsertPos);
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
@@ -3831,7 +3830,7 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
// in the member template's set of variable template partial specializations.
void *InsertPos = nullptr;
VarTemplateSpecializationDecl *PrevDecl =
- VarTemplate->findPartialSpecialization(Converted, InstParams, InsertPos);
+ VarTemplate->findPartialSpecialization(Converted, InsertPos);
// Build the canonical type that describes the converted template
// arguments of the variable template partial specialization.
OpenPOWER on IntegriCloud