xref: /llvm-project/clang/test/Analysis/ctu-main.cpp (revision 56b9b97c1ef594f218eb06d2e62daa85cc238500)
1 // RUN: rm -rf %t && mkdir %t
2 // RUN: mkdir -p %t/ctudir
3 // RUN: %clang_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
4 // RUN:   -emit-pch -o %t/ctudir/ctu-other.cpp.ast %S/Inputs/ctu-other.cpp
5 // RUN: %clang_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
6 // RUN:   -emit-pch -o %t/ctudir/ctu-chain.cpp.ast %S/Inputs/ctu-chain.cpp
7 // RUN: cp %S/Inputs/ctu-other.cpp.externalDefMap.ast-dump.txt %t/ctudir/externalDefMap.txt
8 
9 // RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
10 // RUN:   -analyzer-checker=core,debug.ExprInspection \
11 // RUN:   -analyzer-config eagerly-assume=false \
12 // RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
13 // RUN:   -analyzer-config ctu-dir=%t/ctudir \
14 // RUN:   -analyzer-config ctu-phase1-inlining=none \
15 // RUN:   -verify=newctu %s
16 
17 // Simulate the behavior of the previous CTU implementation by inlining all
18 // functions during the first phase. This way, the second phase is a noop.
19 // RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
20 // RUN:   -analyzer-checker=core,debug.ExprInspection \
21 // RUN:   -analyzer-config eagerly-assume=false \
22 // RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
23 // RUN:   -analyzer-config ctu-dir=%t/ctudir \
24 // RUN:   -analyzer-config ctu-phase1-inlining=all \
25 // RUN:   -verify=oldctu %s
26 
27 // RUN: %clang_analyze_cc1 -std=c++14 -triple x86_64-pc-linux-gnu \
28 // RUN:   -analyzer-checker=core,debug.ExprInspection \
29 // RUN:   -analyzer-config experimental-enable-naive-ctu-analysis=true \
30 // RUN:   -analyzer-config ctu-dir=%t/ctudir \
31 // RUN:   -analyzer-config display-ctu-progress=true 2>&1 %s | FileCheck %s
32 
33 // CHECK: CTU loaded AST file: {{.*}}ctu-other.cpp.ast
34 // CHECK: CTU loaded AST file: {{.*}}ctu-chain.cpp.ast
35 
36 #include "ctu-hdr.h"
37 
38 void clang_analyzer_eval(int);
39 
40 int f(int);
41 int g(int);
42 int h(int);
43 
callback_to_main(int x)44 int callback_to_main(int x) { return x + 1; }
45 
46 namespace myns {
47 int fns(int x);
48 
49 namespace embed_ns {
50 int fens(int x);
51 }
52 
53 class embed_cls {
54 public:
55   int fecl(int x);
56 };
57 }
58 
59 class mycls {
60 public:
61   int fcl(int x);
62   virtual int fvcl(int x);
63   static int fscl(int x);
64 
65   class embed_cls2 {
66   public:
67     int fecl2(int x);
68   };
69 };
70 
71 class derived : public mycls {
72 public:
73   virtual int fvcl(int x) override;
74 };
75 
76 namespace chns {
77 int chf1(int x);
78 }
79 
80 int fun_using_anon_struct(int);
81 int other_macro_diag(int);
82 
83 extern const int extInt;
84 namespace intns {
85 extern const int extInt;
86 }
87 struct S {
88   int a;
89 };
90 extern const S extS;
91 extern S extNonConstS;
92 struct NonTrivialS {
93   int a;
94   // User declaring a dtor makes it non-trivial.
95   ~NonTrivialS();
96 };
97 extern const NonTrivialS extNTS;
98 extern const int extHere;
99 const int extHere = 6;
100 struct A {
101   static const int a;
102 };
103 struct SC {
104   const int a;
105 };
106 extern const SC extSC;
107 struct ST {
108   static const struct SC sc;
109 };
110 struct SCNest {
111   struct SCN {
112     const int a;
113   } scn;
114 };
115 extern SCNest extSCN;
116 extern const SCNest::SCN extSubSCN;
117 struct SCC {
118   SCC(int c);
119   const int a;
120 };
121 extern SCC extSCC;
122 union U {
123   const int a;
124   const unsigned int b;
125 };
126 extern const U extU;
127 
test_virtual_functions(mycls * obj)128 void test_virtual_functions(mycls* obj) {
129   // The dynamic type is known.
130   clang_analyzer_eval(mycls().fvcl(1) == 8);   // newctu-warning{{TRUE}} ctu
131                                                // newctu-warning@-1{{UNKNOWN}} stu
132                                                // oldctu-warning@-2{{TRUE}}
133   clang_analyzer_eval(derived().fvcl(1) == 9); // newctu-warning{{TRUE}} ctu
134                                                // newctu-warning@-1{{UNKNOWN}} stu
135                                                // oldctu-warning@-2{{TRUE}}
136   // We cannot decide about the dynamic type.
137   clang_analyzer_eval(obj->fvcl(1) == 8);      // newctu-warning{{TRUE}} ctu
138                                                // newctu-warning@-1{{UNKNOWN}} ctu, stu
139                                                // oldctu-warning@-2{{TRUE}}
140                                                // oldctu-warning@-3{{UNKNOWN}}
141 }
142 
143 class TestAnonUnionUSR {
144 public:
f(int value)145   inline float f(int value) {
146     union {
147       float f;
148       int i;
149     };
150     i = value;
151     return f;
152   }
153   static const int Test;
154 };
155 
156 extern int testImportOfIncompleteDefaultParmDuringImport(int);
157 
158 extern int testImportOfDelegateConstructor(int);
159 
main()160 int main() {
161   clang_analyzer_eval(f(3) == 2); // newctu-warning{{TRUE}} ctu
162                                   // newctu-warning@-1{{UNKNOWN}} stu
163                                   // oldctu-warning@-2{{TRUE}}
164   clang_analyzer_eval(f(4) == 3); // newctu-warning{{TRUE}} ctu
165                                   // newctu-warning@-1{{UNKNOWN}} stu
166                                   // oldctu-warning@-2{{TRUE}}
167   clang_analyzer_eval(f(5) == 3); // newctu-warning{{FALSE}} ctu
168                                   // newctu-warning@-1{{UNKNOWN}} stu
169                                   // oldctu-warning@-2{{FALSE}}
170   clang_analyzer_eval(g(4) == 6); // newctu-warning{{TRUE}} ctu
171                                   // newctu-warning@-1{{UNKNOWN}} stu
172                                   // oldctu-warning@-2{{TRUE}}
173   clang_analyzer_eval(h(2) == 8); // newctu-warning{{TRUE}} ctu
174                                   // newctu-warning@-1{{UNKNOWN}} stu
175                                   // oldctu-warning@-2{{TRUE}}
176 
177   clang_analyzer_eval(myns::fns(2) == 9);                   // newctu-warning{{TRUE}} ctu
178                                                             // newctu-warning@-1{{UNKNOWN}} stu
179                                                             // oldctu-warning@-2{{TRUE}}
180   clang_analyzer_eval(myns::embed_ns::fens(2) == -1);       // newctu-warning{{TRUE}} ctu
181                                                             // newctu-warning@-1{{UNKNOWN}} stu
182                                                             // oldctu-warning@-2{{TRUE}}
183   clang_analyzer_eval(mycls().fcl(1) == 6);                 // newctu-warning{{TRUE}} ctu
184                                                             // newctu-warning@-1{{UNKNOWN}} stu
185                                                             // oldctu-warning@-2{{TRUE}}
186   clang_analyzer_eval(mycls::fscl(1) == 7);                 // newctu-warning{{TRUE}} ctu
187                                                             // newctu-warning@-1{{UNKNOWN}} stu
188                                                             // oldctu-warning@-2{{TRUE}}
189   clang_analyzer_eval(myns::embed_cls().fecl(1) == -6);     // newctu-warning{{TRUE}} ctu
190                                                             // newctu-warning@-1{{UNKNOWN}} stu
191                                                             // oldctu-warning@-2{{TRUE}}
192   clang_analyzer_eval(mycls::embed_cls2().fecl2(0) == -11); // newctu-warning{{TRUE}} ctu
193                                                             // newctu-warning@-1{{UNKNOWN}} stu
194                                                             // oldctu-warning@-2{{TRUE}}
195 
196   clang_analyzer_eval(chns::chf1(4) == 12); // newctu-warning{{TRUE}} ctu
197                                             // newctu-warning@-1{{UNKNOWN}} stu
198                                             // oldctu-warning@-2{{TRUE}}
199   clang_analyzer_eval(fun_using_anon_struct(8) == 8); // newctu-warning{{TRUE}} ctu
200                                                       // newctu-warning@-1{{UNKNOWN}} stu
201                                                       // oldctu-warning@-2{{TRUE}}
202 
203   clang_analyzer_eval(other_macro_diag(1) == 1); // newctu-warning{{TRUE}} ctu
204                                                  // newctu-warning@-1{{UNKNOWN}} stu
205                                                  // oldctu-warning@-2{{TRUE}}
206   // newctu-warning@Inputs/ctu-other.cpp:93{{REACHABLE}}
207   // oldctu-warning@Inputs/ctu-other.cpp:93{{REACHABLE}}
208   MACRODIAG(); // newctu-warning{{REACHABLE}}
209                // oldctu-warning@-1{{REACHABLE}}
210 
211   // FIXME we should report an UNKNOWN as well for all external variables!
212   clang_analyzer_eval(extInt == 2); // newctu-warning{{TRUE}}
213                                     // oldctu-warning@-1{{TRUE}}
214   clang_analyzer_eval(intns::extInt == 3); // newctu-warning{{TRUE}}
215                                            // oldctu-warning@-1{{TRUE}}
216   clang_analyzer_eval(extS.a == 4); // newctu-warning{{TRUE}}
217                                     // oldctu-warning@-1{{TRUE}}
218   clang_analyzer_eval(extNonConstS.a == 4); // newctu-warning{{UNKNOWN}}
219                                             // oldctu-warning@-1{{UNKNOWN}}
220   // Do not import non-trivial classes' initializers.
221   clang_analyzer_eval(extNTS.a == 4); // newctu-warning{{UNKNOWN}}
222                                       // oldctu-warning@-1{{UNKNOWN}}
223   clang_analyzer_eval(extHere == 6); // newctu-warning{{TRUE}}
224                                      // oldctu-warning@-1{{TRUE}}
225   clang_analyzer_eval(A::a == 3); // newctu-warning{{TRUE}}
226                                   // oldctu-warning@-1{{TRUE}}
227   clang_analyzer_eval(extSC.a == 8); // newctu-warning{{TRUE}}
228                                      // oldctu-warning@-1{{TRUE}}
229   clang_analyzer_eval(ST::sc.a == 2); // newctu-warning{{TRUE}}
230                                       // oldctu-warning@-1{{TRUE}}
231   // clang_analyzer_eval(extSCN.scn.a == 9); // TODO
232   clang_analyzer_eval(extSubSCN.a == 1); // newctu-warning{{TRUE}}
233                                          // oldctu-warning@-1{{TRUE}}
234   // clang_analyzer_eval(extSCC.a == 7); // TODO
235   clang_analyzer_eval(extU.a == 4); // newctu-warning{{TRUE}}
236                                     // oldctu-warning@-1{{TRUE}}
237   clang_analyzer_eval(TestAnonUnionUSR::Test == 5); // newctu-warning{{TRUE}}
238                                                     // oldctu-warning@-1{{TRUE}}
239 
240   clang_analyzer_eval(testImportOfIncompleteDefaultParmDuringImport(9) == 9);
241   // newctu-warning@-1{{TRUE}} ctu
242   // newctu-warning@-2{{UNKNOWN}} stu
243   // oldctu-warning@-3{{TRUE}}
244 
245   clang_analyzer_eval(testImportOfDelegateConstructor(10) == 10);
246   // newctu-warning@-1{{TRUE}} ctu
247   // newctu-warning@-2{{UNKNOWN}} stu
248   // oldctu-warning@-3{{TRUE}}
249 }
250