1 // RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-variable-declarations -std=c++17 %s
2 
3 // Variable declarations that should trigger a warning.
4 int vbad1; // expected-warning{{no previous extern declaration for non-static variable 'vbad1'}}
5 // expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}}
6 
7 int vbad2 = 10; // expected-warning{{no previous extern declaration for non-static variable 'vbad2'}}
8 // expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}}
9 
10 namespace x {
11   int vbad3; // expected-warning{{no previous extern declaration for non-static variable 'vbad3'}}
12   // expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}}
13 }
14 
15 // Variable declarations that should not trigger a warning.
16 static int vgood1;
17 extern int vgood2;
18 int vgood2;
19 static struct {
20   int mgood1;
21 } vgood3;
22 
23 // Functions should never trigger a warning.
24 void fgood1(void);
fgood2(void)25 void fgood2(void) {
26   int lgood1;
27   static int lgood2;
28 }
fgood3(void)29 static void fgood3(void) {
30   int lgood3;
31   static int lgood4;
32 }
33 
34 // Structures, namespaces and classes should be unaffected.
35 struct sgood1 {
36   int mgood2;
37 };
38 struct {
39   int mgood3;
40 } sgood2;
41 class CGood1 {
42   static int MGood1;
43 };
44 int CGood1::MGood1;
45 namespace {
46   int mgood4;
47 }
48 
49 class C {
test()50   void test() {
51     static int x = 0; // no-warn
52   }
53 };
54 
55 // There is also no need to use static in anonymous namespaces.
56 namespace {
57   int vgood4;
58 }
59 
60 inline int inline_var = 0;
61 const int const_var = 0;
62 constexpr int constexpr_var = 0;
63 inline constexpr int inline_constexpr_var = 0;
64 extern const int extern_const_var = 0; // expected-warning {{no previous extern declaration}}
65 // expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}}
66 extern constexpr int extern_constexpr_var = 0; // expected-warning {{no previous extern declaration}}
67 // expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}}
68 
69 template<typename> int var_template = 0;
70 template<typename> constexpr int const_var_template = 0;
71 template<typename> static int static_var_template = 0;
72 
73 template int var_template<int[1]>;
use_var_template()74 int use_var_template() { return var_template<int[2]>; }
75 template int var_template<int[3]>;
76 extern template int var_template<int[4]>;
77 template<> int var_template<int[5]>; // expected-warning {{no previous extern declaration}}
78 // expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}}
79 
80 // FIXME: We give this specialization internal linkage rather than inheriting
81 // the linkage from the template! We should not warn here.
82 template<> int static_var_template<int[5]>; // expected-warning {{no previous extern declaration}}
83 // expected-note@-1{{declare 'static' if the variable is not intended to be used outside of this translation unit}}
84