courbet created this revision. courbet added reviewers: gribozavr, alexfh. Herald added a project: All. courbet requested review of this revision. Herald added a project: clang.
Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D121365 Files: clang/lib/Analysis/CFG.cpp clang/unittests/Analysis/CFGBuildResult.h clang/unittests/Analysis/CFGTest.cpp Index: clang/unittests/Analysis/CFGTest.cpp =================================================================== --- clang/unittests/Analysis/CFGTest.cpp +++ clang/unittests/Analysis/CFGTest.cpp @@ -70,6 +70,27 @@ EXPECT_EQ(BuildResult::BuiltCFG, BuildCFG(Code).getStatus()); } +// Constructing a CFG with a dependent base should not crash. +TEST(CFG, DependantBaseAddImplicitDtors) { + const char *Code = R"( + template <class T> + struct Base { + virtual ~Base() {} + }; + + template <typename T> + struct Derived : public Base<T> { + virtual ~Derived() {} + }; + )"; + CFG::BuildOptions Options; + Options.AddImplicitDtors = true; + Options.setAllAlwaysAdd(); + EXPECT_EQ(BuildResult::BuiltCFG, + BuildCFG(Code, Options, ast_matchers::hasName("~Derived<T>")) + .getStatus()); +} + TEST(CFG, IsLinear) { auto expectLinear = [](bool IsLinear, const char *Code) { BuildResult B = BuildCFG(Code); Index: clang/unittests/Analysis/CFGBuildResult.h =================================================================== --- clang/unittests/Analysis/CFGBuildResult.h +++ clang/unittests/Analysis/CFGBuildResult.h @@ -56,13 +56,15 @@ TheBuildResult = BuildResult::SawFunctionBody; Options.AddImplicitDtors = true; if (std::unique_ptr<CFG> Cfg = - CFG::buildCFG(nullptr, Body, Result.Context, Options)) + CFG::buildCFG(Func, Body, Result.Context, Options)) TheBuildResult = {BuildResult::BuiltCFG, Func, std::move(Cfg), std::move(AST)}; } }; -inline BuildResult BuildCFG(const char *Code, CFG::BuildOptions Options = {}) { +template <typename FuncMatcherT = ast_matchers::internal::TrueMatcher> +BuildResult BuildCFG(const char *Code, CFG::BuildOptions Options = {}, + FuncMatcherT FuncMatcher = ast_matchers::anything()) { std::vector<std::string> Args = {"-std=c++11", "-fno-delayed-template-parsing"}; std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCodeWithArgs(Code, Args); @@ -72,7 +74,8 @@ CFGCallback Callback(std::move(AST)); Callback.Options = Options; ast_matchers::MatchFinder Finder; - Finder.addMatcher(ast_matchers::functionDecl().bind("func"), &Callback); + Finder.addMatcher(ast_matchers::functionDecl(FuncMatcher).bind("func"), + &Callback); Finder.matchAST(Callback.AST->getASTContext()); return std::move(Callback.TheBuildResult); Index: clang/lib/Analysis/CFG.cpp =================================================================== --- clang/lib/Analysis/CFG.cpp +++ clang/lib/Analysis/CFG.cpp @@ -1884,7 +1884,7 @@ // (which is different from the current class) is responsible for // destroying them. const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl(); - if (!CD->hasTrivialDestructor()) { + if (CD && !CD->hasTrivialDestructor()) { autoCreateBlock(); appendBaseDtor(Block, &VI); } @@ -1894,7 +1894,7 @@ for (const auto &BI : RD->bases()) { if (!BI.isVirtual()) { const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl(); - if (!CD->hasTrivialDestructor()) { + if (CD && !CD->hasTrivialDestructor()) { autoCreateBlock(); appendBaseDtor(Block, &BI); }
Index: clang/unittests/Analysis/CFGTest.cpp =================================================================== --- clang/unittests/Analysis/CFGTest.cpp +++ clang/unittests/Analysis/CFGTest.cpp @@ -70,6 +70,27 @@ EXPECT_EQ(BuildResult::BuiltCFG, BuildCFG(Code).getStatus()); } +// Constructing a CFG with a dependent base should not crash. +TEST(CFG, DependantBaseAddImplicitDtors) { + const char *Code = R"( + template <class T> + struct Base { + virtual ~Base() {} + }; + + template <typename T> + struct Derived : public Base<T> { + virtual ~Derived() {} + }; + )"; + CFG::BuildOptions Options; + Options.AddImplicitDtors = true; + Options.setAllAlwaysAdd(); + EXPECT_EQ(BuildResult::BuiltCFG, + BuildCFG(Code, Options, ast_matchers::hasName("~Derived<T>")) + .getStatus()); +} + TEST(CFG, IsLinear) { auto expectLinear = [](bool IsLinear, const char *Code) { BuildResult B = BuildCFG(Code); Index: clang/unittests/Analysis/CFGBuildResult.h =================================================================== --- clang/unittests/Analysis/CFGBuildResult.h +++ clang/unittests/Analysis/CFGBuildResult.h @@ -56,13 +56,15 @@ TheBuildResult = BuildResult::SawFunctionBody; Options.AddImplicitDtors = true; if (std::unique_ptr<CFG> Cfg = - CFG::buildCFG(nullptr, Body, Result.Context, Options)) + CFG::buildCFG(Func, Body, Result.Context, Options)) TheBuildResult = {BuildResult::BuiltCFG, Func, std::move(Cfg), std::move(AST)}; } }; -inline BuildResult BuildCFG(const char *Code, CFG::BuildOptions Options = {}) { +template <typename FuncMatcherT = ast_matchers::internal::TrueMatcher> +BuildResult BuildCFG(const char *Code, CFG::BuildOptions Options = {}, + FuncMatcherT FuncMatcher = ast_matchers::anything()) { std::vector<std::string> Args = {"-std=c++11", "-fno-delayed-template-parsing"}; std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCodeWithArgs(Code, Args); @@ -72,7 +74,8 @@ CFGCallback Callback(std::move(AST)); Callback.Options = Options; ast_matchers::MatchFinder Finder; - Finder.addMatcher(ast_matchers::functionDecl().bind("func"), &Callback); + Finder.addMatcher(ast_matchers::functionDecl(FuncMatcher).bind("func"), + &Callback); Finder.matchAST(Callback.AST->getASTContext()); return std::move(Callback.TheBuildResult); Index: clang/lib/Analysis/CFG.cpp =================================================================== --- clang/lib/Analysis/CFG.cpp +++ clang/lib/Analysis/CFG.cpp @@ -1884,7 +1884,7 @@ // (which is different from the current class) is responsible for // destroying them. const CXXRecordDecl *CD = VI.getType()->getAsCXXRecordDecl(); - if (!CD->hasTrivialDestructor()) { + if (CD && !CD->hasTrivialDestructor()) { autoCreateBlock(); appendBaseDtor(Block, &VI); } @@ -1894,7 +1894,7 @@ for (const auto &BI : RD->bases()) { if (!BI.isVirtual()) { const CXXRecordDecl *CD = BI.getType()->getAsCXXRecordDecl(); - if (!CD->hasTrivialDestructor()) { + if (CD && !CD->hasTrivialDestructor()) { autoCreateBlock(); appendBaseDtor(Block, &BI); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits