diff options
author | Martin Bohme <mboehme@google.com> | 2016-12-05 11:33:19 +0000 |
---|---|---|
committer | Martin Bohme <mboehme@google.com> | 2016-12-05 11:33:19 +0000 |
commit | 96d53fef2346ea7001801462ad338c7f01197d19 (patch) | |
tree | b07d32aceaf75e7ae62afb16399e483b556b4a85 /unittests/Analysis | |
parent | 581ee4199aaf0bc399874e1e0f881b7d84a4af95 (diff) | |
download | clang-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.cpp | 68 |
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 |