1 //===- unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp ------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "CheckerRegistration.h"
10 #include "clang/Frontend/CompilerInstance.h"
11 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
12 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
13 #include "clang/StaticAnalyzer/Core/Checker.h"
14 #include "clang/StaticAnalyzer/Core/CheckerRegistryData.h"
15 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
17 #include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"
18 #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"
19 #include "clang/Tooling/Tooling.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "gtest/gtest.h"
22 #include <memory>
23
24 namespace clang {
25 namespace ento {
26 namespace {
27
28 //===----------------------------------------------------------------------===//
29 // Just a minimal test for how checker registration works with statically
30 // linked, non TableGen generated checkers.
31 //===----------------------------------------------------------------------===//
32
33 class CustomChecker : public Checker<check::ASTCodeBody> {
34 public:
checkASTCodeBody(const Decl * D,AnalysisManager & Mgr,BugReporter & BR) const35 void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
36 BugReporter &BR) const {
37 BR.EmitBasicReport(D, this, "Custom diagnostic", categories::LogicError,
38 "Custom diagnostic description",
39 PathDiagnosticLocation(D, Mgr.getSourceManager()), {});
40 }
41 };
42
addCustomChecker(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)43 void addCustomChecker(AnalysisASTConsumer &AnalysisConsumer,
44 AnalyzerOptions &AnOpts) {
45 AnOpts.CheckersAndPackages = {{"test.CustomChecker", true}};
46 AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
47 Registry.addChecker<CustomChecker>("test.CustomChecker", "Description", "");
48 });
49 }
50
TEST(RegisterCustomCheckers,RegisterChecker)51 TEST(RegisterCustomCheckers, RegisterChecker) {
52 std::string Diags;
53 EXPECT_TRUE(runCheckerOnCode<addCustomChecker>("void f() {;}", Diags));
54 EXPECT_EQ(Diags, "test.CustomChecker: Custom diagnostic description\n");
55 }
56
57 //===----------------------------------------------------------------------===//
58 // Pretty much the same.
59 //===----------------------------------------------------------------------===//
60
61 class LocIncDecChecker : public Checker<check::Location> {
62 public:
checkLocation(SVal Loc,bool IsLoad,const Stmt * S,CheckerContext & C) const63 void checkLocation(SVal Loc, bool IsLoad, const Stmt *S,
64 CheckerContext &C) const {
65 const auto *UnaryOp = dyn_cast<UnaryOperator>(S);
66 if (UnaryOp && !IsLoad) {
67 EXPECT_FALSE(UnaryOp->isIncrementOp());
68 }
69 }
70 };
71
addLocIncDecChecker(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)72 void addLocIncDecChecker(AnalysisASTConsumer &AnalysisConsumer,
73 AnalyzerOptions &AnOpts) {
74 AnOpts.CheckersAndPackages = {{"test.LocIncDecChecker", true}};
75 AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
76 Registry.addChecker<CustomChecker>("test.LocIncDecChecker", "Description",
77 "");
78 });
79 }
80
TEST(RegisterCustomCheckers,CheckLocationIncDec)81 TEST(RegisterCustomCheckers, CheckLocationIncDec) {
82 EXPECT_TRUE(
83 runCheckerOnCode<addLocIncDecChecker>("void f() { int *p; (*p)++; }"));
84 }
85
86 //===----------------------------------------------------------------------===//
87 // Unsatisfied checker dependency
88 //===----------------------------------------------------------------------===//
89
90 class CheckerRegistrationOrderPrinter
91 : public Checker<check::PreStmt<DeclStmt>> {
92 std::unique_ptr<BuiltinBug> BT =
93 std::make_unique<BuiltinBug>(this, "Registration order");
94
95 public:
checkPreStmt(const DeclStmt * DS,CheckerContext & C) const96 void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
97 ExplodedNode *N = nullptr;
98 N = C.generateErrorNode();
99 llvm::SmallString<200> Buf;
100 llvm::raw_svector_ostream OS(Buf);
101 C.getAnalysisManager()
102 .getCheckerManager()
103 ->getCheckerRegistryData()
104 .printEnabledCheckerList(OS);
105 // Strip a newline off.
106 auto R =
107 std::make_unique<PathSensitiveBugReport>(*BT, OS.str().drop_back(1), N);
108 C.emitReport(std::move(R));
109 }
110 };
111
registerCheckerRegistrationOrderPrinter(CheckerManager & mgr)112 void registerCheckerRegistrationOrderPrinter(CheckerManager &mgr) {
113 mgr.registerChecker<CheckerRegistrationOrderPrinter>();
114 }
115
shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager & mgr)116 bool shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager &mgr) {
117 return true;
118 }
119
addCheckerRegistrationOrderPrinter(CheckerRegistry & Registry)120 void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) {
121 Registry.addChecker(registerCheckerRegistrationOrderPrinter,
122 shouldRegisterCheckerRegistrationOrderPrinter,
123 "test.RegistrationOrder", "Description", "", false);
124 }
125
126 #define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG) \
127 class CHECKER_NAME : public Checker<check::PreStmt<DeclStmt>> { \
128 std::unique_ptr<BuiltinBug> BT = \
129 std::make_unique<BuiltinBug>(this, DIAG_MSG); \
130 \
131 public: \
132 void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {} \
133 }; \
134 \
135 void register##CHECKER_NAME(CheckerManager &mgr) { \
136 mgr.registerChecker<CHECKER_NAME>(); \
137 } \
138 \
139 bool shouldRegister##CHECKER_NAME(const CheckerManager &mgr) { \
140 return true; \
141 } \
142 void add##CHECKER_NAME(CheckerRegistry &Registry) { \
143 Registry.addChecker(register##CHECKER_NAME, shouldRegister##CHECKER_NAME, \
144 "test." #CHECKER_NAME, "Description", "", false); \
145 }
146
147 UNITTEST_CHECKER(StrongDep, "Strong")
148 UNITTEST_CHECKER(Dep, "Dep")
149
shouldRegisterStrongFALSE(const CheckerManager & mgr)150 bool shouldRegisterStrongFALSE(const CheckerManager &mgr) {
151 return false;
152 }
153
154
addDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)155 void addDep(AnalysisASTConsumer &AnalysisConsumer,
156 AnalyzerOptions &AnOpts) {
157 AnOpts.CheckersAndPackages = {{"test.Dep", true},
158 {"test.RegistrationOrder", true}};
159 AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {
160 Registry.addChecker(registerStrongDep, shouldRegisterStrongFALSE,
161 "test.Strong", "Description", "", false);
162 addStrongDep(Registry);
163 addDep(Registry);
164 addCheckerRegistrationOrderPrinter(Registry);
165 Registry.addDependency("test.Dep", "test.Strong");
166 });
167 }
168
TEST(RegisterDeps,UnsatisfiedDependency)169 TEST(RegisterDeps, UnsatisfiedDependency) {
170 std::string Diags;
171 EXPECT_TRUE(runCheckerOnCode<addDep>("void f() {int i;}", Diags));
172 EXPECT_EQ(Diags, "test.RegistrationOrder: test.RegistrationOrder\n");
173 }
174
175 //===----------------------------------------------------------------------===//
176 // Weak checker dependencies.
177 //===----------------------------------------------------------------------===//
178
179 UNITTEST_CHECKER(WeakDep, "Weak")
180
addWeakDepCheckerBothEnabled(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)181 void addWeakDepCheckerBothEnabled(AnalysisASTConsumer &AnalysisConsumer,
182 AnalyzerOptions &AnOpts) {
183 AnOpts.CheckersAndPackages = {{"test.Dep", true},
184 {"test.WeakDep", true},
185 {"test.RegistrationOrder", true}};
186 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
187 addWeakDep(Registry);
188 addDep(Registry);
189 addCheckerRegistrationOrderPrinter(Registry);
190 Registry.addWeakDependency("test.Dep", "test.WeakDep");
191 });
192 }
193
addWeakDepCheckerBothEnabledSwitched(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)194 void addWeakDepCheckerBothEnabledSwitched(AnalysisASTConsumer &AnalysisConsumer,
195 AnalyzerOptions &AnOpts) {
196 AnOpts.CheckersAndPackages = {{"test.Dep", true},
197 {"test.WeakDep", true},
198 {"test.RegistrationOrder", true}};
199 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
200 addWeakDep(Registry);
201 addDep(Registry);
202 addCheckerRegistrationOrderPrinter(Registry);
203 Registry.addWeakDependency("test.WeakDep", "test.Dep");
204 });
205 }
206
addWeakDepCheckerDepDisabled(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)207 void addWeakDepCheckerDepDisabled(AnalysisASTConsumer &AnalysisConsumer,
208 AnalyzerOptions &AnOpts) {
209 AnOpts.CheckersAndPackages = {{"test.Dep", true},
210 {"test.WeakDep", false},
211 {"test.RegistrationOrder", true}};
212 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
213 addWeakDep(Registry);
214 addDep(Registry);
215 addCheckerRegistrationOrderPrinter(Registry);
216 Registry.addWeakDependency("test.Dep", "test.WeakDep");
217 });
218 }
219
addWeakDepCheckerDepUnspecified(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)220 void addWeakDepCheckerDepUnspecified(AnalysisASTConsumer &AnalysisConsumer,
221 AnalyzerOptions &AnOpts) {
222 AnOpts.CheckersAndPackages = {{"test.Dep", true},
223 {"test.RegistrationOrder", true}};
224 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
225 addWeakDep(Registry);
226 addDep(Registry);
227 addCheckerRegistrationOrderPrinter(Registry);
228 Registry.addWeakDependency("test.Dep", "test.WeakDep");
229 });
230 }
231
232 UNITTEST_CHECKER(WeakDep2, "Weak2")
233 UNITTEST_CHECKER(Dep2, "Dep2")
234
addWeakDepHasWeakDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)235 void addWeakDepHasWeakDep(AnalysisASTConsumer &AnalysisConsumer,
236 AnalyzerOptions &AnOpts) {
237 AnOpts.CheckersAndPackages = {{"test.Dep", true},
238 {"test.WeakDep", true},
239 {"test.WeakDep2", true},
240 {"test.RegistrationOrder", true}};
241 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
242 addStrongDep(Registry);
243 addWeakDep(Registry);
244 addWeakDep2(Registry);
245 addDep(Registry);
246 addDep2(Registry);
247 addCheckerRegistrationOrderPrinter(Registry);
248 Registry.addWeakDependency("test.Dep", "test.WeakDep");
249 Registry.addWeakDependency("test.WeakDep", "test.WeakDep2");
250 });
251 }
252
addWeakDepTransitivity(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)253 void addWeakDepTransitivity(AnalysisASTConsumer &AnalysisConsumer,
254 AnalyzerOptions &AnOpts) {
255 AnOpts.CheckersAndPackages = {{"test.Dep", true},
256 {"test.WeakDep", false},
257 {"test.WeakDep2", true},
258 {"test.RegistrationOrder", true}};
259 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
260 addStrongDep(Registry);
261 addWeakDep(Registry);
262 addWeakDep2(Registry);
263 addDep(Registry);
264 addDep2(Registry);
265 addCheckerRegistrationOrderPrinter(Registry);
266 Registry.addWeakDependency("test.Dep", "test.WeakDep");
267 Registry.addWeakDependency("test.WeakDep", "test.WeakDep2");
268 });
269 }
270
TEST(RegisterDeps,SimpleWeakDependency)271 TEST(RegisterDeps, SimpleWeakDependency) {
272 std::string Diags;
273 EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerBothEnabled>(
274 "void f() {int i;}", Diags));
275 EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep\ntest."
276 "Dep\ntest.RegistrationOrder\n");
277 Diags.clear();
278
279 // Mind that AnalyzerOption listed the enabled checker list in the same order,
280 // but the dependencies are switched.
281 EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerBothEnabledSwitched>(
282 "void f() {int i;}", Diags));
283 EXPECT_EQ(Diags, "test.RegistrationOrder: test.Dep\ntest."
284 "RegistrationOrder\ntest.WeakDep\n");
285 Diags.clear();
286
287 // Weak dependencies dont prevent dependent checkers from being enabled.
288 EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerDepDisabled>(
289 "void f() {int i;}", Diags));
290 EXPECT_EQ(Diags,
291 "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
292 Diags.clear();
293
294 // Nor will they be enabled just because a dependent checker is.
295 EXPECT_TRUE(runCheckerOnCode<addWeakDepCheckerDepUnspecified>(
296 "void f() {int i;}", Diags));
297 EXPECT_EQ(Diags,
298 "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
299 Diags.clear();
300
301 EXPECT_TRUE(
302 runCheckerOnCode<addWeakDepTransitivity>("void f() {int i;}", Diags));
303 EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep2\ntest."
304 "Dep\ntest.RegistrationOrder\n");
305 Diags.clear();
306
307 EXPECT_TRUE(
308 runCheckerOnCode<addWeakDepHasWeakDep>("void f() {int i;}", Diags));
309 EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep2\ntest."
310 "WeakDep\ntest.Dep\ntest.RegistrationOrder\n");
311 Diags.clear();
312 }
313
314 //===----------------------------------------------------------------------===//
315 // Interaction of weak and regular checker dependencies.
316 //===----------------------------------------------------------------------===//
317
addWeakDepHasStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)318 void addWeakDepHasStrongDep(AnalysisASTConsumer &AnalysisConsumer,
319 AnalyzerOptions &AnOpts) {
320 AnOpts.CheckersAndPackages = {{"test.Dep", true},
321 {"test.StrongDep", true},
322 {"test.WeakDep", true},
323 {"test.RegistrationOrder", true}};
324 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
325 addStrongDep(Registry);
326 addWeakDep(Registry);
327 addDep(Registry);
328 addCheckerRegistrationOrderPrinter(Registry);
329 Registry.addDependency("test.WeakDep", "test.StrongDep");
330 Registry.addWeakDependency("test.Dep", "test.WeakDep");
331 });
332 }
333
addWeakDepAndStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)334 void addWeakDepAndStrongDep(AnalysisASTConsumer &AnalysisConsumer,
335 AnalyzerOptions &AnOpts) {
336 AnOpts.CheckersAndPackages = {{"test.Dep", true},
337 {"test.StrongDep", true},
338 {"test.WeakDep", true},
339 {"test.RegistrationOrder", true}};
340 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
341 addStrongDep(Registry);
342 addWeakDep(Registry);
343 addDep(Registry);
344 addCheckerRegistrationOrderPrinter(Registry);
345 Registry.addDependency("test.Dep", "test.StrongDep");
346 Registry.addWeakDependency("test.Dep", "test.WeakDep");
347 });
348 }
349
addDisabledWeakDepHasStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)350 void addDisabledWeakDepHasStrongDep(AnalysisASTConsumer &AnalysisConsumer,
351 AnalyzerOptions &AnOpts) {
352 AnOpts.CheckersAndPackages = {{"test.Dep", true},
353 {"test.StrongDep", true},
354 {"test.WeakDep", false},
355 {"test.RegistrationOrder", true}};
356 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
357 addStrongDep(Registry);
358 addWeakDep(Registry);
359 addDep(Registry);
360 addCheckerRegistrationOrderPrinter(Registry);
361 Registry.addDependency("test.WeakDep", "test.StrongDep");
362 Registry.addWeakDependency("test.Dep", "test.WeakDep");
363 });
364 }
365
addDisabledWeakDepHasUnspecifiedStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)366 void addDisabledWeakDepHasUnspecifiedStrongDep(
367 AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) {
368 AnOpts.CheckersAndPackages = {{"test.Dep", true},
369 {"test.WeakDep", false},
370 {"test.RegistrationOrder", true}};
371 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
372 addStrongDep(Registry);
373 addWeakDep(Registry);
374 addDep(Registry);
375 addCheckerRegistrationOrderPrinter(Registry);
376 Registry.addDependency("test.WeakDep", "test.StrongDep");
377 Registry.addWeakDependency("test.Dep", "test.WeakDep");
378 });
379 }
380
addWeakDepHasDisabledStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)381 void addWeakDepHasDisabledStrongDep(AnalysisASTConsumer &AnalysisConsumer,
382 AnalyzerOptions &AnOpts) {
383 AnOpts.CheckersAndPackages = {{"test.Dep", true},
384 {"test.StrongDep", false},
385 {"test.WeakDep", true},
386 {"test.RegistrationOrder", true}};
387 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
388 addStrongDep(Registry);
389 addWeakDep(Registry);
390 addDep(Registry);
391 addCheckerRegistrationOrderPrinter(Registry);
392 Registry.addDependency("test.WeakDep", "test.StrongDep");
393 Registry.addWeakDependency("test.Dep", "test.WeakDep");
394 });
395 }
396
addWeakDepHasUnspecifiedButLaterEnabledStrongDep(AnalysisASTConsumer & AnalysisConsumer,AnalyzerOptions & AnOpts)397 void addWeakDepHasUnspecifiedButLaterEnabledStrongDep(
398 AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) {
399 AnOpts.CheckersAndPackages = {{"test.Dep", true},
400 {"test.Dep2", true},
401 {"test.WeakDep", true},
402 {"test.RegistrationOrder", true}};
403 AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) {
404 addStrongDep(Registry);
405 addWeakDep(Registry);
406 addDep(Registry);
407 addDep2(Registry);
408 addCheckerRegistrationOrderPrinter(Registry);
409 Registry.addDependency("test.WeakDep", "test.StrongDep");
410 Registry.addDependency("test.Dep2", "test.StrongDep");
411 Registry.addWeakDependency("test.Dep", "test.WeakDep");
412 });
413 }
414
TEST(RegisterDeps,DependencyInteraction)415 TEST(RegisterDeps, DependencyInteraction) {
416 std::string Diags;
417 EXPECT_TRUE(
418 runCheckerOnCode<addWeakDepHasStrongDep>("void f() {int i;}", Diags));
419 EXPECT_EQ(Diags, "test.RegistrationOrder: test.StrongDep\ntest."
420 "WeakDep\ntest.Dep\ntest.RegistrationOrder\n");
421 Diags.clear();
422
423 // Weak dependencies are registered before strong dependencies. This is most
424 // important for purely diagnostic checkers that are implemented as a part of
425 // purely modeling checkers, becuse the checker callback order will have to be
426 // established in between the modeling portion and the weak dependency.
427 EXPECT_TRUE(
428 runCheckerOnCode<addWeakDepAndStrongDep>("void f() {int i;}", Diags));
429 EXPECT_EQ(Diags, "test.RegistrationOrder: test.WeakDep\ntest."
430 "StrongDep\ntest.Dep\ntest.RegistrationOrder\n");
431 Diags.clear();
432
433 // If a weak dependency is disabled, the checker itself can still be enabled.
434 EXPECT_TRUE(runCheckerOnCode<addDisabledWeakDepHasStrongDep>(
435 "void f() {int i;}", Diags));
436 EXPECT_EQ(Diags, "test.RegistrationOrder: test.Dep\ntest."
437 "RegistrationOrder\ntest.StrongDep\n");
438 Diags.clear();
439
440 // If a weak dependency is disabled, the checker itself can still be enabled,
441 // but it shouldn't enable a strong unspecified dependency.
442 EXPECT_TRUE(runCheckerOnCode<addDisabledWeakDepHasUnspecifiedStrongDep>(
443 "void f() {int i;}", Diags));
444 EXPECT_EQ(Diags,
445 "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
446 Diags.clear();
447
448 // A strong dependency of a weak dependency is disabled, so neither of them
449 // should be enabled.
450 EXPECT_TRUE(runCheckerOnCode<addWeakDepHasDisabledStrongDep>(
451 "void f() {int i;}", Diags));
452 EXPECT_EQ(Diags,
453 "test.RegistrationOrder: test.Dep\ntest.RegistrationOrder\n");
454 Diags.clear();
455
456 EXPECT_TRUE(
457 runCheckerOnCode<addWeakDepHasUnspecifiedButLaterEnabledStrongDep>(
458 "void f() {int i;}", Diags));
459 EXPECT_EQ(Diags, "test.RegistrationOrder: test.StrongDep\ntest.WeakDep\ntest."
460 "Dep\ntest.Dep2\ntest.RegistrationOrder\n");
461 Diags.clear();
462 }
463 } // namespace
464 } // namespace ento
465 } // namespace clang
466