Author: mboehme Date: Mon Dec 5 05:33:19 2016 New Revision: 288665 URL: http://llvm.org/viewvc/llvm-project?rev=288665&view=rev Log: 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 Modified: cfe/trunk/lib/Analysis/CFG.cpp cfe/trunk/unittests/Analysis/CFGTest.cpp Modified: cfe/trunk/lib/Analysis/CFG.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=288665&r1=288664&r2=288665&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/CFG.cpp (original) +++ cfe/trunk/lib/Analysis/CFG.cpp Mon Dec 5 05:33:19 2016 @@ -3581,11 +3581,13 @@ CFGBlock *CFGBuilder::VisitCXXDeleteExpr autoCreateBlock(); appendStmt(Block, DE); QualType DTy = DE->getDestroyedType(); - DTy = DTy.getNonReferenceType(); - CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl(); - if (RD) { - if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor()) - appendDeleteDtor(Block, RD, DE); + if (!DTy.isNull()) { + DTy = DTy.getNonReferenceType(); + CXXRecordDecl *RD = Context->getBaseElementType(DTy)->getAsCXXRecordDecl(); + if (RD) { + if (RD->isCompleteDefinition() && !RD->hasTrivialDestructor()) + appendDeleteDtor(Block, RD, DE); + } } return VisitChildren(DE); Modified: cfe/trunk/unittests/Analysis/CFGTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Analysis/CFGTest.cpp?rev=288665&r1=288664&r2=288665&view=diff ============================================================================== --- cfe/trunk/unittests/Analysis/CFGTest.cpp (original) +++ cfe/trunk/unittests/Analysis/CFGTest.cpp Mon Dec 5 05:33:19 2016 @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits