@@ -18,6 +18,41 @@ namespace clang {
18
18
namespace analysis {
19
19
namespace {
20
20
21
+ enum BuildResult {
22
+ ToolFailed,
23
+ ToolRan,
24
+ SawFunctionBody,
25
+ BuiltCFG,
26
+ };
27
+
28
+ class CFGCallback : public ast_matchers ::MatchFinder::MatchCallback {
29
+ public:
30
+ BuildResult TheBuildResult = ToolRan;
31
+
32
+ void run (const ast_matchers::MatchFinder::MatchResult &Result) override {
33
+ const auto *Func = Result.Nodes .getNodeAs <FunctionDecl>(" func" );
34
+ Stmt *Body = Func->getBody ();
35
+ if (!Body)
36
+ return ;
37
+ TheBuildResult = SawFunctionBody;
38
+ if (CFG::buildCFG (nullptr , Body, Result.Context , CFG::BuildOptions ()))
39
+ TheBuildResult = BuiltCFG;
40
+ }
41
+ };
42
+
43
+ BuildResult BuildCFG (const char *Code) {
44
+ CFGCallback Callback;
45
+
46
+ ast_matchers::MatchFinder Finder;
47
+ Finder.addMatcher (ast_matchers::functionDecl ().bind (" func" ), &Callback);
48
+ std::unique_ptr<tooling::FrontendActionFactory> Factory (
49
+ tooling::newFrontendActionFactory (&Finder));
50
+ std::vector<std::string> Args = {" -std=c++11" , " -fno-delayed-template-parsing" };
51
+ if (!tooling::runToolOnCodeWithArgs (Factory->create (), Code, Args))
52
+ return ToolFailed;
53
+ return Callback.TheBuildResult ;
54
+ }
55
+
21
56
// Constructing a CFG for a range-based for over a dependent type fails (but
22
57
// should not crash).
23
58
TEST (CFG, RangeBasedForOverDependentType) {
@@ -27,30 +62,17 @@ TEST(CFG, RangeBasedForOverDependentType) {
27
62
" for (const Foo *TheFoo : Range) {\n "
28
63
" }\n "
29
64
" }\n " ;
65
+ EXPECT_EQ (SawFunctionBody, BuildCFG (Code));
66
+ }
30
67
31
- class CFGCallback : public ast_matchers ::MatchFinder::MatchCallback {
32
- public:
33
- bool SawFunctionBody = false ;
34
-
35
- void run (const ast_matchers::MatchFinder::MatchResult &Result) override {
36
- const auto *Func = Result.Nodes .getNodeAs <FunctionDecl>(" func" );
37
- Stmt *Body = Func->getBody ();
38
- if (!Body)
39
- return ;
40
- SawFunctionBody = true ;
41
- std::unique_ptr<CFG> cfg =
42
- CFG::buildCFG (nullptr , Body, Result.Context , CFG::BuildOptions ());
43
- EXPECT_EQ (nullptr , cfg);
44
- }
45
- } Callback;
46
-
47
- ast_matchers::MatchFinder Finder;
48
- Finder.addMatcher (ast_matchers::functionDecl ().bind (" func" ), &Callback);
49
- std::unique_ptr<tooling::FrontendActionFactory> Factory (
50
- tooling::newFrontendActionFactory (&Finder));
51
- std::vector<std::string> Args = {" -std=c++11" , " -fno-delayed-template-parsing" };
52
- ASSERT_TRUE (tooling::runToolOnCodeWithArgs (Factory->create (), Code, Args));
53
- EXPECT_TRUE (Callback.SawFunctionBody );
68
+ // Constructing a CFG containing a delete expression on a dependent type should
69
+ // not crash.
70
+ TEST (CFG, DeleteExpressionOnDependentType) {
71
+ const char *Code = " template<class T>\n "
72
+ " void f(T t) {\n "
73
+ " delete t;\n "
74
+ " }\n " ;
75
+ EXPECT_EQ (BuiltCFG, BuildCFG (Code));
54
76
}
55
77
56
78
} // namespace
0 commit comments