[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-10-30 Thread Maurice Heumann via cfe-commits

momo5502 wrote:

seems like nobody can review this. maybe you, @efriedma-quic, have time 😊

https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add /Zc:tlsGuards- option (PR #113830)

2024-10-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/113830

>From 433a059884ce4bbfada60a300666fe58aecede4f Mon Sep 17 00:00:00 2001
From: momo5502 
Date: Sun, 27 Oct 2024 20:02:00 +0100
Subject: [PATCH] Add /Zc:tlsGuards option to control to control tls guard
 emission

---
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Driver/Options.td | 11 +++
 clang/lib/CodeGen/MicrosoftCXXABI.cpp |  1 +
 clang/lib/Driver/ToolChains/Clang.cpp |  4 
 clang/test/CodeGenCXX/ms-thread_local.cpp |  4 
 clang/test/Driver/cl-zc.cpp   |  3 +++
 6 files changed, 24 insertions(+)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 68db400c22e6c1..bf2f23a2828176 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -186,6 +186,7 @@ COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions 
in AST when encounte
 COMPATIBLE_LANGOPT(RecoveryASTType, 1, 1, "Preserve the type in recovery 
expressions")
 
 BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
+BENIGN_LANGOPT(TlsGuards , 1, 1, "on-demand TLS initialization")
 LANGOPT(POSIXThreads  , 1, 0, "POSIX thread support")
 LANGOPT(Blocks, 1, 0, "blocks extension to C")
 BENIGN_LANGOPT(EmitAllDecls  , 1, 0, "emitting all declarations")
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 5df6ddd5e6a0c5..84b1404c214511 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4063,6 +4063,11 @@ defm threadsafe_statics : 
BoolFOption<"threadsafe-statics",
   NegFlag,
   PosFlag>;
+defm tls_guards : BoolFOption<"tls-guards",
+  LangOpts<"TlsGuards">, DefaultTrue,
+  NegFlag,
+  PosFlag>;
 def ftime_report : Flag<["-"], "ftime-report">, Group,
   Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoFlag>;
@@ -8610,6 +8615,12 @@ def _SLASH_Zc_threadSafeInit : 
CLFlag<"Zc:threadSafeInit">,
 def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">,
   HelpText<"Disable thread-safe initialization of static variables">,
   Alias;
+def _SLASH_Zc_tlsGuards : CLFlag<"Zc:tlsGuards">,
+  HelpText<"Enable on-demand initialization of thread-local variables">,
+  Alias;
+def _SLASH_Zc_tlsGuards_ : CLFlag<"Zc:tlsGuards-">,
+  HelpText<"Disable on-demand initialization of thread-local variables">,
+  Alias;
 def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
   HelpText<"Enable trigraphs">, Alias;
 def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp 
b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 0b0b45ffead92f..c705f3ad6e32ed 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -431,6 +431,7 @@ class MicrosoftCXXABI : public CGCXXABI {
   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
 return getContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019_5) &&
+   getContext().getLangOpts().TlsGuards &&
(!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
   }
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 04b3832327a99c..63d55d5ad615dd 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7291,6 +7291,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 (!IsWindowsMSVC || IsMSVC2015Compatible)))
 CmdArgs.push_back("-fno-threadsafe-statics");
 
+  if (!Args.hasFlag(options::OPT_ftls_guards, options::OPT_fno_tls_guards,
+true))
+CmdArgs.push_back("-fno-tls-guards");
+
   // Add -fno-assumptions, if it was specified.
   if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions,
 true))
