[clang] 32aa7d8 - [clang] Fix CTAD not work for C++ explicit type conversion (functional annotation). (#75779)

via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 19 05:35:41 PST 2023


Author: Haojian Wu
Date: 2023-12-19T14:35:37+01:00
New Revision: 32aa7d823c8ae7183e65da2f29ed08a84d6a1b6b

URL: https://github.com/llvm/llvm-project/commit/32aa7d823c8ae7183e65da2f29ed08a84d6a1b6b
DIFF: https://github.com/llvm/llvm-project/commit/32aa7d823c8ae7183e65da2f29ed08a84d6a1b6b.diff

LOG: [clang] Fix CTAD not work for C++ explicit type conversion (functional annotation). (#75779)

This fixes https://github.com/llvm/llvm-project/issues/64347.

The CTAD for an aggregate class is missing to handle the explicit type
conversion case, e.g. `TemplateFooClass(1, 2);`. Per C++ expr.type.conv
p1, the deduced type is the return type of the deduction guide selected
by the CTAD for the reminder.

In the deduction implementation
`DeduceTemplateSpecializationFromInitializer`, the parenthesized
express-list case relies on the `ParenListExpr` parameter (default is
nullptr), the AST `ParenListExpr` node is not built for all variant
initializer cases (`BuildCXXTypeConstructorExpr`, `BuildCXXNew` etc),
thus the deduction doesn't perform for these cases. This patch fixes it
by removing the `ParenListExpr` and using the `Inits` instead (which
also simplifies the interface and implementation).

Added: 
    clang/test/SemaCXX/ctad.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaInit.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index edb97347f07716..39b9176865fc04 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -686,6 +686,9 @@ Bug Fixes in This Version
 - Fix an issue where clang doesn't respect detault template arguments that
   are added in a later redeclaration for CTAD.
   Fixes (#69987 <https://github.com/llvm/llvm-project/issues/69987>`_)
+- Fix an issue where CTAD fails for explicit type conversion.
+  Fixes (#64347 <https://github.com/llvm/llvm-project/issues/64347>`_)
+
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9887cc4ba4658d..5e3b57ea33220b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9354,8 +9354,7 @@ class Sema final {
 
   QualType DeduceTemplateSpecializationFromInitializer(
       TypeSourceInfo *TInfo, const InitializedEntity &Entity,
-      const InitializationKind &Kind, MultiExprArg Init,
-      ParenListExpr *PL = nullptr);
+      const InitializationKind &Kind, MultiExprArg Init);
 
   QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
                                         QualType Type, TypeSourceInfo *TSI,

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d1a26fe1218432..ffbe317d559995 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12954,7 +12954,7 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl,
     // FIXME: Initialization should not be taking a mutable list of inits.
     SmallVector<Expr*, 8> InitsCopy(DeduceInits.begin(), DeduceInits.end());
     return DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind,
-                                                       InitsCopy, PL);
+                                                       InitsCopy);
   }
 
   if (DirectInit) {

diff  --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index d6459fd9d7875d..0fbd87ce34db90 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -10561,7 +10561,7 @@ static bool isOrIsDerivedFromSpecializationOf(CXXRecordDecl *RD,
 
 QualType Sema::DeduceTemplateSpecializationFromInitializer(
     TypeSourceInfo *TSInfo, const InitializedEntity &Entity,
-    const InitializationKind &Kind, MultiExprArg Inits, ParenListExpr *PL) {
+    const InitializationKind &Kind, MultiExprArg Inits) {
   auto *DeducedTST = dyn_cast<DeducedTemplateSpecializationType>(
       TSInfo->getType()->getContainedDeducedType());
   assert(DeducedTST && "not a deduced template specialization type");
@@ -10792,9 +10792,12 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
     if (getLangOpts().CPlusPlus20 && !HasAnyDeductionGuide) {
       if (ListInit && ListInit->getNumInits()) {
         SynthesizeAggrGuide(ListInit);
-      } else if (PL && PL->getNumExprs()) {
-        InitListExpr TempListInit(getASTContext(), PL->getLParenLoc(),
-                                  PL->exprs(), PL->getRParenLoc());
+      } else if (Inits.size()) { // parenthesized expression-list
+        // Inits are expressions inside the parentheses. We don't have
+        // the parentheses source locations, use the begin/end of Inits as the
+        // best heuristic.
+        InitListExpr TempListInit(getASTContext(), Inits.front()->getBeginLoc(),
+                                  Inits, Inits.back()->getEndLoc());
         SynthesizeAggrGuide(&TempListInit);
       }
     }

diff  --git a/clang/test/SemaCXX/ctad.cpp b/clang/test/SemaCXX/ctad.cpp
new file mode 100644
index 00000000000000..10806f107b4ee9
--- /dev/null
+++ b/clang/test/SemaCXX/ctad.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused-value -std=c++20 %s
+// expected-no-diagnostics
+
+namespace GH64347 {
+
+template<typename X, typename Y> struct A { X x; Y y;};
+void test() {
+   A(1, 2);
+   new A(1, 2);
+}
+
+template<A a>
+void f() { (void)a; }
+void k() {
+  // Test CTAD works for non-type template arguments.
+  f<A(0, 0)>();
+}
+
+} // namespace GH64347


        


More information about the cfe-commits mailing list