================ @@ -0,0 +1,187 @@ +/** + * When building shared libraries, hidden objects which are defined in header + * files will be duplicated, with one copy in each shared library. If the object + * was meant to be globally unique (one copy per program), this can cause very + * subtle bugs. This file contains tests for the -Wunique-object-duplication + * warning, which is meant to detect this. + * + * Roughly, an object might be incorrectly duplicated if: + * - Is defined in a header (so it might appear in multiple TUs), and + * - Has external linkage (otherwise it's supposed to be duplicated), and + * - Has hidden visibility (or else the dynamic linker will handle it) + * + * Duplication becomes an issue only if one of the following is true: + * - The object is mutable (the copies won't be in sync), or + * - Its initialization may has side effects (it may now run more than once), or + * - The value of its address is used. + * + * Currently, we only detect the first two, and only warn on effectful + * initialization if we're certain there are side effects. Warning if the + * address is taken is prone to false positives, so we don't warn for now. + * + * The check is also disabled on Windows for now, since it uses + * dllimport/dllexport instead of visibility. + */ + +#define HIDDEN __attribute__((visibility("hidden"))) +#define DEFAULT __attribute__((visibility("default"))) + +// Helper functions +constexpr int init_constexpr(int x) { return x; }; +extern double init_dynamic(int); + +/****************************************************************************** + * Case one: Static local variables in an externally-visible function + ******************************************************************************/ +namespace StaticLocalTest { + +inline void has_static_locals_external() { + // Mutable + static int disallowedStatic1 = 0; // hidden-warning {{'disallowedStatic1' is mutable, has hidden visibility, and external linkage; it may be duplicated when built into a shared library}} + // Initialization might run more than once + static const double disallowedStatic2 = disallowedStatic1++; // hidden-warning {{'disallowedStatic2' has hidden visibility, and external linkage; its initialization may run more than once when built into a shared library}} + + // OK, because immutable and compile-time-initialized + static constexpr int allowedStatic1 = 0; + static const float allowedStatic2 = 1; + static constexpr int allowedStatic3 = init_constexpr(2); + static const int allowedStatic4 = init_constexpr(3); +} + +// Don't warn for non-inline functions, since they can't (legally) appear +// in more than one TU in the first place. +void has_static_locals_non_inline() { + // Mutable + static int allowedStatic1 = 0; + // Initialization might run more than once + static const double allowedStatic2 = allowedStatic1++; +} + +// Everything in this function is OK because the function is TU-local +static void has_static_locals_internal() { + static int allowedStatic1 = 0; + static double allowedStatic2 = init_dynamic(2); + static char allowedStatic3 = []() { return allowedStatic1++; }(); + + static constexpr int allowedStatic4 = 0; + static const float allowedStatic5 = 1; + static constexpr int allowedStatic6 = init_constexpr(2); + static const int allowedStatic7 = init_constexpr(3); +} + +namespace { + +// Everything in this function is OK because the function is also TU-local +void has_static_locals_anon() { + static int allowedStatic1 = 0; + static double allowedStatic2 = init_dynamic(2); + static char allowedStatic3 = []() { return allowedStatic1++; }(); + + static constexpr int allowedStatic4 = 0; + static const float allowedStatic5 = 1; + static constexpr int allowedStatic6 = init_constexpr(2); + static const int allowedStatic7 = init_constexpr(3); ---------------- zmodem wrote:
same as above https://github.com/llvm/llvm-project/pull/117622 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits