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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits