[clang] Bugfix for chosing the correct deduction guide (PR #66487)

via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 15 03:28:33 PDT 2023


https://github.com/HoBoIs created https://github.com/llvm/llvm-project/pull/66487

If there is 2 guides one of them generated from a non-templated constructor and one of them from a templated constructor the standard gives priority to the first. Clang detected ambiguity before, now the correct guide is chosen.

Example for the bug:
https://godbolt.org/z/ee3e9qG78

Also a minor fix for issue #64020

I'm a new developer, can someone with more experience in clang check if the change in file "clang/lib/Sema/SemaTemplateInstantiateDecl.cpp" can never cause a use after free.

>From 5abc9393bf68d14b8cb9cc5cc86a854e3a2aeae5 Mon Sep 17 00:00:00 2001
From: hobois <horvath.botond.istvan at gmial.com>
Date: Fri, 15 Sep 2023 09:28:21 +0200
Subject: [PATCH] Bugfix for chosing the correct deduction guide

If there is 2 guides one of them generated from a non-templated constructor and one of them from a templated constructor the standard gives priority to the first. Clang detected ambiguity before, now the correct guide is chosen.

Also a minor fix for issue #64020
---
 clang/lib/Sema/SemaOverload.cpp                | 14 +++++++++++++-
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp |  2 +-
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 45a9e5dc98c032d..ec902fcad817e76 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -10153,6 +10153,18 @@ bool clang::isBetterOverloadCandidate(
       //  -- F1 is the copy deduction candidate(16.3.1.8) and F2 is not
       if (Guide1->getDeductionCandidateKind() == DeductionCandidate::Copy)
         return true;
+      if (Guide2->getDeductionCandidateKind() == DeductionCandidate::Copy)
+        return false;
+
+      //  --F1 is generated from a non-template constructor and F2 is generated from a constructor template
+      const auto* Constructor1 = Guide1->getCorrespondingConstructor();
+      const auto* Constructor2 = Guide2->getCorrespondingConstructor();
+      if (Constructor1 && Constructor2){
+        bool isC1Templated = Constructor1->getTemplatedKind() != FunctionDecl::TemplatedKind::TK_NonTemplate;
+        bool isC2Templated = Constructor2->getTemplatedKind() != FunctionDecl::TemplatedKind::TK_NonTemplate;
+        if (isC1Templated != isC2Templated)
+          return isC2Templated;
+      }
     }
   }
 
@@ -10196,7 +10208,7 @@ bool clang::isBetterOverloadCandidate(
     if (AS1 != AS2) {
       if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
         return true;
-      if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+      if (Qualifiers::isAddressSpaceSupersetOf(AS1, AS2))
         return false;
     }
   }
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 9e5f85b0f9166bd..b9c4a9db842b9ee 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2129,7 +2129,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
     Function = CXXDeductionGuideDecl::Create(
         SemaRef.Context, DC, D->getInnerLocStart(),
         InstantiatedExplicitSpecifier, NameInfo, T, TInfo,
-        D->getSourceRange().getEnd(), /*Ctor=*/nullptr,
+        D->getSourceRange().getEnd(), DGuide->getCorrespondingConstructor(),
         DGuide->getDeductionCandidateKind());
     Function->setAccess(D->getAccess());
   } else {



More information about the cfe-commits mailing list