llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Jonathan Marriott (JonathanMarriott) <details> <summary>Changes</summary> Fixes #<!-- -->146101, in summary dumping a `catch(...)` statement using IgnoreUnlessSpelledInSource AST traversal causes a seg fault, as the variable declaration of the catch is `nullptr`. Diagnosed the cause by attaching the debugger to `clang-query`, this PR adds a fix to check for `nullptr` before accessing the `isImplicit()` method of the `Decl` pointee in the AST node traverser visitor --- Full diff: https://github.com/llvm/llvm-project/pull/146103.diff 2 Files Affected: - (modified) clang/include/clang/AST/ASTNodeTraverser.h (+1-1) - (modified) clang/unittests/AST/ASTTraverserTest.cpp (+75) ``````````diff diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 8d02a50e2e8a5..8ebabb2bde10d 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -99,7 +99,7 @@ class ASTNodeTraverser TraversalKind GetTraversalKind() const { return Traversal; } void Visit(const Decl *D, bool VisitLocs = false) { - if (Traversal == TK_IgnoreUnlessSpelledInSource && D->isImplicit()) + if (Traversal == TK_IgnoreUnlessSpelledInSource && D && D->isImplicit()) return; getNodeDelegate().AddChild([=] { diff --git a/clang/unittests/AST/ASTTraverserTest.cpp b/clang/unittests/AST/ASTTraverserTest.cpp index 8b6e3e90c0ea6..988e81d8e51de 100644 --- a/clang/unittests/AST/ASTTraverserTest.cpp +++ b/clang/unittests/AST/ASTTraverserTest.cpp @@ -28,6 +28,10 @@ class NodeTreePrinter : public TextTreeStructure { : TextTreeStructure(OS, /* showColors */ false), OS(OS) {} void Visit(const Decl *D) { + if (!D) { + OS << "<<<NULL>>>"; + return; + } OS << D->getDeclKindName() << "Decl"; if (auto *ND = dyn_cast<NamedDecl>(D)) { OS << " '" << ND->getDeclName() << "'"; @@ -1932,4 +1936,75 @@ CXXRewrittenBinaryOperator } } +TEST(Traverse, CatchStatements) { + + auto AST = buildASTFromCode(R"cpp( +void test() +{ + try + { + int a; + } + catch (...) + { + int b; + } + + try + { + int a; + } + catch (const int&) + { + int b; + } +} +)cpp"); + + auto BN = + ast_matchers::match(cxxCatchStmt().bind("catch"), AST->getASTContext()); + EXPECT_EQ(BN.size(), 2u); + const auto *catchWithoutDecl = BN[0].getNodeAs<Stmt>("catch"); + + llvm::StringRef Expected = R"cpp( +CXXCatchStmt +|-<<<NULL>>> +`-CompoundStmt + `-DeclStmt + `-VarDecl 'b' +)cpp"; + EXPECT_EQ(dumpASTString(TK_AsIs, catchWithoutDecl), Expected); + + Expected = R"cpp( +CXXCatchStmt +|-<<<NULL>>> +`-CompoundStmt + `-DeclStmt + `-VarDecl 'b' +)cpp"; + EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, catchWithoutDecl), + Expected); + + const auto *catchWithDecl = BN[1].getNodeAs<Stmt>("catch"); + + Expected = R"cpp( +CXXCatchStmt +|-VarDecl '' +`-CompoundStmt + `-DeclStmt + `-VarDecl 'b' +)cpp"; + EXPECT_EQ(dumpASTString(TK_AsIs, catchWithDecl), Expected); + + Expected = R"cpp( +CXXCatchStmt +|-VarDecl '' +`-CompoundStmt + `-DeclStmt + `-VarDecl 'b' +)cpp"; + EXPECT_EQ(dumpASTString(TK_IgnoreUnlessSpelledInSource, catchWithDecl), + Expected); +} + } // namespace clang `````````` </details> https://github.com/llvm/llvm-project/pull/146103 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits