brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.5 KiB · a5da767 Raw
250 lines · c
1/**2 * This file contains tests for the -Wunique_object_duplication warning.3 * See the warning's documentation for more information.4 */5 6#ifdef WINDOWS_TEST7#define HIDDEN8// dllimport also suffices for visibility, but those can't have definitions9#define VISIBLE __declspec(dllexport)10#else11#define HIDDEN __attribute__((visibility("hidden")))12#define VISIBLE __attribute__((visibility("default")))13#endif14 15// Helper functions16constexpr int init_constexpr(int x) { return x; };17extern double init_dynamic(int);18 19/******************************************************************************20 * Case one: Static local variables in an externally-visible function21 ******************************************************************************/22namespace StaticLocalTest {23 24inline void has_static_locals_external() {25  // Mutable26  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}}27                                    // windows-warning@-1 {{'disallowedStatic1' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}28  // Initialization might run more than once29  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}}30                                                               // windows-warning@-1 {{initialization of 'disallowedStatic2' may run twice when built into a shared library: it has external linkage and no import/export annotation}}31  // OK, because immutable and compile-time-initialized32  static constexpr int allowedStatic1 = 0;33  static const float allowedStatic2 = 1;34  static constexpr int allowedStatic3 = init_constexpr(2);35  static const int allowedStatic4 = init_constexpr(3);36}37 38// Don't warn for non-inline functions, since they can't (legally) appear39// in more than one TU in the first place.40void has_static_locals_non_inline() {41  // Mutable42  static int allowedStatic1 = 0;43  // Initialization might run more than once44  static const double allowedStatic2 = allowedStatic1++;45}46 47// Everything in this function is OK because the function is TU-local48static void has_static_locals_internal() {49  static int allowedStatic1 = 0;50  static double allowedStatic2 = init_dynamic(2);51  static char allowedStatic3 = []() { return allowedStatic1++; }();52  static constexpr int allowedStatic4 = 0;53}54 55namespace {56 57// Everything in this function is OK because the function is also TU-local58void has_static_locals_anon() {59  static int allowedStatic1 = 0;60  static double allowedStatic2 = init_dynamic(2);61  static char allowedStatic3 = []() { return allowedStatic1++; }();62  static constexpr int allowedStatic4 = init_constexpr(3);63}64 65} // Anonymous namespace66 67HIDDEN inline void static_local_always_hidden() {68    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}}69                                      // expected-warning@-1 {{'disallowedStatic1' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}70                                      // windows-warning@-2 {{'disallowedStatic1' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}71    {72      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}}73                                        // expected-warning@-1 {{'disallowedStatic2' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}74                                        // windows-warning@-2 {{'disallowedStatic2' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}75    }76 77    auto lmb = []() {78      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}}79                                        // expected-warning@-1 {{'disallowedStatic3' may be duplicated when built into a shared library: it is mutable, with external linkage and hidden visibility}}80                                        // windows-warning@-2 {{'disallowedStatic3' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}81    };82}83 84// Always visible85VISIBLE void static_local_never_hidden() {86    static int allowedStatic1 = 3;87 88    {89      static int allowedStatic2 = 3;90    }91 92    auto lmb = []() {93      static int allowedStatic3 = 3;94    };95}96 97// Don't warn on this because it's not in a function98const int setByLambda = ([]() { static int x = 3; return x++; })();99 100inline void has_extern_local() {101  extern int allowedAddressExtern; // Not a definition102}103 104inline void has_regular_local() {105  int allowedAddressLocal = 0;106}107 108inline void has_thread_local() {109  // thread_local variables are static by default110  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}}111                                              // windows-warning@-1 {{'disallowedThreadLocal' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}112}113 114// Functions themselves are always immutable, so referencing them is okay115inline auto& allowedFunctionReference = has_static_locals_external;116 117} // namespace StaticLocalTest118 119/******************************************************************************120 * Case two: Globals with external linkage121 ******************************************************************************/122namespace GlobalTest {123  // Mutable124  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}}125                                         // windows-warning@-1 {{'disallowedGlobal1' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}126 127 128  // Initialization might run more than once129  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}}130                                                               // windows-warning@-1 {{initialization of 'disallowedGlobal5' may run twice when built into a shared library: it has external linkage and no import/export annotation}}131  // OK because internal linkage, so duplication is intended132  static float allowedGlobal1 = 3.14;133  const double allowedGlobal2 = init_dynamic(2);134  static const char allowedGlobal3 = []() { return disallowedGlobal1++; }();135  static inline double allowedGlobal4 = init_dynamic(2);136 137  // OK, because immutable and compile-time-initialized138  constexpr int allowedGlobal5 = 0;139  const float allowedGlobal6 = 1;140  constexpr int allowedGlobal7 = init_constexpr(2);141  const int allowedGlobal8 = init_constexpr(3);142 143  // We don't warn on this because non-inline variables can't (legally) appear144  // in more than one TU.145  float allowedGlobal9 = 3.14;146 147  // Pointers need to be double-const-qualified148  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}}149                                                       // windows-warning@-1 {{'nonConstReference' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}150  const inline int& constReference = allowedGlobal5;151 152  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}}153                                                   // windows-warning@-1 {{'nonConstPointerToNonConst' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}154  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}}155                                                      // windows-warning@-1 {{'nonConstPointerToConst' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}156  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}}157                                                      // windows-warning@-1 {{'constPointerToNonConst' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}158  inline int const* const constPointerToConst = nullptr;159  // Don't warn on new because it tends to generate false positives160  inline int const* const constPointerToConstNew = new int(7);161 162  inline int const * const * const * const nestedConstPointer = nullptr;163  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}}164                                                                             // windows-warning@-1 {{'nestedNonConstPointer' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}165 166  struct Test {167    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}}168                                                 // windows-warning@-1 {{'disallowedStaticMember1' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}169    // Defined below, in the header file170    static float disallowedStaticMember2;171    // Defined in the cpp file, so won't get duplicated172    static float allowedStaticMember1;173 174    // Always visible175    VISIBLE static inline float allowedStaticMember2 = 0.0;176  };177 178  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}}179                                                    // windows-warning@-1 {{'disallowedStaticMember2' may be duplicated when built into a shared library: it is mutable, with external linkage and no import/export annotation}}180 181  // This is always visible, so nothing inside it will get duplicated182  struct VISIBLE NeverHidden {183    static inline float allowedStaticMember3;184    static float allowedStaticMember4;185  };186 187  inline float NeverHidden::allowedStaticMember4 = 3.4;188} // namespace GlobalTest189 190/******************************************************************************191 * Case three: Inside templates192 ******************************************************************************/193 194namespace TemplateTest {195 196// We never warn inside templates because it's usually infeasible to actually197// fix the warning.198 199template <typename T>200int allowedTemplate1 = 0;201 202template int allowedTemplate1<int>;203 204template <typename T>205inline int allowedTemplate2 = 0;206 207template int allowedTemplate2<int>;208 209} // namespace TemplateTest210 211/******************************************************************************212 * Case four: Nested classes213 ******************************************************************************/214 215namespace NestedClassTest {216// Unlike visibility, declexport annotations do not propagate down to nested217// classes. Hence on windows, we only avoid duplication of class members if218// their immediate containing class is annotated. On posix, we get avoid219// duplication if any containing class is annotated.220 221class VISIBLE Outer {222  // Visible because their class is exported223  inline static int allowedOuterMember = 0;224  int* allowedOuterFunction() {225    static int allowed = 0;226    return &allowed;227  }228 229  // No annotation, and visibility is only propagated on posix.230  class HiddenOnWindows {231    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}}232 233 234    int* disallowedInnerFunction() {235      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}}236      return &disallowed;237    }238  };239 240  class VISIBLE AlwaysVisible {241    inline static int allowedInnerMember = 0;242 243    int* allowedInnerFunction() {244      static int allowed = 0;245      return &allowed;246    }247  };248};249 250}