1 | // RUN: %check_clang_tidy %s cppcoreguidelines-interfaces-global-init %t |
2 | |
3 | constexpr int makesInt() { return 3; } |
4 | constexpr int takesInt(int i) { return i + 1; } |
5 | constexpr 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(i: 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(i: &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(i: 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(i: 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(i: 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 | |
45 | void f() { |
46 | // This is fine, it's executed after dynamic initialization occurs. |
47 | static int G = takesInt(i: 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(i: GlobalScope); |
60 | static int GlobalScope2 = takesInt(i: ns::NamespaceScope); |
61 | // Enums are fine. |
62 | enum Enum { kEnumValue = 1 }; |
63 | static int = takesInt(i: kEnumValue); |
64 | |
65 | // Leave constexprs alone. |
66 | extern constexpr int GlobalScopeConstexpr = makesInt(); |
67 | static constexpr int GlobalScopeConstexprOk = |
68 | takesInt(i: 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" ; |
73 | constexpr int Fingerprint(const char *value) { return 0; } |
74 | static int kFingerprint = Fingerprint(value: 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 | |