diff options
author | Sam McCall <sam.mccall@gmail.com> | 2023-03-08 16:13:28 +0100 |
---|---|---|
committer | Sam McCall <sam.mccall@gmail.com> | 2023-04-19 15:37:06 +0200 |
commit | a443b3d18ef4d01e767994845b3f2819480a7b48 (patch) | |
tree | 681aeb8b5c1dfe24275c1f6aca8b0bc7301cc732 /clang/unittests | |
parent | 50639d3d0dfcc62405a04763a7603021408cfa84 (diff) | |
download | llvm-a443b3d18ef4d01e767994845b3f2819480a7b48.tar.gz |
[dataflow] add HTML logger: browse code/cfg/analysis timeline/state
With -dataflow-log=/dir we will write /dir/0.html etc for each
function analyzed.
These files show the function's code and CFG, and the path through
the CFG taken by the analysis. At each analysis point we can see the
lattice state.
Currently the lattice state dump is not terribly useful but we can
improve this: showing values associated with the current Expr,
simplifying flow condition, highlighting changes etc.
(Trying not to let this patch scope-creep too much, so I ripped out the
half-finished features)
Demo: https://htmlpreview.github.io/?https://gist.githubusercontent.com/sam-mccall/1746985bf13406bd19181af281aea9ff/raw/9718fdd48406dabccb3092acd983b4bd55da9dfa/analysis.html
Differential Revision: https://reviews.llvm.org/D146591
Diffstat (limited to 'clang/unittests')
-rw-r--r-- | clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp b/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp index eab37045c393..0b8579a45b2d 100644 --- a/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/LoggerTest.cpp @@ -9,6 +9,7 @@ namespace clang::dataflow::test { namespace { +using testing::HasSubstr; struct TestLattice { int Elements = 0; @@ -83,19 +84,24 @@ private: void logText(llvm::StringRef Text) override { OS << Text << "\n"; } }; -TEST(LoggerTest, Sequence) { +AnalysisInputs<TestAnalysis> makeInputs() { const char *Code = R"cpp( int target(bool b, int p, int q) { return b ? p : q; } )cpp"; + static const std::vector<std::string> Args = { + "-fsyntax-only", "-fno-delayed-template-parsing", "-std=c++17"}; auto Inputs = AnalysisInputs<TestAnalysis>( Code, ast_matchers::hasName("target"), [](ASTContext &C, Environment &) { return TestAnalysis(C); }); - std::vector<std::string> Args = { - "-fsyntax-only", "-fno-delayed-template-parsing", "-std=c++17"}; Inputs.ASTBuildArgs = Args; + return Inputs; +} + +TEST(LoggerTest, Sequence) { + auto Inputs = makeInputs(); std::string Log; TestLogger Logger(Log); Inputs.BuiltinOptions.Log = &Logger; @@ -148,5 +154,29 @@ endAnalysis() )"); } +TEST(LoggerTest, HTML) { + auto Inputs = makeInputs(); + std::vector<std::string> Logs; + auto Logger = Logger::html([&]() { + Logs.emplace_back(); + return std::make_unique<llvm::raw_string_ostream>(Logs.back()); + }); + Inputs.BuiltinOptions.Log = Logger.get(); + + ASSERT_THAT_ERROR(checkDataflow<TestAnalysis>(std::move(Inputs), + [](const AnalysisOutputs &) {}), + llvm::Succeeded()); + + // Simple smoke tests: we can't meaningfully test the behavior. + ASSERT_THAT(Logs, testing::SizeIs(1)); + EXPECT_THAT(Logs[0], HasSubstr("function updateSelection")) << "embeds JS"; + EXPECT_THAT(Logs[0], HasSubstr("html {")) << "embeds CSS"; + EXPECT_THAT(Logs[0], HasSubstr("b (ImplicitCastExpr")) << "has CFG elements"; + EXPECT_THAT(Logs[0], HasSubstr("\"B3:1_B3.1\":")) + << "has analysis point state"; + EXPECT_THAT(Logs[0], HasSubstr("transferBranch(0)")) << "has analysis logs"; + EXPECT_THAT(Logs[0], HasSubstr("LocToVal")) << "has built-in lattice dump"; +} + } // namespace } // namespace clang::dataflow::test |