aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaojian Wu <hokein.wu@gmail.com>2023-12-19 14:35:37 +0100
committerGitHub <noreply@github.com>2023-12-19 14:35:37 +0100
commit32aa7d823c8ae7183e65da2f29ed08a84d6a1b6b (patch)
treeec52cf160f43b1b09ecc2644085466e00652c93e
parent0d3d44522382028864d0223bc1d74929e17d5137 (diff)
downloadllvm-32aa7d823c8ae7183e65da2f29ed08a84d6a1b6b.zip
llvm-32aa7d823c8ae7183e65da2f29ed08a84d6a1b6b.tar.gz
llvm-32aa7d823c8ae7183e65da2f29ed08a84d6a1b6b.tar.bz2
[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).
-rw-r--r--clang/docs/ReleaseNotes.rst3
-rw-r--r--clang/include/clang/Sema/Sema.h3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp2
-rw-r--r--clang/lib/Sema/SemaInit.cpp11
-rw-r--r--clang/test/SemaCXX/ctad.cpp19
5 files changed, 31 insertions, 7 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index edb9734..39b9176 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 9887cc4..5e3b57e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9354,8 +9354,7 @@ public:
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 d1a26fe..ffbe317 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 d6459fd..0fbd87c 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 0000000..10806f1
--- /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