[clang] 5ab3114 - Expand annotation check for -Wunique-object-duplication on Windows. (#145944)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 30 07:51:07 PDT 2025
Author: Devon Loehr
Date: 2025-06-30T10:51:04-04:00
New Revision: 5ab3114bd12cdafc1e4e384e3a06c7258723ebde
URL: https://github.com/llvm/llvm-project/commit/5ab3114bd12cdafc1e4e384e3a06c7258723ebde
DIFF: https://github.com/llvm/llvm-project/commit/5ab3114bd12cdafc1e4e384e3a06c7258723ebde.diff
LOG: Expand annotation check for -Wunique-object-duplication on Windows. (#145944)
Since dllexport/dllimport annotations don't propagate the same way as
visibility, the unique object duplication warning needs to check both
the object in question and its containing class. Previously, we
restricted this check to static data members, but it applies to all
objects inside a class, including functions. Not checking functions
leads to false positives, so remove that restriction.
Added:
Modified:
clang/lib/Sema/SemaDecl.cpp
clang/test/SemaCXX/unique_object_duplication.h
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 33b9ef869746a..f4bc191d1dae6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13531,21 +13531,19 @@ bool Sema::GloballyUniqueObjectMightBeAccidentallyDuplicated(
// The target is "hidden" (from the dynamic linker) if:
// 1. On posix, it has hidden visibility, or
- // 2. On windows, it has no import/export annotation
+ // 2. On windows, it has no import/export annotation, and neither does the
+ // class which directly contains it.
if (Context.getTargetInfo().shouldDLLImportComdatSymbols()) {
if (Target->hasAttr<DLLExportAttr>() || Target->hasAttr<DLLImportAttr>())
return false;
// If the variable isn't directly annotated, check to see if it's a member
// of an annotated class.
- const VarDecl *VD = dyn_cast<VarDecl>(Target);
+ const CXXRecordDecl *Ctx =
+ dyn_cast<CXXRecordDecl>(Target->getDeclContext());
+ if (Ctx && (Ctx->hasAttr<DLLExportAttr>() || Ctx->hasAttr<DLLImportAttr>()))
+ return false;
- if (VD && VD->isStaticDataMember()) {
- const CXXRecordDecl *Ctx = dyn_cast<CXXRecordDecl>(VD->getDeclContext());
- if (Ctx &&
- (Ctx->hasAttr<DLLExportAttr>() || Ctx->hasAttr<DLLImportAttr>()))
- return false;
- }
} else if (Lnk.getVisibility() != HiddenVisibility) {
// Posix case
return false;
diff --git a/clang/test/SemaCXX/unique_object_duplication.h b/clang/test/SemaCXX/unique_object_duplication.h
index bd0ee6bd14d64..a5da767b79474 100644
--- a/clang/test/SemaCXX/unique_object_duplication.h
+++ b/clang/test/SemaCXX/unique_object_duplication.h
@@ -173,10 +173,6 @@ namespace GlobalTest {
// Always visible
VISIBLE static inline float allowedStaticMember2 = 0.0;
-
- // Tests here are sparse because the AddrTest case below will define plenty
- // more, which aren't problematic to define (because they're immutable), but
- // may still cause problems if their address is taken.
};
inline float Test::disallowedStaticMember2 = 2.3; // hidden-warning {{'disallowedStaticMember2' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
@@ -211,3 +207,44 @@ inline int allowedTemplate2 = 0;
template int allowedTemplate2<int>;
} // namespace TemplateTest
+
+/******************************************************************************
+ * Case four: Nested classes
+ ******************************************************************************/
+
+namespace NestedClassTest {
+// Unlike visibility, declexport annotations do not propagate down to nested
+// classes. Hence on windows, we only avoid duplication of class members if
+// their immediate containing class is annotated. On posix, we get avoid
+// duplication if any containing class is annotated.
+
+class VISIBLE Outer {
+ // Visible because their class is exported
+ inline static int allowedOuterMember = 0;
+ int* allowedOuterFunction() {
+ static int allowed = 0;
+ return &allowed;
+ }
+
+ // No annotation, and visibility is only propagated on posix.
+ class HiddenOnWindows {
+ inline static int disallowedInnerMember = 0; // windows-warning {{'disallowedInnerMember' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
+
+
+ int* disallowedInnerFunction() {
+ static int disallowed = 0; // windows-warning {{'disallowed' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
+ return &disallowed;
+ }
+ };
+
+ class VISIBLE AlwaysVisible {
+ inline static int allowedInnerMember = 0;
+
+ int* allowedInnerFunction() {
+ static int allowed = 0;
+ return &allowed;
+ }
+ };
+};
+
+}
\ No newline at end of file
More information about the cfe-commits
mailing list