[clang] [MS] Add /Zc:tlsGuards option to control tls guard emission (PR #113830)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
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)
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)
@@ -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)
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)
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)
@@ -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)
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)
@@ -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)
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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
@@ -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)
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)
@@ -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)
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)
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)
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)
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