CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
250 lines
13 KiB
C++
250 lines
13 KiB
C++
/**
|
|
* This file contains tests for the -Wunique_object_duplication warning.
|
|
* See the warning's documentation for more information.
|
|
*/
|
|
|
|
#ifdef WINDOWS_TEST
|
|
#define HIDDEN
|
|
// dllimport also suffices for visibility, but those can't have definitions
|
|
#define VISIBLE __declspec(dllexport)
|
|
#else
|
|
#define HIDDEN __attribute__((visibility("hidden")))
|
|
#define VISIBLE __attribute__((visibility("default")))
|
|
#endif
|
|
|
|
// 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' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'disallowedStatic1' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
// Initialization might run more than once
|
|
static const double disallowedStatic2 = disallowedStatic1++; // hidden-warning {{initialization of 'disallowedStatic2' may run twice when built into a shared library: it has external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{initialization of 'disallowedStatic2' may run twice when built into a shared library: it has external linkage and no import/export annotation}}
|
|
// 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;
|
|
}
|
|
|
|
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 = init_constexpr(3);
|
|
}
|
|
|
|
} // Anonymous namespace
|
|
|
|
HIDDEN inline void static_local_always_hidden() {
|
|
static int disallowedStatic1 = 3; // hidden-warning {{'disallowedStatic1' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// expected-warning@-1 {{'disallowedStatic1' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-2 {{'disallowedStatic1' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
{
|
|
static int disallowedStatic2 = 3; // hidden-warning {{'disallowedStatic2' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// expected-warning@-1 {{'disallowedStatic2' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-2 {{'disallowedStatic2' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
}
|
|
|
|
auto lmb = []() {
|
|
static int disallowedStatic3 = 3; // hidden-warning {{'disallowedStatic3' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// expected-warning@-1 {{'disallowedStatic3' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-2 {{'disallowedStatic3' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
};
|
|
}
|
|
|
|
// Always visible
|
|
VISIBLE void static_local_never_hidden() {
|
|
static int allowedStatic1 = 3;
|
|
|
|
{
|
|
static int allowedStatic2 = 3;
|
|
}
|
|
|
|
auto lmb = []() {
|
|
static int allowedStatic3 = 3;
|
|
};
|
|
}
|
|
|
|
// Don't warn on this because it's not in a function
|
|
const int setByLambda = ([]() { static int x = 3; return x++; })();
|
|
|
|
inline void has_extern_local() {
|
|
extern int allowedAddressExtern; // Not a definition
|
|
}
|
|
|
|
inline void has_regular_local() {
|
|
int allowedAddressLocal = 0;
|
|
}
|
|
|
|
inline void has_thread_local() {
|
|
// thread_local variables are static by default
|
|
thread_local int disallowedThreadLocal = 0; // hidden-warning {{'disallowedThreadLocal' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'disallowedThreadLocal' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
}
|
|
|
|
// Functions themselves are always immutable, so referencing them is okay
|
|
inline auto& allowedFunctionReference = has_static_locals_external;
|
|
|
|
} // namespace StaticLocalTest
|
|
|
|
/******************************************************************************
|
|
* Case two: Globals with external linkage
|
|
******************************************************************************/
|
|
namespace GlobalTest {
|
|
// Mutable
|
|
inline float disallowedGlobal1 = 3.14; // hidden-warning {{'disallowedGlobal1' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'disallowedGlobal1' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
|
|
|
|
// Initialization might run more than once
|
|
inline const double disallowedGlobal5 = disallowedGlobal1++; // hidden-warning {{initialization of 'disallowedGlobal5' may run twice when built into a shared library: it has external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{initialization of 'disallowedGlobal5' may run twice when built into a shared library: it has external linkage and no import/export annotation}}
|
|
// OK because internal linkage, so duplication is intended
|
|
static float allowedGlobal1 = 3.14;
|
|
const double allowedGlobal2 = init_dynamic(2);
|
|
static const char allowedGlobal3 = []() { return disallowedGlobal1++; }();
|
|
static inline double allowedGlobal4 = init_dynamic(2);
|
|
|
|
// OK, because immutable and compile-time-initialized
|
|
constexpr int allowedGlobal5 = 0;
|
|
const float allowedGlobal6 = 1;
|
|
constexpr int allowedGlobal7 = init_constexpr(2);
|
|
const int allowedGlobal8 = init_constexpr(3);
|
|
|
|
// We don't warn on this because non-inline variables can't (legally) appear
|
|
// in more than one TU.
|
|
float allowedGlobal9 = 3.14;
|
|
|
|
// Pointers need to be double-const-qualified
|
|
inline float& nonConstReference = disallowedGlobal1; // hidden-warning {{'nonConstReference' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'nonConstReference' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
const inline int& constReference = allowedGlobal5;
|
|
|
|
inline int* nonConstPointerToNonConst = nullptr; // hidden-warning {{'nonConstPointerToNonConst' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'nonConstPointerToNonConst' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
inline int const* nonConstPointerToConst = nullptr; // hidden-warning {{'nonConstPointerToConst' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'nonConstPointerToConst' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
inline int* const constPointerToNonConst = nullptr; // hidden-warning {{'constPointerToNonConst' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'constPointerToNonConst' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
inline int const* const constPointerToConst = nullptr;
|
|
// Don't warn on new because it tends to generate false positives
|
|
inline int const* const constPointerToConstNew = new int(7);
|
|
|
|
inline int const * const * const * const nestedConstPointer = nullptr;
|
|
inline int const * const ** const * const nestedNonConstPointer = nullptr; // hidden-warning {{'nestedNonConstPointer' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'nestedNonConstPointer' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
|
|
struct Test {
|
|
static inline float disallowedStaticMember1; // hidden-warning {{'disallowedStaticMember1' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}
|
|
// windows-warning@-1 {{'disallowedStaticMember1' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
// Defined below, in the header file
|
|
static float disallowedStaticMember2;
|
|
// Defined in the cpp file, so won't get duplicated
|
|
static float allowedStaticMember1;
|
|
|
|
// Always visible
|
|
VISIBLE static inline float allowedStaticMember2 = 0.0;
|
|
};
|
|
|
|
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}}
|
|
// windows-warning@-1 {{'disallowedStaticMember2' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}
|
|
|
|
// This is always visible, so nothing inside it will get duplicated
|
|
struct VISIBLE NeverHidden {
|
|
static inline float allowedStaticMember3;
|
|
static float allowedStaticMember4;
|
|
};
|
|
|
|
inline float NeverHidden::allowedStaticMember4 = 3.4;
|
|
} // namespace GlobalTest
|
|
|
|
/******************************************************************************
|
|
* Case three: Inside templates
|
|
******************************************************************************/
|
|
|
|
namespace TemplateTest {
|
|
|
|
// We never warn inside templates because it's usually infeasible to actually
|
|
// fix the warning.
|
|
|
|
template <typename T>
|
|
int allowedTemplate1 = 0;
|
|
|
|
template int allowedTemplate1<int>;
|
|
|
|
template <typename T>
|
|
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;
|
|
}
|
|
};
|
|
};
|
|
|
|
} |