summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Friedman <efriedma@quicinc.com>2024-04-29 12:00:12 -0700
committerTom Stellard <tstellar@redhat.com>2024-05-01 15:56:33 -0700
commit617a15a9eac96088ae5e9134248d8236e34b91b1 (patch)
treee9d2cc6ad220dedae13f2324f23924546f91d6ef
parent20b9ed64ea074f03057e1d775a1d9d0f067ab0b0 (diff)
[clang codegen] Fix MS ABI detection of user-provided constructors. (#90151)llvmorg-18.1.5
In the context of determining whether a class counts as an "aggregate", a constructor template counts as a user-provided constructor. Fixes #86384 (cherry picked from commit 3ab4ae9e58c09dfd8203547ba8916f3458a0a481)
-rw-r--r--clang/docs/ReleaseNotes.rst6
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp12
-rw-r--r--clang/test/CodeGen/arm64-microsoft-arguments.cpp15
3 files changed, 30 insertions, 3 deletions
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1e88b58725bd..e533ecfd5aeb 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -149,6 +149,12 @@ ABI Changes in This Version
- Following the SystemV ABI for x86-64, ``__int128`` arguments will no longer
be split between a register and a stack slot.
+- Fixed Microsoft calling convention for returning certain classes with a
+ templated constructor. If a class has a templated constructor, it should
+ be returned indirectly even if it meets all the other requirements for
+ returning a class in a register. This affects some uses of std::pair.
+ (#GH86384).
+
AST Dumping Potentially Breaking Changes
----------------------------------------
- When dumping a sugared type, Clang will no longer print the desugared type if
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 172c4c937b97..4d0f4c63f843 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1135,9 +1135,15 @@ static bool isTrivialForMSVC(const CXXRecordDecl *RD, QualType Ty,
return false;
if (RD->hasNonTrivialCopyAssignment())
return false;
- for (const CXXConstructorDecl *Ctor : RD->ctors())
- if (Ctor->isUserProvided())
- return false;
+ for (const Decl *D : RD->decls()) {
+ if (auto *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (Ctor->isUserProvided())
+ return false;
+ } else if (auto *Template = dyn_cast<FunctionTemplateDecl>(D)) {
+ if (isa<CXXConstructorDecl>(Template->getTemplatedDecl()))
+ return false;
+ }
+ }
if (RD->hasNonTrivialDestructor())
return false;
return true;
diff --git a/clang/test/CodeGen/arm64-microsoft-arguments.cpp b/clang/test/CodeGen/arm64-microsoft-arguments.cpp
index e8309888dcfe..85472645acb3 100644
--- a/clang/test/CodeGen/arm64-microsoft-arguments.cpp
+++ b/clang/test/CodeGen/arm64-microsoft-arguments.cpp
@@ -201,3 +201,18 @@ S11 f11() {
S11 x;
return func11(x);
}
+
+// GH86384
+// Pass and return object with template constructor (pass directly,
+// return indirectly).
+// CHECK: define dso_local void @"?f12@@YA?AUS12@@XZ"(ptr dead_on_unwind inreg noalias writable sret(%struct.S12) align 4 {{.*}})
+// CHECK: call void @"?func12@@YA?AUS12@@U1@@Z"(ptr dead_on_unwind inreg writable sret(%struct.S12) align 4 {{.*}}, i64 {{.*}})
+struct S12 {
+ template<typename T> S12(T*) {}
+ int x;
+};
+S12 func12(S12 x);
+S12 f12() {
+ S12 x((int*)0);
+ return func12(x);
+}