1 // RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t 2 makesInt()3constexpr int makesInt() { return 3; } takesInt(int i)4constexpr int takesInt(int i) { return i + 1; } takesIntPtr(int * i)5constexpr int takesIntPtr(int *i) { return *i; } 6 7 extern int ExternGlobal; 8 static int GlobalScopeBadInit1 = ExternGlobal; 9 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' 10 static int GlobalScopeBadInit2 = takesInt(ExternGlobal); 11 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' 12 static int GlobalScopeBadInit3 = takesIntPtr(&ExternGlobal); 13 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' 14 static int GlobalScopeBadInit4 = 3 * (ExternGlobal + 2); 15 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' 16 17 namespace ns { 18 static int NamespaceScope = makesInt(); 19 static int NamespaceScopeBadInit = takesInt(ExternGlobal); 20 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' 21 22 struct A { 23 static int ClassScope; 24 static int ClassScopeBadInit; 25 }; 26 27 int A::ClassScopeBadInit = takesInt(ExternGlobal); 28 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ExternGlobal' 29 30 static int FromClassBadInit = takesInt(A::ClassScope); 31 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'ClassScope' 32 } // namespace ns 33 34 // "const int B::I;" is fine, it just ODR-defines B::I. See [9.4.3] Static 35 // members [class.static]. However the ODR-definitions are not in the right 36 // order (C::I after C::J, see [3.6.2.3]). 37 class B1 { 38 static const int I = 0; 39 static const int J = I; 40 }; 41 const int B1::J; 42 // CHECK-MESSAGES: [[@LINE-1]]:15: warning: initializing non-local variable with non-const expression depending on uninitialized non-local variable 'I' 43 const int B1::I; 44 f()45void f() { 46 // This is fine, it's executed after dynamic initialization occurs. 47 static int G = takesInt(ExternGlobal); 48 } 49 50 // Declaration then definition then usage is fine. 51 extern int ExternGlobal2; 52 extern int ExternGlobal2; 53 int ExternGlobal2 = 123; 54 static int GlobalScopeGoodInit1 = ExternGlobal2; 55 56 57 // Defined global variables are fine: 58 static int GlobalScope = makesInt(); 59 static int GlobalScopeGoodInit2 = takesInt(GlobalScope); 60 static int GlobalScope2 = takesInt(ns::NamespaceScope); 61 // Enums are fine. 62 enum Enum { kEnumValue = 1 }; 63 static int GlobalScopeFromEnum = takesInt(kEnumValue); 64 65 // Leave constexprs alone. 66 extern constexpr int GlobalScopeConstexpr = makesInt(); 67 static constexpr int GlobalScopeConstexprOk = 68 takesInt(GlobalScopeConstexpr); 69 70 // This is a pretty common instance: People are usually not using constexpr, but 71 // this is what they should write: 72 static constexpr const char kValue[] = "value"; Fingerprint(const char * value)73constexpr int Fingerprint(const char *value) { return 0; } 74 static int kFingerprint = Fingerprint(kValue); 75 76 // This is fine because the ODR-definitions are in the right order (C::J after 77 // C::I). 78 class B2 { 79 static const int I = 0; 80 static const int J = I; 81 }; 82 const int B2::I; 83 const int B2::J; 84 85