summaryrefslogtreecommitdiff
path: root/unittests/Analysis
diff options
context:
space:
mode:
authorMartin Bohme <mboehme@google.com>2016-12-05 11:33:19 +0000
committerMartin Bohme <mboehme@google.com>2016-12-05 11:33:19 +0000
commit96d53fef2346ea7001801462ad338c7f01197d19 (patch)
treeb07d32aceaf75e7ae62afb16399e483b556b4a85 /unittests/Analysis
parent581ee4199aaf0bc399874e1e0f881b7d84a4af95 (diff)
downloadclang-96d53fef2346ea7001801462ad338c7f01197d19.tar.gz
CFGBuilder: Fix crash when visiting delete expression on dependent type
Summary: CXXDeleteExpr::getDestroyedType() can return a null QualType if the destroyed type is a dependent type. This patch protects against this. Reviewers: klimek Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D27350 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@288665 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/Analysis')
-rw-r--r--unittests/Analysis/CFGTest.cpp68
1 files changed, 45 insertions, 23 deletions
diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp
index a8d397e9a5..e691110050 100644
--- a/unittests/Analysis/CFGTest.cpp
+++ b/unittests/Analysis/CFGTest.cpp
@@ -18,6 +18,41 @@ namespace clang {
namespace analysis {
namespace {
+enum BuildResult {
+ ToolFailed,
+ ToolRan,
+ SawFunctionBody,
+ BuiltCFG,
+};
+
+class CFGCallback : public ast_matchers::MatchFinder::MatchCallback {
+public:
+ BuildResult TheBuildResult = ToolRan;
+
+ void run(const ast_matchers::MatchFinder::MatchResult &Result) override {
+ const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
+ Stmt *Body = Func->getBody();
+ if (!Body)
+ return;
+ TheBuildResult = SawFunctionBody;
+ if (CFG::buildCFG(nullptr, Body, Result.Context, CFG::BuildOptions()))
+ TheBuildResult = BuiltCFG;
+ }
+};
+
+BuildResult BuildCFG(const char *Code) {
+ CFGCallback Callback;
+
+ ast_matchers::MatchFinder Finder;
+ Finder.addMatcher(ast_matchers::functionDecl().bind("func"), &Callback);
+ std::unique_ptr<tooling::FrontendActionFactory> Factory(
+ tooling::newFrontendActionFactory(&Finder));
+ std::vector<std::string> Args = {"-std=c++11", "-fno-delayed-template-parsing"};
+ if (!tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args))
+ return ToolFailed;
+ return Callback.TheBuildResult;
+}
+
// Constructing a CFG for a range-based for over a dependent type fails (but
// should not crash).
TEST(CFG, RangeBasedForOverDependentType) {
@@ -27,30 +62,17 @@ TEST(CFG, RangeBasedForOverDependentType) {
" for (const Foo *TheFoo : Range) {\n"
" }\n"
"}\n";
+ EXPECT_EQ(SawFunctionBody, BuildCFG(Code));
+}
- class CFGCallback : public ast_matchers::MatchFinder::MatchCallback {
- public:
- bool SawFunctionBody = false;
-
- void run(const ast_matchers::MatchFinder::MatchResult &Result) override {
- const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>("func");
- Stmt *Body = Func->getBody();
- if (!Body)
- return;
- SawFunctionBody = true;
- std::unique_ptr<CFG> cfg =
- CFG::buildCFG(nullptr, Body, Result.Context, CFG::BuildOptions());
- EXPECT_EQ(nullptr, cfg);
- }
- } Callback;
-
- ast_matchers::MatchFinder Finder;
- Finder.addMatcher(ast_matchers::functionDecl().bind("func"), &Callback);
- std::unique_ptr<tooling::FrontendActionFactory> Factory(
- tooling::newFrontendActionFactory(&Finder));
- std::vector<std::string> Args = {"-std=c++11", "-fno-delayed-template-parsing"};
- ASSERT_TRUE(tooling::runToolOnCodeWithArgs(Factory->create(), Code, Args));
- EXPECT_TRUE(Callback.SawFunctionBody);
+// Constructing a CFG containing a delete expression on a dependent type should
+// not crash.
+TEST(CFG, DeleteExpressionOnDependentType) {
+ const char *Code = "template<class T>\n"
+ "void f(T t) {\n"
+ " delete t;\n"
+ "}\n";
+ EXPECT_EQ(BuiltCFG, BuildCFG(Code));
}
} // namespace