r288665 - CFGBuilder: Fix crash when visiting delete expression on dependent type
Martin Bohme via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 5 03:33:20 PST 2016
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
More information about the cfe-commits
mailing list