aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index bec2820..ca7e3b2 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -35,6 +35,7 @@
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
+#include "llvm/ADT/SmallVectorExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
@@ -4487,6 +4488,119 @@ ExprResult Sema::SubstConstraintExprWithoutSatisfaction(
return Instantiator.TransformExpr(E);
}
+ExprResult Sema::SubstConceptTemplateArguments(
+ const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr,
+ const MultiLevelTemplateArgumentList &MLTAL) {
+ TemplateInstantiator Instantiator(*this, MLTAL, SourceLocation(),
+ DeclarationName());
+ const ASTTemplateArgumentListInfo *ArgsAsWritten =
+ CSE->getTemplateArgsAsWritten();
+ TemplateArgumentListInfo SubstArgs(ArgsAsWritten->getLAngleLoc(),
+ ArgsAsWritten->getRAngleLoc());
+
+ Sema::InstantiatingTemplate Inst(
+ *this, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
+ Sema::InstantiatingTemplate::ConstraintNormalization{},
+ CSE->getNamedConcept(),
+ ArgsAsWritten->arguments().front().getSourceRange());
+
+ if (Inst.isInvalid())
+ return ExprError();
+
+ if (Instantiator.TransformConceptTemplateArguments(
+ ArgsAsWritten->getTemplateArgs(),
+ ArgsAsWritten->getTemplateArgs() +
+ ArgsAsWritten->getNumTemplateArgs(),
+ SubstArgs))
+ return true;
+
+ llvm::SmallVector<TemplateArgument, 4> NewArgList = llvm::map_to_vector(
+ SubstArgs.arguments(),
+ [](const TemplateArgumentLoc &Loc) { return Loc.getArgument(); });
+
+ MultiLevelTemplateArgumentList MLTALForConstraint =
+ getTemplateInstantiationArgs(
+ CSE->getNamedConcept(),
+ CSE->getNamedConcept()->getLexicalDeclContext(),
+ /*Final=*/false,
+ /*Innermost=*/NewArgList,
+ /*RelativeToPrimary=*/true,
+ /*Pattern=*/nullptr,
+ /*ForConstraintInstantiation=*/true);
+
+ // Rebuild a constraint, only substituting non-dependent concept names
+ // and nothing else.
+ // Given C<SomeType, SomeValue, SomeConceptName, SomeDependentConceptName>.
+ // only SomeConceptName is substituted, in the constraint expression of C.
+ struct ConstraintExprTransformer : TreeTransform<ConstraintExprTransformer> {
+ using Base = TreeTransform<ConstraintExprTransformer>;
+ MultiLevelTemplateArgumentList &MLTAL;
+
+ ConstraintExprTransformer(Sema &SemaRef,
+ MultiLevelTemplateArgumentList &MLTAL)
+ : TreeTransform(SemaRef), MLTAL(MLTAL) {}
+
+ ExprResult TransformExpr(Expr *E) {
+ if (!E)
+ return E;
+ switch (E->getStmtClass()) {
+ case Stmt::BinaryOperatorClass:
+ case Stmt::ConceptSpecializationExprClass:
+ case Stmt::ParenExprClass:
+ case Stmt::UnresolvedLookupExprClass:
+ return Base::TransformExpr(E);
+ default:
+ break;
+ }
+ return E;
+ }
+
+ // Rebuild both branches of a conjunction / disjunction
+ // even if there is a substitution failure in one of
+ // the branch.
+ ExprResult TransformBinaryOperator(BinaryOperator *E) {
+ if (!(E->getOpcode() == BinaryOperatorKind::BO_LAnd ||
+ E->getOpcode() == BinaryOperatorKind::BO_LOr))
+ return E;
+
+ ExprResult LHS = TransformExpr(E->getLHS());
+ ExprResult RHS = TransformExpr(E->getRHS());
+
+ if (LHS.get() == E->getLHS() && RHS.get() == E->getRHS())
+ return E;
+
+ return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
+ E->getOpcode(), SemaRef.Context.BoolTy,
+ VK_PRValue, OK_Ordinary,
+ E->getOperatorLoc(), FPOptionsOverride{});
+ }
+
+ bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+ TemplateArgumentLoc &Output,
+ bool Uneval = false) {
+ if (Input.getArgument().isConceptOrConceptTemplateParameter())
+ return Base::TransformTemplateArgument(Input, Output, Uneval);
+
+ Output = Input;
+ return false;
+ }
+
+ ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E,
+ bool IsAddressOfOperand = false) {
+ if (E->isConceptReference()) {
+ ExprResult Res = SemaRef.SubstExpr(E, MLTAL);
+ return Res;
+ }
+ return E;
+ }
+ };
+
+ ConstraintExprTransformer Transformer(*this, MLTALForConstraint);
+ ExprResult Res =
+ Transformer.TransformExpr(const_cast<Expr *>(ConstraintExpr));
+ return Res;
+}
+
ExprResult Sema::SubstInitializer(Expr *Init,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool CXXDirectInit) {