[clang] [CUDA][HIP] Fix CTAD for host/device constructors (PR #168711)

Corentin Jabot via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 27 04:29:37 PST 2025


================
@@ -218,9 +218,31 @@ buildDeductionGuide(Sema &SemaRef, TemplateDecl *OriginalTemplate,
       TInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams();
 
   // Build the implicit deduction guide template.
+  QualType GuideType = TInfo->getType();
+
+  // In CUDA/HIP mode, avoid creating duplicate implicit deduction guides with
+  // identical function types. This can happen when there are separate
+  // __host__ and __device__ constructors with the same signature; each would
+  // otherwise synthesize its own implicit deduction guide, leading to
+  // ambiguous CTAD purely due to target attributes. For such cases we keep the
+  // first guide we created and skip building another one.
+  if (IsImplicit && Ctor && SemaRef.getLangOpts().CUDA)
+    for (NamedDecl *Existing : DC->lookup(DeductionGuideName)) {
+      auto *ExistingFT = dyn_cast<FunctionTemplateDecl>(Existing);
+      auto *ExistingGuide =
+          ExistingFT
+              ? dyn_cast<CXXDeductionGuideDecl>(ExistingFT->getTemplatedDecl())
+              : dyn_cast<CXXDeductionGuideDecl>(Existing);
+      if (!ExistingGuide)
+        continue;
+
+      if (SemaRef.Context.hasSameType(ExistingGuide->getType(), GuideType))
+        return Existing;
+    }
----------------
cor3ntin wrote:

I don't think this is sufficient, 

Consider


```cpp
template <typename T>
struct S {
  S();
  __device__ S() requires true;
};
```

I think you want to check that `IsOverload(Ctr, ExistingGuide, /*UseMemberUsingDeclRules*/false, /*ConsiderCudaAttrs=*/true)` is false and `IsOverload(Ctr, ExistingGuide, /*UseMemberUsingDeclRules*/false, /*ConsiderCudaAttrs=*/false)` is true, or something along these line.

https://github.com/llvm/llvm-project/pull/168711


More information about the cfe-commits mailing list