diff --git a/clang/test/CodeGenCXX/ms-thread_local.cpp 
b/clang/test/CodeGenCXX/ms-thread_local.cpp
index cb0e8720c19b8b..cbd5647ee5032d 100644
--- a/clang/test/CodeGenCXX/ms-thread_local.cpp
+++ b/clang/test/CodeGenCXX/ms-thread_local.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -emit-llvm -o - | FileCheck %s
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.20 -emit-llvm -o - | FileCheck %s 
-check-prefix=CHECK-LEGACY
+// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -fno-tls-guards -emit-llvm -o - | FileCheck %s 
-check-prefix=CHECK-NO-GUARDS
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -ftls-model=local-dynamic -emit-llvm -o - | 
FileCheck %s -check-prefix=CHECK-LD
 
 struct A {
@@ -23,17 +24,20 @@ thread_local A a = A();
 // CHECK-LD-DAG: @"__tls_ini

[clang] Add /Zc:tlsGuards option to control to control tls guard emission (PR #113830)

2024-10-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add /Zc:tlsGuards option to control to control tls guard emission (PR #113830)

2024-10-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-10-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [MS] Add /Zc:tlsGuards option to control to control tls guard emission (PR #113830)

2024-10-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Add /Zc:tlsGuards option to control to control tls guard emission (PR #113830)

2024-10-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 ready_for_review 
https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-10-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/113830

>From 23d4562382b753c604fffa078f8bdd0f75d57ac4 Mon Sep 17 00:00:00 2001
From: momo5502 
Date: Sun, 27 Oct 2024 20:02:00 +0100
Subject: [PATCH] [MS] Add /Zc:tlsGuards option to control tls guard emission

---
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Driver/Options.td | 11 +++
 clang/lib/CodeGen/MicrosoftCXXABI.cpp |  1 +
 clang/lib/Driver/ToolChains/Clang.cpp |  4 
 clang/test/CodeGenCXX/ms-thread_local.cpp |  4 
 clang/test/Driver/cl-zc.cpp   |  3 +++
 6 files changed, 24 insertions(+)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 68db400c22e6c1..bf2f23a2828176 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -186,6 +186,7 @@ COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions 
in AST when encounte
 COMPATIBLE_LANGOPT(RecoveryASTType, 1, 1, "Preserve the type in recovery 
expressions")
 
 BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
+BENIGN_LANGOPT(TlsGuards , 1, 1, "on-demand TLS initialization")
 LANGOPT(POSIXThreads  , 1, 0, "POSIX thread support")
 LANGOPT(Blocks, 1, 0, "blocks extension to C")
 BENIGN_LANGOPT(EmitAllDecls  , 1, 0, "emitting all declarations")
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 5df6ddd5e6a0c5..84b1404c214511 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4063,6 +4063,11 @@ defm threadsafe_statics : 
BoolFOption<"threadsafe-statics",
   NegFlag,
   PosFlag>;
+defm tls_guards : BoolFOption<"tls-guards",
+  LangOpts<"TlsGuards">, DefaultTrue,
+  NegFlag,
+  PosFlag>;
 def ftime_report : Flag<["-"], "ftime-report">, Group,
   Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoFlag>;
@@ -8610,6 +8615,12 @@ def _SLASH_Zc_threadSafeInit : 
CLFlag<"Zc:threadSafeInit">,
 def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">,
   HelpText<"Disable thread-safe initialization of static variables">,
   Alias;
+def _SLASH_Zc_tlsGuards : CLFlag<"Zc:tlsGuards">,
+  HelpText<"Enable on-demand initialization of thread-local variables">,
+  Alias;
+def _SLASH_Zc_tlsGuards_ : CLFlag<"Zc:tlsGuards-">,
+  HelpText<"Disable on-demand initialization of thread-local variables">,
+  Alias;
 def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
   HelpText<"Enable trigraphs">, Alias;
 def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp 
b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 0b0b45ffead92f..c705f3ad6e32ed 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -431,6 +431,7 @@ class MicrosoftCXXABI : public CGCXXABI {
   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
 return getContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019_5) &&
+   getContext().getLangOpts().TlsGuards &&
(!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
   }
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 04b3832327a99c..63d55d5ad615dd 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7291,6 +7291,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 (!IsWindowsMSVC || IsMSVC2015Compatible)))
 CmdArgs.push_back("-fno-threadsafe-statics");
 
+  if (!Args.hasFlag(options::OPT_ftls_guards, options::OPT_fno_tls_guards,
+true))
+CmdArgs.push_back("-fno-tls-guards");
+
   // Add -fno-assumptions, if it was specified.
   if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions,
 true))
diff --git a/clang/test/CodeGenCXX/ms-thread_local.cpp 
b/clang/test/CodeGenCXX/ms-thread_local.cpp
index cb0e8720c19b8b..cbd5647ee5032d 100644
--- a/clang/test/CodeGenCXX/ms-thread_local.cpp
+++ b/clang/test/CodeGenCXX/ms-thread_local.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -emit-llvm -o - | FileCheck %s
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.20 -emit-llvm -o - | FileCheck %s 
-check-prefix=CHECK-LEGACY
+// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -fno-tls-guards -emit-llvm -o - | FileCheck %s 
-check-prefix=CHECK-NO-GUARDS
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -ftls-model=local-dynamic -emit-llvm -o - | 
FileCheck %s -check-prefix=CHECK-LD
 
 struct A {
@@ -23,17 +24,20 @@ thread_local A a = A();
 // CHECK-LD-DAG: @"__tls_init$initi

[clang] Add /Zc:tlsGuards- option (PR #113830)

2024-10-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 created 
https://github.com/llvm/llvm-project/pull/113830

This fixes #103484

>From b1b4da14386856667d11c284535348002954f94f Mon Sep 17 00:00:00 2001
From: momo5502 
Date: Sun, 27 Oct 2024 20:02:00 +0100
Subject: [PATCH] Add /Zc:tlsGuards- option

---
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Driver/Options.td | 11 +++
 clang/lib/CodeGen/MicrosoftCXXABI.cpp |  1 +
 clang/lib/Driver/ToolChains/Clang.cpp |  4 
 4 files changed, 17 insertions(+)

diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 68db400c22e6c1..bf2f23a2828176 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -186,6 +186,7 @@ COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions 
in AST when encounte
 COMPATIBLE_LANGOPT(RecoveryASTType, 1, 1, "Preserve the type in recovery 
expressions")
 
 BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
+BENIGN_LANGOPT(TlsGuards , 1, 1, "on-demand TLS initialization")
 LANGOPT(POSIXThreads  , 1, 0, "POSIX thread support")
 LANGOPT(Blocks, 1, 0, "blocks extension to C")
 BENIGN_LANGOPT(EmitAllDecls  , 1, 0, "emitting all declarations")
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 5df6ddd5e6a0c5..84b1404c214511 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4063,6 +4063,11 @@ defm threadsafe_statics : 
BoolFOption<"threadsafe-statics",
   NegFlag,
   PosFlag>;
+defm tls_guards : BoolFOption<"tls-guards",
+  LangOpts<"TlsGuards">, DefaultTrue,
+  NegFlag,
+  PosFlag>;
 def ftime_report : Flag<["-"], "ftime-report">, Group,
   Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoFlag>;
@@ -8610,6 +8615,12 @@ def _SLASH_Zc_threadSafeInit : 
CLFlag<"Zc:threadSafeInit">,
 def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">,
   HelpText<"Disable thread-safe initialization of static variables">,
   Alias;
+def _SLASH_Zc_tlsGuards : CLFlag<"Zc:tlsGuards">,
+  HelpText<"Enable on-demand initialization of thread-local variables">,
+  Alias;
+def _SLASH_Zc_tlsGuards_ : CLFlag<"Zc:tlsGuards-">,
+  HelpText<"Disable on-demand initialization of thread-local variables">,
+  Alias;
 def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
   HelpText<"Enable trigraphs">, Alias;
 def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp 
b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 0b0b45ffead92f..c705f3ad6e32ed 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -431,6 +431,7 @@ class MicrosoftCXXABI : public CGCXXABI {
   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
 return getContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019_5) &&
+   getContext().getLangOpts().TlsGuards &&
(!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
   }
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 04b3832327a99c..da659fa4db235d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7291,6 +7291,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 (!IsWindowsMSVC || IsMSVC2015Compatible)))
 CmdArgs.push_back("-fno-threadsafe-statics");
 
+  if (!Args.hasFlag(options::OPT_ftls_guards,
+options::OPT_fno_tls_guards, true))
+CmdArgs.push_back("-fno-tls-guards");
+
   // Add -fno-assumptions, if it was specified.
   if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions,
 true))

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-11-09 Thread Maurice Heumann via cfe-commits

momo5502 wrote:

@efriedma-quic is the PR fine like that?

https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-11-01 Thread Maurice Heumann via cfe-commits


@@ -4063,6 +4063,11 @@ defm threadsafe_statics : 
BoolFOption<"threadsafe-statics",
   NegFlag,
   PosFlag>;
+defm tls_guards : BoolFOption<"tls-guards",
+  LangOpts<"TlsGuards">, DefaultTrue,

momo5502 wrote:

Ah I see :D i have never added an option before.

I removed it as a clang option and renamed it to `-fms-tls-guards` (& 
`-fno-ms-tls-guards`).
It applies to all tls variables in general, whether they are defined inside a 
function or not should not be relevant, from what I understand from Microsoft's 
documentation

https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-11-01 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/113830

>From 46aede6d9c19eeb304554ac3fdd0fe4b04b3e257 Mon Sep 17 00:00:00 2001
From: momo5502 
Date: Sun, 27 Oct 2024 20:02:00 +0100
Subject: [PATCH] [MS] Add /Zc:tlsGuards option to control tls guard emission

---
 clang/include/clang/Basic/CodeGenOptions.def |  1 +
 clang/include/clang/Driver/Options.td| 11 +++
 clang/lib/CodeGen/MicrosoftCXXABI.cpp|  1 +
 clang/lib/Driver/ToolChains/Clang.cpp|  4 
 clang/test/CodeGenCXX/ms-thread_local.cpp|  4 
 clang/test/Driver/cl-zc.cpp  |  3 +++
 6 files changed, 24 insertions(+)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index e45370bde74a5d..4cf22c4ee08ce0 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -155,6 +155,7 @@ VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0)
 CODEGENOPT(HotPatch, 1, 0) ///< Supports the Microsoft /HOTPATCH flag and
///< generates a 'patchable-function' attribute.
 
+CODEGENOPT(TlsGuards , 1, 1) ///< Controls emission of tls guards via 
-fms-tls-guards
 CODEGENOPT(JMCInstrument, 1, 0) ///< Set when -fjmc is enabled.
 CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
 CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 5df6ddd5e6a0c5..54610c310e234d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4063,6 +4063,11 @@ defm threadsafe_statics : 
BoolFOption<"threadsafe-statics",
   NegFlag,
   PosFlag>;
+defm ms_tls_guards : BoolFOption<"ms-tls-guards",
+  CodeGenOpts<"TlsGuards">, DefaultTrue,
+  NegFlag,
+  PosFlag>;
 def ftime_report : Flag<["-"], "ftime-report">, Group,
   Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoFlag>;
@@ -8610,6 +8615,12 @@ def _SLASH_Zc_threadSafeInit : 
CLFlag<"Zc:threadSafeInit">,
 def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">,
   HelpText<"Disable thread-safe initialization of static variables">,
   Alias;
+def _SLASH_Zc_tlsGuards : CLFlag<"Zc:tlsGuards">,
+  HelpText<"Enable on-demand initialization of thread-local variables">,
+  Alias;
+def _SLASH_Zc_tlsGuards_ : CLFlag<"Zc:tlsGuards-">,
+  HelpText<"Disable on-demand initialization of thread-local variables">,
+  Alias;
 def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
   HelpText<"Enable trigraphs">, Alias;
 def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp 
b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 0b0b45ffead92f..af316706fdc13f 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -431,6 +431,7 @@ class MicrosoftCXXABI : public CGCXXABI {
   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
 return getContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019_5) &&
+   CGM.getCodeGenOpts().TlsGuards &&
(!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
   }
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 04b3832327a99c..466fcd38c747ad 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7291,6 +7291,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 (!IsWindowsMSVC || IsMSVC2015Compatible)))
 CmdArgs.push_back("-fno-threadsafe-statics");
 
+  if (!Args.hasFlag(options::OPT_fms_tls_guards, 
options::OPT_fno_ms_tls_guards,
+true))
+CmdArgs.push_back("-fno-ms-tls-guards");
+
   // Add -fno-assumptions, if it was specified.
   if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions,
 true))
diff --git a/clang/test/CodeGenCXX/ms-thread_local.cpp 
b/clang/test/CodeGenCXX/ms-thread_local.cpp
index cb0e8720c19b8b..1e1d1db0744b29 100644
--- a/clang/test/CodeGenCXX/ms-thread_local.cpp
+++ b/clang/test/CodeGenCXX/ms-thread_local.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -emit-llvm -o - | FileCheck %s
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.20 -emit-llvm -o - | FileCheck %s 
-check-prefix=CHECK-LEGACY
+// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -fno-ms-tls-guards -emit-llvm -o - | FileCheck 
%s -check-prefix=CHECK-NO-GUARDS
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -ftls-model=local-dynamic -emit-llvm -o - | 
FileCheck %s -check-prefix=CHECK-LD
 
 struct A {
@@ -23,17 +24,20 @@ thread_local A a = 

[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-11-01 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/113830

>From 8caca3e5a7caeedd47f2910b82dcde2e7fbbcba7 Mon Sep 17 00:00:00 2001
From: momo5502 
Date: Sun, 27 Oct 2024 20:02:00 +0100
Subject: [PATCH] [MS] Add /Zc:tlsGuards option to control tls guard emission

---
 clang/include/clang/Basic/CodeGenOptions.def |  1 +
 clang/include/clang/Driver/Options.td| 11 +++
 clang/lib/CodeGen/MicrosoftCXXABI.cpp|  1 +
 clang/lib/Driver/ToolChains/Clang.cpp|  5 +
 clang/test/CodeGenCXX/ms-thread_local.cpp|  4 
 clang/test/Driver/cl-zc.cpp  |  3 +++
 6 files changed, 25 insertions(+)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index e45370bde74a5d..4cf22c4ee08ce0 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -155,6 +155,7 @@ VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0)
 CODEGENOPT(HotPatch, 1, 0) ///< Supports the Microsoft /HOTPATCH flag and
///< generates a 'patchable-function' attribute.
 
+CODEGENOPT(TlsGuards , 1, 1) ///< Controls emission of tls guards via 
-fms-tls-guards
 CODEGENOPT(JMCInstrument, 1, 0) ///< Set when -fjmc is enabled.
 CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
 CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 5df6ddd5e6a0c5..54610c310e234d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4063,6 +4063,11 @@ defm threadsafe_statics : 
BoolFOption<"threadsafe-statics",
   NegFlag,
   PosFlag>;
+defm ms_tls_guards : BoolFOption<"ms-tls-guards",
+  CodeGenOpts<"TlsGuards">, DefaultTrue,
+  NegFlag,
+  PosFlag>;
 def ftime_report : Flag<["-"], "ftime-report">, Group,
   Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoFlag>;
@@ -8610,6 +8615,12 @@ def _SLASH_Zc_threadSafeInit : 
CLFlag<"Zc:threadSafeInit">,
 def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">,
   HelpText<"Disable thread-safe initialization of static variables">,
   Alias;
+def _SLASH_Zc_tlsGuards : CLFlag<"Zc:tlsGuards">,
+  HelpText<"Enable on-demand initialization of thread-local variables">,
+  Alias;
+def _SLASH_Zc_tlsGuards_ : CLFlag<"Zc:tlsGuards-">,
+  HelpText<"Disable on-demand initialization of thread-local variables">,
+  Alias;
 def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
   HelpText<"Enable trigraphs">, Alias;
 def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp 
b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 0b0b45ffead92f..af316706fdc13f 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -431,6 +431,7 @@ class MicrosoftCXXABI : public CGCXXABI {
   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
 return getContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019_5) &&
+   CGM.getCodeGenOpts().TlsGuards &&
(!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
   }
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 04b3832327a99c..4f382886379fad 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7291,6 +7291,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 (!IsWindowsMSVC || IsMSVC2015Compatible)))
 CmdArgs.push_back("-fno-threadsafe-statics");
 
+  if (!Args.hasFlag(options::OPT_fms_tls_guards,
+options::OPT_fno_ms_tls_guards,
+true))
+CmdArgs.push_back("-fno-ms-tls-guards");
+
   // Add -fno-assumptions, if it was specified.
   if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions,
 true))
diff --git a/clang/test/CodeGenCXX/ms-thread_local.cpp 
b/clang/test/CodeGenCXX/ms-thread_local.cpp
index cb0e8720c19b8b..1e1d1db0744b29 100644
--- a/clang/test/CodeGenCXX/ms-thread_local.cpp
+++ b/clang/test/CodeGenCXX/ms-thread_local.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -emit-llvm -o - | FileCheck %s
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.20 -emit-llvm -o - | FileCheck %s 
-check-prefix=CHECK-LEGACY
+// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -fno-ms-tls-guards -emit-llvm -o - | FileCheck 
%s -check-prefix=CHECK-NO-GUARDS
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -ftls-model=local-dynamic -emit-llvm -o - | 
FileCheck %s -check-prefix=CHECK-LD
 
 struct A {
@@ -23,17 +24,20 @

[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-11-01 Thread Maurice Heumann via cfe-commits


@@ -186,6 +186,7 @@ COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions 
in AST when encounte
 COMPATIBLE_LANGOPT(RecoveryASTType, 1, 1, "Preserve the type in recovery 
expressions")
 
 BENIGN_LANGOPT(ThreadsafeStatics , 1, 1, "thread-safe static initializers")
+BENIGN_LANGOPT(TlsGuards , 1, 1, "on-demand TLS initialization")

momo5502 wrote:

done. moved to codegen options

https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86] Consistently use __inline__ keyword in intrin.h (PR #117856)

2024-11-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 created 
https://github.com/llvm/llvm-project/pull/117856

Using `inline` instead of `__inline__` may cause duplicate symbol errors in 
some scenarios.

This fixes #117854

>From 2048ca63a5bdf1a5858986a849a6046e307f412d Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 27 Nov 2024 09:13:26 +0100
Subject: [PATCH] [X86] Consistently use __inline__ keyword in intrin.h

This fixes #117854
---
 clang/lib/Headers/intrin.h | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index 6308c865ca9136..8e2b95b52442db 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -330,33 +330,33 @@ static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
   __asm__ volatile("hlt");
 }
 
-static inline unsigned char __inbyte(unsigned short port) {
+static __inline__ unsigned char __inbyte(unsigned short port) {
   unsigned char ret;
   __asm__ __volatile__("inb %w1, %b0" : "=a"(ret) : "Nd"(port));
   return ret;
 }
 
-static inline unsigned short __inword(unsigned short port) {
+static __inline__ unsigned short __inword(unsigned short port) {
   unsigned short ret;
   __asm__ __volatile__("inw %w1, %w0" : "=a"(ret) : "Nd"(port));
   return ret;
 }
 
-static inline unsigned long __indword(unsigned short port) {
+static __inline__ unsigned long __indword(unsigned short port) {
   unsigned long ret;
   __asm__ __volatile__("inl %w1, %k0" : "=a"(ret) : "Nd"(port));
   return ret;
 }
 
-static inline void __outbyte(unsigned short port, unsigned char data) {
+static __inline__ void __outbyte(unsigned short port, unsigned char data) {
   __asm__ __volatile__("outb %b0, %w1" : : "a"(data), "Nd"(port));
 }
 
-static inline void __outword(unsigned short port, unsigned short data) {
+static __inline__ void __outword(unsigned short port, unsigned short data) {
   __asm__ __volatile__("outw %w0, %w1" : : "a"(data), "Nd"(port));
 }
 
-static inline void __outdword(unsigned short port, unsigned long data) {
+static __inline__ void __outdword(unsigned short port, unsigned long data) {
   __asm__ __volatile__("outl %k0, %w1" : : "a"(data), "Nd"(port));
 }
 #endif

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86] Consistently use __inline__ keyword in intrin.h (PR #117856)

2024-11-27 Thread Maurice Heumann via cfe-commits

momo5502 wrote:

> LGTM - cheers

Thank you, can you merge it for me plase :)

https://github.com/llvm/llvm-project/pull/117856
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-11-13 Thread Maurice Heumann via cfe-commits

momo5502 wrote:

> LGTM

Thanks, would you mind merging it for me please

https://github.com/llvm/llvm-project/pull/113830
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)

2024-11-16 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/113830

>From 722a446023bd394c85c6eebf66e7bb5631a92a4d Mon Sep 17 00:00:00 2001
From: momo5502 
Date: Sun, 27 Oct 2024 20:02:00 +0100
Subject: [PATCH] [MS] Add /Zc:tlsGuards option to control tls guard emission

---
 clang/include/clang/Basic/CodeGenOptions.def |  1 +
 clang/include/clang/Driver/Options.td| 11 +++
 clang/lib/CodeGen/MicrosoftCXXABI.cpp|  1 +
 clang/lib/Driver/ToolChains/Clang.cpp|  4 
 clang/test/CodeGenCXX/ms-thread_local.cpp|  4 
 clang/test/Driver/cl-zc.cpp  |  3 +++
 6 files changed, 24 insertions(+)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def 
b/clang/include/clang/Basic/CodeGenOptions.def
index e45370bde74a5d..4cf22c4ee08ce0 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -155,6 +155,7 @@ VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0)
 CODEGENOPT(HotPatch, 1, 0) ///< Supports the Microsoft /HOTPATCH flag and
///< generates a 'patchable-function' attribute.
 
+CODEGENOPT(TlsGuards , 1, 1) ///< Controls emission of tls guards via 
-fms-tls-guards
 CODEGENOPT(JMCInstrument, 1, 0) ///< Set when -fjmc is enabled.
 CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
 CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 0a94a7185df8c7..d7230dd7272fd6 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4072,6 +4072,11 @@ defm threadsafe_statics : 
BoolFOption<"threadsafe-statics",
   NegFlag,
   PosFlag>;
+defm ms_tls_guards : BoolFOption<"ms-tls-guards",
+  CodeGenOpts<"TlsGuards">, DefaultTrue,
+  NegFlag,
+  PosFlag>;
 def ftime_report : Flag<["-"], "ftime-report">, Group,
   Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoFlag>;
@@ -8635,6 +8640,12 @@ def _SLASH_Zc_threadSafeInit : 
CLFlag<"Zc:threadSafeInit">,
 def _SLASH_Zc_threadSafeInit_ : CLFlag<"Zc:threadSafeInit-">,
   HelpText<"Disable thread-safe initialization of static variables">,
   Alias;
+def _SLASH_Zc_tlsGuards : CLFlag<"Zc:tlsGuards">,
+  HelpText<"Enable on-demand initialization of thread-local variables">,
+  Alias;
+def _SLASH_Zc_tlsGuards_ : CLFlag<"Zc:tlsGuards-">,
+  HelpText<"Disable on-demand initialization of thread-local variables">,
+  Alias;
 def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
   HelpText<"Enable trigraphs">, Alias;
 def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp 
b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 3802dc8bcafc49..d587daac5a88a9 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -431,6 +431,7 @@ class MicrosoftCXXABI : public CGCXXABI {
   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
 return getContext().getLangOpts().isCompatibleWithMSVC(
LangOptions::MSVC2019_5) &&
+   CGM.getCodeGenOpts().TlsGuards &&
(!isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD));
   }
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 3133b8f5762389..d3eec9fea0d498 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7317,6 +7317,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 (!IsWindowsMSVC || IsMSVC2015Compatible)))
 CmdArgs.push_back("-fno-threadsafe-statics");
 
+  if (!Args.hasFlag(options::OPT_fms_tls_guards, 
options::OPT_fno_ms_tls_guards,
+true))
+CmdArgs.push_back("-fno-ms-tls-guards");
+
   // Add -fno-assumptions, if it was specified.
   if (!Args.hasFlag(options::OPT_fassumptions, options::OPT_fno_assumptions,
 true))
diff --git a/clang/test/CodeGenCXX/ms-thread_local.cpp 
b/clang/test/CodeGenCXX/ms-thread_local.cpp
index cb0e8720c19b8b..1e1d1db0744b29 100644
--- a/clang/test/CodeGenCXX/ms-thread_local.cpp
+++ b/clang/test/CodeGenCXX/ms-thread_local.cpp
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -emit-llvm -o - | FileCheck %s
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.20 -emit-llvm -o - | FileCheck %s 
-check-prefix=CHECK-LEGACY
+// RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -fno-ms-tls-guards -emit-llvm -o - | FileCheck 
%s -check-prefix=CHECK-NO-GUARDS
 // RUN: %clang_cc1 %s -std=c++1y -triple=i686-pc-win32 
-fms-compatibility-version=19.25 -ftls-model=local-dynamic -emit-llvm -o - | 
FileCheck %s -check-prefix=CHECK-LD
 
 struct A {
@@ -23,17 +24,20 @@ thread_local A a = 

[clang] Mark union member destructors referenced (PR #128866)

2025-02-26 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From 484ff7a53ab700fda30ee90f739bb2573f41c851 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 08:37:04 +0100
Subject: [PATCH 1/2] Mark union member destructors referenced

---
 clang/lib/Sema/SemaDeclCXX.cpp | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 664d48ccbc382..ce7927dedd96b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5764,7 +5764,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
   // Ignore dependent contexts. Also ignore unions, since their members never
   // have destructors implicitly called.
-  if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
+  if (ClassDecl->isDependentContext() /*|| ClassDecl->isUnion()*/)
 return;
 
   // FIXME: all the access-control diagnostics are positioned on the
@@ -5793,8 +5793,10 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 if (FieldClassDecl->hasIrrelevantDestructor())
   continue;
 // The destructor for an implicit anonymous union member is never invoked.
-if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion())
+if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion()) {
+  MarkBaseAndMemberDestructorsReferenced(Location, FieldClassDecl);
   continue;
+}
 
 CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
 // Dtor might still be missing, e.g because it's invalid.

>From 448d01dc91a4cb79250efd43f52da5caa18ed6b5 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 2/2] Only instantiate destructors via a constructor

---
 clang/include/clang/Sema/Sema.h | 2 +-
 clang/lib/Sema/SemaDecl.cpp | 2 +-
 clang/lib/Sema/SemaDeclCXX.cpp  | 8 
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 476abe86cb2d2..c2e6006c06a77 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5430,7 +5430,7 @@ class Sema final : public SemaBase {
   /// mark all the non-trivial destructors of its members and bases as
   /// referenced.
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
-  CXXRecordDecl *Record);
+  CXXRecordDecl *Record, bool 
AllowUnionMembers);
 
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 285bd27a35a76..d546acb238583 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -16464,7 +16464,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt 
*Body,
   CheckDestructor(Destructor);
 
 MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
-   Destructor->getParent());
+   Destructor->getParent(), false);
   }
 
   // If any errors have occurred, clear out any temporaries that may have
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ce7927dedd96b..a9f17f1981b33 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5454,7 +5454,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
 // Constructors implicitly reference the base and member
 // destructors.
 MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+   Constructor->getParent(), true);
   }
 
   return HadError;
@@ -5761,7 +5761,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
 
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
- CXXRecordDecl *ClassDecl) {
+ CXXRecordDecl *ClassDecl, bool 
AllowUnionMembers) {
   // Ignore dependent contexts. Also ignore unions, since their members never
   // have destructors implicitly called.
   if (ClassDecl->isDependentContext() /*|| ClassDecl->isUnion()*/)
@@ -5794,7 +5794,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
   continue;
 // The destructor for an implicit anonymous union member is never invoked.
 if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion()) {
-  MarkBaseAndMemberDestructorsReferenced(Location, FieldClassDecl);
+  MarkBaseAndMemberDestructorsR

[clang] Don't generate SEH scopes for noexcept functions (PR #128839)

2025-02-25 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 created 
https://github.com/llvm/llvm-project/pull/128839

This fixes #93251

>From 36931d9d2a4d50ac363a1b2de123909eacfb72a6 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 08:37:04 +0100
Subject: [PATCH] Don't generate SEH scopes for noexcept functions

---
 clang/lib/CodeGen/CGCleanup.cpp | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index 7e1c5b7da9552..69d605944b88c 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -152,6 +152,19 @@ EHScopeStack::getInnermostActiveNormalCleanup() const {
   return stable_end();
 }
 
+static bool FunctionCanThrow(const FunctionDecl *D) {
+  if (!D) {
+return true;
+  }
+
+  const auto *Proto = D->getType()->getAs();
+  if (!Proto) {
+// Function proto is not found, we conservatively assume throwing.
+return true;
+  }
+  return !isNoexceptExceptionSpec(Proto->getExceptionSpecType()) ||
+ Proto->canThrow() != CT_Cannot;
+}
 
 void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
   char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size));
@@ -191,7 +204,9 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t 
Size) {
   // consistent with MSVC's behavior, except in the presence of -EHa.
   // Check getInvokeDest() to generate llvm.seh.scope.begin() as needed.
   if (CGF->getLangOpts().EHAsynch && IsEHCleanup && !IsLifetimeMarker &&
-  CGF->getTarget().getCXXABI().isMicrosoft() && CGF->getInvokeDest())
+  CGF->getTarget().getCXXABI().isMicrosoft() &&
+  FunctionCanThrow(dyn_cast(CGF->CurFuncDecl)) &&
+  CGF->getInvokeDest())
 CGF->EmitSehCppScopeBegin();
 
   return Scope->getCleanupBuffer();
@@ -784,7 +799,8 @@ void CodeGenFunction::PopCleanupBlock(bool 
FallthroughIsBranchThrough,
 cleanupFlags.setIsEHCleanupKind();
 
   // Under -EHa, invoke seh.scope.end() to mark scope end before dtor
-  bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker();
+  bool IsEHa = getLangOpts().EHAsynch && !Scope.isLifetimeMarker() &&
+   FunctionCanThrow(dyn_cast(CurFuncDecl));
   const EHPersonality &Personality = EHPersonality::get(*this);
   if (!RequiresNormalCleanup) {
 // Mark CPP scope end for passed-by-value Arg temp

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Don't generate SEH scopes for noexcept functions (PR #128839)

2025-02-25 Thread Maurice Heumann via cfe-commits

momo5502 wrote:

FunctionCanThrow is copied from CGCoroutine.cpp

https://github.com/llvm/llvm-project/pull/128839
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Don't generate SEH scopes for noexcept functions (PR #128839)

2025-02-26 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 closed 
https://github.com/llvm/llvm-project/pull/128839
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Mark union member destructors referenced (PR #128866)

2025-02-26 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 created 
https://github.com/llvm/llvm-project/pull/128866

This could be a fix for #93251

>From 484ff7a53ab700fda30ee90f739bb2573f41c851 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 08:37:04 +0100
Subject: [PATCH] Mark union member destructors referenced

---
 clang/lib/Sema/SemaDeclCXX.cpp | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 664d48ccbc382..ce7927dedd96b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5764,7 +5764,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
   // Ignore dependent contexts. Also ignore unions, since their members never
   // have destructors implicitly called.
-  if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
+  if (ClassDecl->isDependentContext() /*|| ClassDecl->isUnion()*/)
 return;
 
   // FIXME: all the access-control diagnostics are positioned on the
@@ -5793,8 +5793,10 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 if (FieldClassDecl->hasIrrelevantDestructor())
   continue;
 // The destructor for an implicit anonymous union member is never invoked.
-if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion())
+if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion()) {
+  MarkBaseAndMemberDestructorsReferenced(Location, FieldClassDecl);
   continue;
+}
 
 CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
 // Dtor might still be missing, e.g because it's invalid.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Mark union member destructors referenced (PR #128866)

2025-02-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From 484ff7a53ab700fda30ee90f739bb2573f41c851 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 08:37:04 +0100
Subject: [PATCH 1/2] Mark union member destructors referenced

---
 clang/lib/Sema/SemaDeclCXX.cpp | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 664d48ccbc382..ce7927dedd96b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5764,7 +5764,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
   // Ignore dependent contexts. Also ignore unions, since their members never
   // have destructors implicitly called.
-  if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
+  if (ClassDecl->isDependentContext() /*|| ClassDecl->isUnion()*/)
 return;
 
   // FIXME: all the access-control diagnostics are positioned on the
@@ -5793,8 +5793,10 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 if (FieldClassDecl->hasIrrelevantDestructor())
   continue;
 // The destructor for an implicit anonymous union member is never invoked.
-if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion())
+if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion()) {
+  MarkBaseAndMemberDestructorsReferenced(Location, FieldClassDecl);
   continue;
+}
 
 CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
 // Dtor might still be missing, e.g because it's invalid.

>From 9918e933eb5bde3a24148e9aeb94688ea49d3353 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 2/2] Instantiate initialized field destructors

---
 clang/include/clang/Sema/Sema.h |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp  | 86 +++--
 2 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 476abe86cb2d2..6d3879985c6ce 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ce7927dedd96b..aa1f4460718a2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5451,10 +5451,19 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (Field) {
+MarkFieldDestructorReferenced(Location, Field);
+  }
+}
+
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+// MarkBaseAndMemberDestructorsReferenced(Location,
+// Constructor->getParent());
   }
 
   return HadError;
@@ -5759,6 +5768,43 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+

[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-02-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 ready_for_review 
https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-02-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Mark union member destructors referenced (PR #128866)

2025-02-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From 9234ac6c96f83977c32f2e90ebb553975dc209a5 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 87 +++
 .../test/SemaCXX/union-member-destructor.cpp  | 14 +++
 3 files changed, 68 insertions(+), 35 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 476abe86cb2d2..6d3879985c6ce 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 664d48ccbc382..842c4a866fc88 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5451,10 +5451,23 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *FieldRecordDecl = Field->getParent();
+  if (!FieldRecordDecl->isUnion() ||
+  !FieldRecordDecl->isAnonymousStructOrUnion())
+continue;
+
+  MarkFieldDestructorReferenced(Location, Field);
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5759,6 +5772,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5774,39 +5823,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous union member is never invoked.
-if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion())
-  continue;
-
-CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);

[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-02-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-02-28 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From 4353dbd9acc6c3e577b9aa65f5628602cf015caf Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 3 files changed, 110 insertions(+), 35 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 476abe86cb2d2..6d3879985c6ce 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 664d48ccbc382..5eafc539dd0fc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5451,10 +5451,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5759,6 +5780,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5774,39 +5831,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous union member is never invoked.
-if (FieldClassDecl->is

[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-02-28 Thread Maurice Heumann via cfe-commits


@@ -5451,10 +5451,23 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *FieldRecordDecl = Field->getParent();
+  if (!FieldRecordDecl->isUnion() ||

momo5502 wrote:

Both examples should work now. Let's hope all other tests still pass :D

The first example throws an additional error in gcc:

```
member 'VSX VS::_Tail' with destructor 
not allowed in anonymous aggregate
```

this error is not thrown by clang. should it though? If so, I don't think 
implementing that makes sense within the scope of this PR.
However, is it ok that I still added the sample as a test case, even though 
technically the behaviour clang yields for this test is not 100% correct?

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-02-28 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-02-28 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From 9749a0462b23b17fe830dd98f33a7fe00580cbc4 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 476abe86cb2d2..6d3879985c6ce 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 664d48ccbc382..5eafc539dd0fc 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5451,10 +5451,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5759,6 +5780,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5774,39 +5831,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous uni

[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-02-28 Thread Maurice Heumann via cfe-commits


@@ -5451,10 +5451,23 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *FieldRecordDecl = Field->getParent();
+  if (!FieldRecordDecl->isUnion() ||

momo5502 wrote:

One test failed, but it seems that it now behaves identical to gcc ( 
https://godbolt.org/z/fbxT8xnY9 ), so I fixed the test.

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-07 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/6] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From f23cf926c4dbf934971e5f4f8b40105e3b41bb0f Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/7] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 80177996b48b0..0afff5dd8d415 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5439,6 +5439,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits


@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+namespace t1{
+template  struct VSX {
+  ~VSX() { static_assert(sizeof(T) != 4, ""); } // expected-error {{static 
assertion failed due to requirement 'sizeof(int) != 4':}} \
+// expected-note {{expression 
evaluates to '4 != 4'}}
+};
+struct VS {
+  union {
+VSX _Tail;
+  };
+  ~VS() { }
+  VS(short);
+};
+VS::VS(short) : _Tail() { } // expected-note {{in instantiation of member 
function 't1::VSX::~VSX' requested here}}

momo5502 wrote:

alright, done.

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-08 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/7] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-03-04 Thread Maurice Heumann via cfe-commits


@@ -5450,10 +5450,20 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  MarkFieldDestructorReferenced(Location, Field);

momo5502 wrote:

done

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-03-04 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/3] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-03-04 Thread Maurice Heumann via cfe-commits


@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+namespace t1{
+template  struct VSX {
+  ~VSX() { static_assert(sizeof(T) != 4, ""); } // expected-error {{static 
assertion failed due to requirement 'sizeof(int) != 4':}} \
+// expected-note {{expression 
evaluates to '4 != 4'}}
+};
+struct VS {
+  union {
+VSX _Tail;
+  };
+  ~VS() { }
+  VS(short);
+};
+VS::VS(short) : _Tail() { } // expected-note {{in instantiation of member 
function 't1::VSX::~VSX' requested here}}

momo5502 wrote:

I added a delegating constructor to the test. As the delegating constructor 
invokes the one that triggers the assertion, the assertion has to come either 
way. Therefore, I assume the test should assert that the note does not appear 
at the delegating constructor.

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-03-04 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/4] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/8] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/7] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/6] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/9] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 01/10] Instantiate destructors from initialized anonymous
 union fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymo

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/6] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From f23cf926c4dbf934971e5f4f8b40105e3b41bb0f Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/6] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 80177996b48b0..0afff5dd8d415 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5439,6 +5439,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/7] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits


@@ -5283,6 +5283,102 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl 
*Constructor,
   return false;
 }
 
+static void MarkFieldDestructorReferenced(Sema &S, SourceLocation Location,
+  FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(S.Context, Field->getType()))
+return;
+
+  QualType FieldType = S.Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = S.LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  S.CheckDestructorAccess(Field->getLocation(), Dtor,
+  S.PDiag(diag::err_access_dtor_field)
+  << Field->getDeclName() << FieldType);
+
+  S.MarkFunctionReferenced(Location, Dtor);
+  S.DiagnoseUseOfDecl(Dtor, Location);
+}
+
+static void MarkBaseDestructorsReferenced(Sema &S, SourceLocation Location,
+  CXXRecordDecl *ClassDecl) {
+  if (ClassDecl->isDependentContext())
+return;
+
+  // We only potentially invoke the destructors of potentially constructed
+  // subobjects.
+  bool VisitVirtualBases = !ClassDecl->isAbstract();
+
+  // If the destructor exists and has already been marked used in the MS ABI,
+  // then virtual base destructors have already been checked and marked used.
+  // Skip checking them again to avoid duplicate diagnostics.
+  if (S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+CXXDestructorDecl *Dtor = ClassDecl->getDestructor();
+if (Dtor && Dtor->isUsed())
+  VisitVirtualBases = false;
+  }
+
+  llvm::SmallPtrSet DirectVirtualBases;

momo5502 wrote:

Yep, makes sense. I changed it.

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/7] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-06 Thread Maurice Heumann via cfe-commits


@@ -5283,6 +5283,102 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl 
*Constructor,
   return false;
 }
 
+static void MarkFieldDestructorReferenced(Sema &S, SourceLocation Location,
+  FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(S.Context, Field->getType()))
+return;
+
+  QualType FieldType = S.Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = S.LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  S.CheckDestructorAccess(Field->getLocation(), Dtor,
+  S.PDiag(diag::err_access_dtor_field)
+  << Field->getDeclName() << FieldType);
+
+  S.MarkFunctionReferenced(Location, Dtor);
+  S.DiagnoseUseOfDecl(Dtor, Location);
+}
+
+static void MarkBaseDestructorsReferenced(Sema &S, SourceLocation Location,
+  CXXRecordDecl *ClassDecl) {
+  if (ClassDecl->isDependentContext())
+return;
+
+  // We only potentially invoke the destructors of potentially constructed
+  // subobjects.
+  bool VisitVirtualBases = !ClassDecl->isAbstract();
+
+  // If the destructor exists and has already been marked used in the MS ABI,
+  // then virtual base destructors have already been checked and marked used.
+  // Skip checking them again to avoid duplicate diagnostics.
+  if (S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+CXXDestructorDecl *Dtor = ClassDecl->getDestructor();
+if (Dtor && Dtor->isUsed())
+  VisitVirtualBases = false;
+  }
+
+  llvm::SmallPtrSet DirectVirtualBases;
+
+  // Bases.
+  for (const auto &Base : ClassDecl->bases()) {
+const RecordType *RT = Base.getType()->getAs();
+if (!RT)
+  continue;
+
+// Remember direct virtual bases.
+if (Base.isVirtual()) {
+  if (!VisitVirtualBases)
+continue;
+  DirectVirtualBases.insert(RT);
+}
+
+CXXRecordDecl *BaseClassDecl = cast(RT->getDecl());
+// If our base class is invalid, we probably can't get its dtor anyway.
+if (BaseClassDecl->isInvalidDecl())

momo5502 wrote:

I extracted everything up to the destructor lookup. 
The `CheckDestructorAccess` call afterwards seems to differ slightly, so I left 
the rest as it is.

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-11 Thread Maurice Heumann via cfe-commits


@@ -5863,6 +5869,26 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  &DirectVirtualBases);
 }
 
+void Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
+  CXXRecordDecl *ClassDecl) {
+  // Ignore dependent contexts. Also ignore unions, since their members never
+  // have destructors implicitly called.
+  if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
+return;
+
+  // FIXME: all the access-control diagnostics are positioned on the
+  // field/base declaration.  That's probably good; that said, the
+  // user might reasonably want to know why the destructor is being
+  // emitted, and we currently don't say.

momo5502 wrote:

@cor3ntin shall I remove it or keep it?

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-11 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From b6c1d10fb99a45f07ba044ad516c44a1b6ff4a0c Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/7] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9ac26d8728446..50ab9b07c4333 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5445,6 +5445,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 1edbe62f1c79a..df38d418cba8b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5453,10 +5453,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5761,6 +5782,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5776,39 +5833,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-11 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/6] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] Mark union member destructors referenced (PR #128866)

2025-02-26 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From 484ff7a53ab700fda30ee90f739bb2573f41c851 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 08:37:04 +0100
Subject: [PATCH 1/2] Mark union member destructors referenced

---
 clang/lib/Sema/SemaDeclCXX.cpp | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 664d48ccbc382..ce7927dedd96b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5764,7 +5764,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
   // Ignore dependent contexts. Also ignore unions, since their members never
   // have destructors implicitly called.
-  if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
+  if (ClassDecl->isDependentContext() /*|| ClassDecl->isUnion()*/)
 return;
 
   // FIXME: all the access-control diagnostics are positioned on the
@@ -5793,8 +5793,10 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 if (FieldClassDecl->hasIrrelevantDestructor())
   continue;
 // The destructor for an implicit anonymous union member is never invoked.
-if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion())
+if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion()) {
+  MarkBaseAndMemberDestructorsReferenced(Location, FieldClassDecl);
   continue;
+}
 
 CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
 // Dtor might still be missing, e.g because it's invalid.

>From fdfa8e245c87e127068436cb10d75e2a10be6f33 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 2/2] Instantiate initialized field destructors

---
 clang/include/clang/Sema/Sema.h |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp  | 84 ++---
 2 files changed, 49 insertions(+), 37 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 476abe86cb2d2..6d3879985c6ce 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ce7927dedd96b..63602616b75be 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5451,10 +5451,17 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  auto *Field = Initializer->getAnyMember();
+  MarkFieldDestructorReferenced(Location, Field);
+}
+
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+// MarkBaseAndMemberDestructorsReferenced(Location,
+// Constructor->getParent());
   }
 
   return HadError;
@@ -5759,6 +5766,43 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_fiel

[clang] Mark union member destructors referenced (PR #128866)

2025-02-27 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From 5e5184ae2c4fddc1bef3f090748516cf5dc315ec Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH] Instantiate initialized field destructors

