[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