|
35 | 35 | #include "clang/Sema/Template.h" |
36 | 36 | #include "clang/Sema/TemplateDeduction.h" |
37 | 37 | #include "clang/Sema/TemplateInstCallback.h" |
| 38 | +#include "llvm/ADT/SmallVectorExtras.h" |
38 | 39 | #include "llvm/ADT/StringExtras.h" |
39 | 40 | #include "llvm/Support/ErrorHandling.h" |
40 | 41 | #include "llvm/Support/SaveAndRestore.h" |
@@ -4487,6 +4488,119 @@ ExprResult Sema::SubstConstraintExprWithoutSatisfaction( |
4487 | 4488 | return Instantiator.TransformExpr(E); |
4488 | 4489 | } |
4489 | 4490 |
|
| 4491 | +ExprResult Sema::SubstConceptTemplateArguments( |
| 4492 | + const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr, |
| 4493 | + const MultiLevelTemplateArgumentList &MLTAL) { |
| 4494 | + TemplateInstantiator Instantiator(*this, MLTAL, SourceLocation(), |
| 4495 | + DeclarationName()); |
| 4496 | + const ASTTemplateArgumentListInfo *ArgsAsWritten = |
| 4497 | + CSE->getTemplateArgsAsWritten(); |
| 4498 | + TemplateArgumentListInfo SubstArgs(ArgsAsWritten->getLAngleLoc(), |
| 4499 | + ArgsAsWritten->getRAngleLoc()); |
| 4500 | + |
| 4501 | + Sema::InstantiatingTemplate Inst( |
| 4502 | + *this, ArgsAsWritten->arguments().front().getSourceRange().getBegin(), |
| 4503 | + Sema::InstantiatingTemplate::ConstraintNormalization{}, |
| 4504 | + CSE->getNamedConcept(), |
| 4505 | + ArgsAsWritten->arguments().front().getSourceRange()); |
| 4506 | + |
| 4507 | + if (Inst.isInvalid()) |
| 4508 | + return ExprError(); |
| 4509 | + |
| 4510 | + if (Instantiator.TransformConceptTemplateArguments( |
| 4511 | + ArgsAsWritten->getTemplateArgs(), |
| 4512 | + ArgsAsWritten->getTemplateArgs() + |
| 4513 | + ArgsAsWritten->getNumTemplateArgs(), |
| 4514 | + SubstArgs)) |
| 4515 | + return true; |
| 4516 | + |
| 4517 | + llvm::SmallVector<TemplateArgument, 4> NewArgList = llvm::map_to_vector( |
| 4518 | + SubstArgs.arguments(), |
| 4519 | + [](const TemplateArgumentLoc &Loc) { return Loc.getArgument(); }); |
| 4520 | + |
| 4521 | + MultiLevelTemplateArgumentList MLTALForConstraint = |
| 4522 | + getTemplateInstantiationArgs( |
| 4523 | + CSE->getNamedConcept(), |
| 4524 | + CSE->getNamedConcept()->getLexicalDeclContext(), |
| 4525 | + /*Final=*/false, |
| 4526 | + /*Innermost=*/NewArgList, |
| 4527 | + /*RelativeToPrimary=*/true, |
| 4528 | + /*Pattern=*/nullptr, |
| 4529 | + /*ForConstraintInstantiation=*/true); |
| 4530 | + |
| 4531 | + // Rebuild a constraint, only substituting non-dependent concept names |
| 4532 | + // and nothing else. |
| 4533 | + // Given C<SomeType, SomeValue, SomeConceptName, SomeDependentConceptName>. |
| 4534 | + // only SomeConceptName is substituted, in the constraint expression of C. |
| 4535 | + struct ConstraintExprTransformer : TreeTransform<ConstraintExprTransformer> { |
| 4536 | + using Base = TreeTransform<ConstraintExprTransformer>; |
| 4537 | + MultiLevelTemplateArgumentList &MLTAL; |
| 4538 | + |
| 4539 | + ConstraintExprTransformer(Sema &SemaRef, |
| 4540 | + MultiLevelTemplateArgumentList &MLTAL) |
| 4541 | + : TreeTransform(SemaRef), MLTAL(MLTAL) {} |
| 4542 | + |
| 4543 | + ExprResult TransformExpr(Expr *E) { |
| 4544 | + if (!E) |
| 4545 | + return E; |
| 4546 | + switch (E->getStmtClass()) { |
| 4547 | + case Stmt::BinaryOperatorClass: |
| 4548 | + case Stmt::ConceptSpecializationExprClass: |
| 4549 | + case Stmt::ParenExprClass: |
| 4550 | + case Stmt::UnresolvedLookupExprClass: |
| 4551 | + return Base::TransformExpr(E); |
| 4552 | + default: |
| 4553 | + break; |
| 4554 | + } |
| 4555 | + return E; |
| 4556 | + } |
| 4557 | + |
| 4558 | + // Rebuild both branches of a conjunction / disjunction |
| 4559 | + // even if there is a substitution failure in one of |
| 4560 | + // the branch. |
| 4561 | + ExprResult TransformBinaryOperator(BinaryOperator *E) { |
| 4562 | + if (!(E->getOpcode() == BinaryOperatorKind::BO_LAnd || |
| 4563 | + E->getOpcode() == BinaryOperatorKind::BO_LOr)) |
| 4564 | + return E; |
| 4565 | + |
| 4566 | + ExprResult LHS = TransformExpr(E->getLHS()); |
| 4567 | + ExprResult RHS = TransformExpr(E->getRHS()); |
| 4568 | + |
| 4569 | + if (LHS.get() == E->getLHS() && RHS.get() == E->getRHS()) |
| 4570 | + return E; |
| 4571 | + |
| 4572 | + return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(), |
| 4573 | + E->getOpcode(), SemaRef.Context.BoolTy, |
| 4574 | + VK_PRValue, OK_Ordinary, |
| 4575 | + E->getOperatorLoc(), FPOptionsOverride{}); |
| 4576 | + } |
| 4577 | + |
| 4578 | + bool TransformTemplateArgument(const TemplateArgumentLoc &Input, |
| 4579 | + TemplateArgumentLoc &Output, |
| 4580 | + bool Uneval = false) { |
| 4581 | + if (Input.getArgument().isConceptOrConceptTemplateParameter()) |
| 4582 | + return Base::TransformTemplateArgument(Input, Output, Uneval); |
| 4583 | + |
| 4584 | + Output = Input; |
| 4585 | + return false; |
| 4586 | + } |
| 4587 | + |
| 4588 | + ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E, |
| 4589 | + bool IsAddressOfOperand = false) { |
| 4590 | + if (E->isConceptReference()) { |
| 4591 | + ExprResult Res = SemaRef.SubstExpr(E, MLTAL); |
| 4592 | + return Res; |
| 4593 | + } |
| 4594 | + return E; |
| 4595 | + } |
| 4596 | + }; |
| 4597 | + |
| 4598 | + ConstraintExprTransformer Transformer(*this, MLTALForConstraint); |
| 4599 | + ExprResult Res = |
| 4600 | + Transformer.TransformExpr(const_cast<Expr *>(ConstraintExpr)); |
| 4601 | + return Res; |
| 4602 | +} |
| 4603 | + |
4490 | 4604 | ExprResult Sema::SubstInitializer(Expr *Init, |
4491 | 4605 | const MultiLevelTemplateArgumentList &TemplateArgs, |
4492 | 4606 | bool CXXDirectInit) { |
|
0 commit comments