---
 clang/include/clang/Sema/Sema.h |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp  | 88 -
 2 files changed, 55 insertions(+), 35 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 476abe86cb2d2..6d3879985c6ce 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 664d48ccbc382..62ee967ae7e26 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5451,10 +5451,23 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *FieldRecordDecl = Field->getParent();
+  if (!FieldRecordDecl->isUnion() ||
+  !FieldRecordDecl->isAnonymousStructOrUnion())
+continue;
+
+  MarkFieldDestructorReferenced(Location, Field);
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5759,6 +5772,43 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5774,39 +5824,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous union member is never invoked.
-if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion())
-  continue;
-
-CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
-// Dtor might still be missing, e.g because it's invalid.
-if (!Dtor)
-  continue;
-CheckDestructorAccess(Field->getLocation(), Dtor,
- 

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-05 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-03-05 Thread Maurice Heumann via cfe-commits


@@ -5432,6 +5432,9 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkBaseDestructorsReferenced(SourceLocation Loc, CXXRecordDecl 
*Record);
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);

momo5502 wrote:

done

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-03-05 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-03-05 Thread Maurice Heumann via cfe-commits


@@ -5863,6 +5869,26 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  &DirectVirtualBases);
 }
 
+void Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
+  CXXRecordDecl *ClassDecl) {
+  // Ignore dependent contexts. Also ignore unions, since their members never
+  // have destructors implicitly called.
+  if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
+return;
+
+  // FIXME: all the access-control diagnostics are positioned on the
+  // field/base declaration.  That's probably good; that said, the
+  // user might reasonably want to know why the destructor is being
+  // emitted, and we currently don't say.

momo5502 wrote:

Hard for me to judge. It was added 15 years ago: 
https://github.com/llvm/llvm-project/commit/1064d7ef2992225ddbd792d1b54d144b809b5b39
I can remove it, if desired.

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized anonymous union fields (PR #128866)

2025-03-05 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From bb4091d2f9b7062aa83e5bee2ba525478a7dbd0a Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/5] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5b5cee5810488..c5b2d58a78fd2 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5432,6 +5432,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index a3a028b9485d6..761f6a09037a7 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5450,10 +5450,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5758,6 +5779,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5773,39 +5830,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-13 Thread Maurice Heumann via cfe-commits

momo5502 wrote:

> @shafik can you merge once you are happy?

@shafik has already approved. the only open comment was from you @cor3ntin. 
judging from your comment here, I assume Iit's ok to keep the fixme and resolve 
the comment (if not, feel free to reopen it).

https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-13 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 updated 
https://github.com/llvm/llvm-project/pull/128866

>From d854512f165c9dfd7dec437433a7944381df5d96 Mon Sep 17 00:00:00 2001
From: Maurice Heumann 
Date: Wed, 26 Feb 2025 14:31:47 +0100
Subject: [PATCH 1/7] Instantiate destructors from initialized anonymous union
 fields

---
 clang/include/clang/Sema/Sema.h   |  2 +
 clang/lib/Sema/SemaDeclCXX.cpp| 95 ---
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  6 +-
 .../test/SemaCXX/union-member-destructor.cpp  | 48 ++
 4 files changed, 113 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/SemaCXX/union-member-destructor.cpp

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9ac26d8728446..50ab9b07c4333 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5445,6 +5445,8 @@ class Sema final : public SemaBase {
   void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
   CXXRecordDecl *Record);
 
+  void MarkFieldDestructorReferenced(SourceLocation Loc, FieldDecl *Field);
+
   /// Mark destructors of virtual bases of this class referenced. In the 
Itanium
   /// C++ ABI, this is done when emitting a destructor for any non-abstract
   /// class. In the Microsoft C++ ABI, this is done any time a class's
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 1c62a551ee732..69fd70a1e83ed 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5456,10 +5456,31 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl 
*Constructor, bool AnyErrors,
NumInitializers * sizeof(CXXCtorInitializer*));
 Constructor->setCtorInitializers(baseOrMemberInitializers);
 
+SourceLocation Location = Constructor->getLocation();
+
+for (CXXCtorInitializer *Initializer : Info.AllToInit) {
+  FieldDecl *Field = Initializer->getAnyMember();
+  if (!Field)
+continue;
+
+  RecordDecl *Parent = Field->getParent();
+
+  while (Parent) {
+if (Parent->isUnion()) {
+  MarkFieldDestructorReferenced(Location, Field);
+  break;
+}
+
+if (!Parent->isAnonymousStructOrUnion() || Parent == ClassDecl) {
+  break;
+}
+
+Parent = cast(Parent->getDeclContext());
+  }
+}
 // Constructors implicitly reference the base and member
 // destructors.
-MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
-   Constructor->getParent());
+MarkBaseAndMemberDestructorsReferenced(Location, Constructor->getParent());
   }
 
   return HadError;
@@ -5764,6 +5785,42 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseUninitializedFields(*this, Constructor);
 }
 
+void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
+ FieldDecl *Field) {
+  if (Field->isInvalidDecl())
+return;
+
+  // Don't destroy incomplete or zero-length arrays.
+  if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
+return;
+
+  QualType FieldType = Context.getBaseElementType(Field->getType());
+
+  const RecordType *RT = FieldType->getAs();
+  if (!RT)
+return;
+
+  CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
+  if (FieldClassDecl->isInvalidDecl())
+return;
+  if (FieldClassDecl->hasIrrelevantDestructor())
+return;
+  // The destructor for an implicit anonymous union member is never invoked.
+  if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
+return;
+
+  CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
+  // Dtor might still be missing, e.g because it's invalid.
+  if (!Dtor)
+return;
+  CheckDestructorAccess(Field->getLocation(), Dtor,
+PDiag(diag::err_access_dtor_field)
+<< Field->getDeclName() << FieldType);
+
+  MarkFunctionReferenced(Location, Dtor);
+  DiagnoseUseOfDecl(Dtor, Location);
+}
+
 void
 Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
  CXXRecordDecl *ClassDecl) {
@@ -5779,39 +5836,7 @@ 
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
 
   // Non-static data members.
   for (auto *Field : ClassDecl->fields()) {
-if (Field->isInvalidDecl())
-  continue;
-
-// Don't destroy incomplete or zero-length arrays.
-if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
-  continue;
-
-QualType FieldType = Context.getBaseElementType(Field->getType());
-
-const RecordType* RT = FieldType->getAs();
-if (!RT)
-  continue;
-
-CXXRecordDecl *FieldClassDecl = cast(RT->getDecl());
-if (FieldClassDecl->isInvalidDecl())
-  continue;
-if (FieldClassDecl->hasIrrelevantDestructor())
-  continue;
-// The destructor for an implicit anonymous

[clang] [Sema] Instantiate destructors for initialized members (PR #128866)

2025-03-15 Thread Maurice Heumann via cfe-commits

https://github.com/momo5502 edited 
https://github.com/llvm/llvm-project/pull/128866
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits