From 690ff37a286991f142584f25842e50c6cb23aba6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kirst=C3=B3f=20Umann?= Date: Fri, 12 Jun 2020 20:54:24 +0200 Subject: [PATCH] [analyzer] Force dependency checkers to be hidden Since strong dependencies aren't user-facing (its hardly ever legal to disable them), lets enforce that they are hidden. Modeling checkers that aren't dependencies are of course not impacted, but there is only so much you can do against developers shooting themselves in the foot :^) I also made some changes to the test files, reversing the "test" package for, well, testing. Differential Revision: https://reviews.llvm.org/D81761 --- .../clang/StaticAnalyzer/Checkers/Checkers.td | 9 +- .../StaticAnalyzer/Frontend/CheckerRegistry.cpp | 7 + .../StaticAnalyzer/RegisterCustomCheckersTest.cpp | 192 ++++++++++----------- 3 files changed, 106 insertions(+), 102 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 0ceedfb..c1baa52 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -130,7 +130,8 @@ def CallAndMessageModeling : Checker<"CallAndMessageModeling">, "function/method call. For instance, if we can't reason about the " "nullability of the implicit this parameter after a method call, " "this checker conservatively assumes it to be non-null">, - Documentation; + Documentation, + Hidden; def CallAndMessageChecker : Checker<"CallAndMessage">, HelpText<"Check for logical errors for function calls and Objective-C " @@ -220,7 +221,8 @@ def StackAddrEscapeChecker : Checker<"StackAddressEscape">, def DynamicTypePropagation : Checker<"DynamicTypePropagation">, HelpText<"Generate dynamic type information">, - Documentation; + Documentation, + Hidden; def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">, HelpText<"Assume that const string-like globals are non-null">, @@ -363,7 +365,8 @@ def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">, "false", InAlpha> ]>, - Documentation; + Documentation, + Hidden; def TrustNonnullChecker : Checker<"TrustNonnull">, HelpText<"Trust that returns from framework methods annotated with _Nonnull " diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp index a688205..528284c 100644 --- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -310,6 +310,13 @@ template void CheckerRegistry::resolveDependencies() { DependencyIt->FullName == Entry.second && "Failed to find the dependency of a checker!"); + // We do allow diagnostics from unit test/example dependency checkers. + assert((DependencyIt->FullName.startswith("test") || + DependencyIt->FullName.startswith("example") || IsWeak || + DependencyIt->IsHidden) && + "Strong dependencies are modeling checkers, and as such " + "non-user facing! Mark them hidden in Checkers.td!"); + if (IsWeak) CheckerIt->WeakDependencies.emplace_back(&*DependencyIt); else diff --git a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp index c7c7595..60b8aaf 100644 --- a/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp +++ b/clang/unittests/StaticAnalyzer/RegisterCustomCheckersTest.cpp @@ -42,17 +42,16 @@ public: void addCustomChecker(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.CustomChecker", true}}; + AnOpts.CheckersAndPackages = {{"test.CustomChecker", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { - Registry.addChecker("custom.CustomChecker", "Description", - ""); + Registry.addChecker("test.CustomChecker", "Description", ""); }); } TEST(RegisterCustomCheckers, RegisterChecker) { std::string Diags; EXPECT_TRUE(runCheckerOnCode("void f() {;}", Diags)); - EXPECT_EQ(Diags, "custom.CustomChecker:Custom diagnostic description\n"); + EXPECT_EQ(Diags, "test.CustomChecker:Custom diagnostic description\n"); } //===----------------------------------------------------------------------===// @@ -121,7 +120,7 @@ bool shouldRegisterCheckerRegistrationOrderPrinter(const CheckerManager &mgr) { void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) { Registry.addChecker(registerCheckerRegistrationOrderPrinter, shouldRegisterCheckerRegistrationOrderPrinter, - "custom.RegistrationOrder", "Description", "", false); + "test.RegistrationOrder", "Description", "", false); } #define UNITTEST_CHECKER(CHECKER_NAME, DIAG_MSG) \ @@ -142,7 +141,7 @@ void addCheckerRegistrationOrderPrinter(CheckerRegistry &Registry) { } \ void add##CHECKER_NAME(CheckerRegistry &Registry) { \ Registry.addChecker(register##CHECKER_NAME, shouldRegister##CHECKER_NAME, \ - "custom." #CHECKER_NAME, "Description", "", false); \ + "test." #CHECKER_NAME, "Description", "", false); \ } UNITTEST_CHECKER(StrongDep, "Strong") @@ -155,22 +154,22 @@ bool shouldRegisterStrongFALSE(const CheckerManager &mgr) { void addDep(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker(registerStrongDep, shouldRegisterStrongFALSE, - "custom.Strong", "Description", "", false); + "test.Strong", "Description", "", false); addStrongDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addDependency("custom.Dep", "custom.Strong"); + Registry.addDependency("test.Dep", "test.Strong"); }); } TEST(RegisterDeps, UnsatisfiedDependency) { std::string Diags; EXPECT_TRUE(runCheckerOnCode("void f() {int i;}", Diags)); - EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.RegistrationOrder\n"); } //===----------------------------------------------------------------------===// @@ -181,52 +180,52 @@ UNITTEST_CHECKER(WeakDep, "Weak") void addWeakDepCheckerBothEnabled(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.WeakDep", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.WeakDep", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } void addWeakDepCheckerBothEnabledSwitched(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.WeakDep", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.WeakDep", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addWeakDependency("custom.WeakDep", "custom.Dep"); + Registry.addWeakDependency("test.WeakDep", "test.Dep"); }); } void addWeakDepCheckerDepDisabled(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.WeakDep", false}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.WeakDep", false}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } void addWeakDepCheckerDepUnspecified(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } @@ -235,10 +234,10 @@ UNITTEST_CHECKER(Dep2, "Dep2") void addWeakDepHasWeakDep(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.WeakDep", true}, - {"custom.WeakDep2", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.WeakDep", true}, + {"test.WeakDep2", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addStrongDep(Registry); addWeakDep(Registry); @@ -246,17 +245,17 @@ void addWeakDepHasWeakDep(AnalysisASTConsumer &AnalysisConsumer, addDep(Registry); addDep2(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); - Registry.addWeakDependency("custom.WeakDep", "custom.WeakDep2"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); + Registry.addWeakDependency("test.WeakDep", "test.WeakDep2"); }); } void addWeakDepTransitivity(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.WeakDep", false}, - {"custom.WeakDep2", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.WeakDep", false}, + {"test.WeakDep2", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addStrongDep(Registry); addWeakDep(Registry); @@ -264,8 +263,8 @@ void addWeakDepTransitivity(AnalysisASTConsumer &AnalysisConsumer, addDep(Registry); addDep2(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); - Registry.addWeakDependency("custom.WeakDep", "custom.WeakDep2"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); + Registry.addWeakDependency("test.WeakDep", "test.WeakDep2"); }); } @@ -273,42 +272,40 @@ TEST(RegisterDeps, SimpleWeakDependency) { std::string Diags; EXPECT_TRUE(runCheckerOnCode( "void f() {int i;}", Diags)); - EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.WeakDep\ncustom." - "Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.WeakDep\ntest." + "Dep\ntest.RegistrationOrder\n"); Diags.clear(); // Mind that AnalyzerOption listed the enabled checker list in the same order, // but the dependencies are switched. EXPECT_TRUE(runCheckerOnCode( "void f() {int i;}", Diags)); - EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.Dep\ncustom." - "RegistrationOrder\ncustom.WeakDep\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.Dep\ntest." + "RegistrationOrder\ntest.WeakDep\n"); Diags.clear(); // Weak dependencies dont prevent dependent checkers from being enabled. EXPECT_TRUE(runCheckerOnCode( "void f() {int i;}", Diags)); - EXPECT_EQ(Diags, - "custom.RegistrationOrder:custom.Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.Dep\ntest.RegistrationOrder\n"); Diags.clear(); // Nor will they be enabled just because a dependent checker is. EXPECT_TRUE(runCheckerOnCode( "void f() {int i;}", Diags)); - EXPECT_EQ(Diags, - "custom.RegistrationOrder:custom.Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.Dep\ntest.RegistrationOrder\n"); Diags.clear(); EXPECT_TRUE( runCheckerOnCode("void f() {int i;}", Diags)); - EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.WeakDep2\ncustom." - "Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.WeakDep2\ntest." + "Dep\ntest.RegistrationOrder\n"); Diags.clear(); EXPECT_TRUE( runCheckerOnCode("void f() {int i;}", Diags)); - EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.WeakDep2\ncustom." - "WeakDep\ncustom.Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.WeakDep2\ntest." + "WeakDep\ntest.Dep\ntest.RegistrationOrder\n"); Diags.clear(); } @@ -318,98 +315,98 @@ TEST(RegisterDeps, SimpleWeakDependency) { void addWeakDepHasStrongDep(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.StrongDep", true}, - {"custom.WeakDep", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.StrongDep", true}, + {"test.WeakDep", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addStrongDep(Registry); addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addDependency("custom.WeakDep", "custom.StrongDep"); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addDependency("test.WeakDep", "test.StrongDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } void addWeakDepAndStrongDep(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.StrongDep", true}, - {"custom.WeakDep", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.StrongDep", true}, + {"test.WeakDep", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addStrongDep(Registry); addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addDependency("custom.Dep", "custom.StrongDep"); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addDependency("test.Dep", "test.StrongDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } void addDisabledWeakDepHasStrongDep(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.StrongDep", true}, - {"custom.WeakDep", false}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.StrongDep", true}, + {"test.WeakDep", false}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addStrongDep(Registry); addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addDependency("custom.WeakDep", "custom.StrongDep"); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addDependency("test.WeakDep", "test.StrongDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } void addDisabledWeakDepHasUnspecifiedStrongDep( AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.WeakDep", false}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.WeakDep", false}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addStrongDep(Registry); addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addDependency("custom.WeakDep", "custom.StrongDep"); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addDependency("test.WeakDep", "test.StrongDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } void addWeakDepHasDisabledStrongDep(AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.StrongDep", false}, - {"custom.WeakDep", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.StrongDep", false}, + {"test.WeakDep", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addStrongDep(Registry); addWeakDep(Registry); addDep(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addDependency("custom.WeakDep", "custom.StrongDep"); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addDependency("test.WeakDep", "test.StrongDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } void addWeakDepHasUnspecifiedButLaterEnabledStrongDep( AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) { - AnOpts.CheckersAndPackages = {{"custom.Dep", true}, - {"custom.Dep2", true}, - {"custom.WeakDep", true}, - {"custom.RegistrationOrder", true}}; + AnOpts.CheckersAndPackages = {{"test.Dep", true}, + {"test.Dep2", true}, + {"test.WeakDep", true}, + {"test.RegistrationOrder", true}}; AnalysisConsumer.AddCheckerRegistrationFn([=](CheckerRegistry &Registry) { addStrongDep(Registry); addWeakDep(Registry); addDep(Registry); addDep2(Registry); addCheckerRegistrationOrderPrinter(Registry); - Registry.addDependency("custom.WeakDep", "custom.StrongDep"); - Registry.addDependency("custom.Dep2", "custom.StrongDep"); - Registry.addWeakDependency("custom.Dep", "custom.WeakDep"); + Registry.addDependency("test.WeakDep", "test.StrongDep"); + Registry.addDependency("test.Dep2", "test.StrongDep"); + Registry.addWeakDependency("test.Dep", "test.WeakDep"); }); } @@ -417,8 +414,8 @@ TEST(RegisterDeps, DependencyInteraction) { std::string Diags; EXPECT_TRUE( runCheckerOnCode("void f() {int i;}", Diags)); - EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.StrongDep\ncustom." - "WeakDep\ncustom.Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.StrongDep\ntest." + "WeakDep\ntest.Dep\ntest.RegistrationOrder\n"); Diags.clear(); // Weak dependencies are registered before strong dependencies. This is most @@ -427,39 +424,36 @@ TEST(RegisterDeps, DependencyInteraction) { // established in between the modeling portion and the weak dependency. EXPECT_TRUE( runCheckerOnCode("void f() {int i;}", Diags)); - EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.WeakDep\ncustom." - "StrongDep\ncustom.Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.WeakDep\ntest." + "StrongDep\ntest.Dep\ntest.RegistrationOrder\n"); Diags.clear(); // If a weak dependency is disabled, the checker itself can still be enabled. EXPECT_TRUE(runCheckerOnCode( "void f() {int i;}", Diags)); - EXPECT_EQ(Diags, "custom.RegistrationOrder:custom.Dep\ncustom." - "RegistrationOrder\ncustom.StrongDep\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.Dep\ntest." + "RegistrationOrder\ntest.StrongDep\n"); Diags.clear(); // If a weak dependency is disabled, the checker itself can still be enabled, // but it shouldn't enable a strong unspecified dependency. EXPECT_TRUE(runCheckerOnCode( "void f() {int i;}", Diags)); - EXPECT_EQ(Diags, - "custom.RegistrationOrder:custom.Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.Dep\ntest.RegistrationOrder\n"); Diags.clear(); // A strong dependency of a weak dependency is disabled, so neither of them // should be enabled. EXPECT_TRUE(runCheckerOnCode( "void f() {int i;}", Diags)); - EXPECT_EQ(Diags, - "custom.RegistrationOrder:custom.Dep\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.Dep\ntest.RegistrationOrder\n"); Diags.clear(); EXPECT_TRUE( runCheckerOnCode( "void f() {int i;}", Diags)); - EXPECT_EQ(Diags, - "custom.RegistrationOrder:custom.StrongDep\ncustom.WeakDep\ncustom." - "Dep\ncustom.Dep2\ncustom.RegistrationOrder\n"); + EXPECT_EQ(Diags, "test.RegistrationOrder:test.StrongDep\ntest.WeakDep\ntest." + "Dep\ntest.Dep2\ntest.RegistrationOrder\n"); Diags.clear(); } } // namespace -- 2.7.4