[clang] [Clang] Defer the instantiation of explicit-specifier until constraint checking completes (PR #70548)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 30 09:55:01 PDT 2023
================
@@ -3553,6 +3553,56 @@ static unsigned getPackIndexForParam(Sema &S,
llvm_unreachable("parameter index would not be produced from template");
}
+// if `Specialization` is a `CXXConstructorDecl` or `CXXConversionDecl`
+// we try to instantiate and update its explicit specifier after constraint
+// checking.
+static Sema::TemplateDeductionResult
+tryInstantiateExplicitSpecifier(Sema &S, FunctionDecl *Specialization,
+ const MultiLevelTemplateArgumentList &SubstArgs,
+ TemplateDeductionInfo &Info,
+ FunctionTemplateDecl *FunctionTemplate,
+ ArrayRef<TemplateArgument> DeducedArgs) {
+
+ const auto TryInstantiateExplicitSpecifierForSingleDecl =
+ [&](auto *ExplicitDecl) {
+ ExplicitSpecifier ExplicitSpecifier =
+ ExplicitDecl->getExplicitSpecifier();
+ Expr *const Expr = ExplicitSpecifier.getExpr();
+ if (!Expr) {
+ return Sema::TDK_Success;
+ }
+ if (!Expr->isValueDependent()) {
+ return Sema::TDK_Success;
+ }
+ // TemplateDeclInstantiator::InitFunctionInstantiation set the
+ // ActiveInstType to TemplateInstantiation, but we need
+ // to enable SFINAE when instantiating explicit specifier.
+ Sema::InstantiatingTemplate Inst(
+ S, Info.getLocation(), FunctionTemplate, DeducedArgs,
+ Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution,
+ Info);
+ const auto Instantiated =
+ S.instantiateExplicitSpecifier(SubstArgs, ExplicitSpecifier);
+ if (Instantiated.isInvalid()) {
+ ExplicitDecl->setInvalidDecl(true);
+ return clang::Sema::TDK_SubstitutionFailure;
+ }
+ ExplicitDecl->setExplicitSpecifier(Instantiated);
+ return clang::Sema::TDK_Success;
+ };
+ Sema::TemplateDeductionResult DeductionResult = clang::Sema::TDK_Success;
+ if (CXXConstructorDecl *ConstructorDecl =
+ dyn_cast_or_null<CXXConstructorDecl>(Specialization)) {
+ DeductionResult =
+ TryInstantiateExplicitSpecifierForSingleDecl(ConstructorDecl);
+ } else if (CXXConversionDecl *ConversionDecl =
+ dyn_cast_or_null<CXXConversionDecl>(Specialization)) {
+ DeductionResult =
+ TryInstantiateExplicitSpecifierForSingleDecl(ConversionDecl);
+ }
+ return DeductionResult;
----------------
LYP951018 wrote:
I've refactored the code here. If `Specialization` is not either constructor or conversion function, `cast` will `assert`.
https://github.com/llvm/llvm-project/pull/70548
More information about the cfe-commits
mailing list