[PATCH] D24997: [ClangTidy] Add UsingInserter and NamespaceAliaser
jbangert created this revision. jbangert added a reviewer: alexfh. jbangert added a subscriber: cfe-commits. jbangert added a project: clang-tools-extra. This adds helper classes to add using declaractions and namespace aliases to function bodies. These help making function calls to deeply nested functions concise (e.g. when calling helpers in a refactoring) https://reviews.llvm.org/D24997 Files: clang-tidy/utils/ASTUtils.cpp clang-tidy/utils/ASTUtils.h clang-tidy/utils/NamespaceAliaser.cpp clang-tidy/utils/NamespaceAliaser.h clang-tidy/utils/UsingInserter.cpp clang-tidy/utils/UsingInserter.h unittests/clang-tidy/NamespaceAliaserTest.cpp unittests/clang-tidy/UsingInserterTest.cpp Index: unittests/clang-tidy/UsingInserterTest.cpp === --- /dev/null +++ unittests/clang-tidy/UsingInserterTest.cpp @@ -0,0 +1,115 @@ +//=== UsingInserterTest.cpp - clang-tidy ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "../clang-tidy/utils/UsingInserter.h" + +#include "ClangTidyTest.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "gtest/gtest.h" + +namespace clang { +namespace tidy { +namespace utils { + +// Replace all function calls with calls to foo::func. Inserts using +// declarations as necessary. This checker is for testing only. It +// can only run on one test case (e.g. wih one SourceManager). +class InsertUsingCheck : public clang::tidy::ClangTidyCheck { +public: + using clang::tidy::ClangTidyCheck::ClangTidyCheck; + void registerMatchers(clang::ast_matchers::MatchFinder *Finder) override { +Finder->addMatcher(clang::ast_matchers::callExpr().bind("foo"), this); + } + void + check(const clang::ast_matchers::MatchFinder::MatchResult &Result) override { +if (!Inserter) + Inserter.reset(new UsingInserter(*Result.SourceManager, + Result.Context->getLangOpts())); + +const clang::CallExpr *Call = +Result.Nodes.getNodeAs("foo"); +assert(Call != nullptr && "Did not find node \"foo\""); +auto Hint = +Inserter->createUsingDeclaration(*Result.Context, *Call, "::foo::func"); + +if (Hint.hasValue()) + diag(Call->getLocStart(), "Fix for testing") << Hint.getValue(); + +diag(Call->getLocStart(), "insert call") +<< clang::FixItHint::CreateReplacement( + Call->getCallee()->getSourceRange(), + Inserter->getShortName(*Result.Context, *Call, "::foo::func")); + } + +private: + std::unique_ptr Inserter; +}; + +template +std::string runChecker(StringRef Code, int ExpectedWarningCount) { + std::map AdditionalFileContents = {{"foo.h", +"namespace foo {\n" +"namespace bar {\n" +"}\n" +"void func() { }\n" +"}"}}; + std::vector errors; + + std::string result = + test::runCheckOnCode(Code, &errors, "foo.cc", None, + ClangTidyOptions(), AdditionalFileContents); + + EXPECT_EQ(ExpectedWarningCount, errors.size()); + return result; +} + +TEST(UsingInserterTest, ReusesExisting) { + EXPECT_EQ("#include \"foo.h\"\n" +"namespace {" +"using ::foo::func;\n" +"void f() { func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "namespace {" + "using ::foo::func;\n" + "void f() { f(); }" + "}", + 1)); +} + +TEST(UsingInserterTest, ReusesExistingGlobal) { + EXPECT_EQ("#include \"foo.h\"\n" +"using ::foo::func;\n" +"namespace {" +"void f() { func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "using ::foo::func;\n" + "namespace {" + "void f() { f(); }" + "}", + 1)); +} + +TEST(UsingInserterTest, AvoidsConflict) { + EXPECT_EQ("#include \"foo.h\"\n" +"namespace {" +"void f() { int func; ::foo::func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "namespace {" +
[PATCH] D24997: [ClangTidy] Add UsingInserter and NamespaceAliaser
jbangert updated this revision to Diff 74187. jbangert marked 15 inline comments as done. https://reviews.llvm.org/D24997 Files: clang-tidy/utils/ASTUtils.cpp clang-tidy/utils/ASTUtils.h clang-tidy/utils/NamespaceAliaser.cpp clang-tidy/utils/NamespaceAliaser.h clang-tidy/utils/UsingInserter.cpp clang-tidy/utils/UsingInserter.h unittests/clang-tidy/NamespaceAliaserTest.cpp unittests/clang-tidy/UsingInserterTest.cpp Index: unittests/clang-tidy/UsingInserterTest.cpp === --- /dev/null +++ unittests/clang-tidy/UsingInserterTest.cpp @@ -0,0 +1,115 @@ +//=== UsingInserterTest.cpp - clang-tidy ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "../clang-tidy/utils/UsingInserter.h" + +#include "ClangTidyTest.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "gtest/gtest.h" + +namespace clang { +namespace tidy { +namespace utils { + +// Replace all function calls with calls to foo::func. Inserts using +// declarations as necessary. This checker is for testing only. It +// can only run on one test case (e.g. wih one SourceManager). +class InsertUsingCheck : public clang::tidy::ClangTidyCheck { +public: + using clang::tidy::ClangTidyCheck::ClangTidyCheck; + void registerMatchers(clang::ast_matchers::MatchFinder *Finder) override { +Finder->addMatcher(clang::ast_matchers::callExpr().bind("foo"), this); + } + void + check(const clang::ast_matchers::MatchFinder::MatchResult &Result) override { +if (!Inserter) + Inserter.reset(new UsingInserter(*Result.SourceManager, + Result.Context->getLangOpts())); + +const clang::CallExpr *Call = +Result.Nodes.getNodeAs("foo"); +assert(Call != nullptr && "Did not find node \"foo\""); +auto Hint = +Inserter->createUsingDeclaration(*Result.Context, *Call, "::foo::func"); + +if (Hint.hasValue()) + diag(Call->getLocStart(), "Fix for testing") << Hint.getValue(); + +diag(Call->getLocStart(), "insert call") +<< clang::FixItHint::CreateReplacement( + Call->getCallee()->getSourceRange(), + Inserter->getShortName(*Result.Context, *Call, "::foo::func")); + } + +private: + std::unique_ptr Inserter; +}; + +template +std::string runChecker(StringRef Code, int ExpectedWarningCount) { + std::map AdditionalFileContents = {{"foo.h", +"namespace foo {\n" +"namespace bar {\n" +"}\n" +"void func() { }\n" +"}"}}; + std::vector errors; + + std::string result = + test::runCheckOnCode(Code, &errors, "foo.cc", None, + ClangTidyOptions(), AdditionalFileContents); + + EXPECT_EQ(ExpectedWarningCount, errors.size()); + return result; +} + +TEST(UsingInserterTest, ReusesExisting) { + EXPECT_EQ("#include \"foo.h\"\n" +"namespace {" +"using ::foo::func;\n" +"void f() { func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "namespace {" + "using ::foo::func;\n" + "void f() { f(); }" + "}", + 1)); +} + +TEST(UsingInserterTest, ReusesExistingGlobal) { + EXPECT_EQ("#include \"foo.h\"\n" +"using ::foo::func;\n" +"namespace {" +"void f() { func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "using ::foo::func;\n" + "namespace {" + "void f() { f(); }" + "}", + 1)); +} + +TEST(UsingInserterTest, AvoidsConflict) { + EXPECT_EQ("#include \"foo.h\"\n" +"namespace {" +"void f() { int func; ::foo::func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "namespace {" + "void f() { int func; f(); }" + "}", + 1)); +} + +} // namespace utils +} // namespace tidy +} // namespace clang Index: unittests/clang-tidy/NamespaceAliaserTest.cpp
[PATCH] D24997: [ClangTidy] Add UsingInserter and NamespaceAliaser
jbangert updated this revision to Diff 74311. https://reviews.llvm.org/D24997 Files: clang-tidy/utils/ASTUtils.cpp clang-tidy/utils/ASTUtils.h clang-tidy/utils/NamespaceAliaser.cpp clang-tidy/utils/NamespaceAliaser.h clang-tidy/utils/UsingInserter.cpp clang-tidy/utils/UsingInserter.h unittests/clang-tidy/NamespaceAliaserTest.cpp unittests/clang-tidy/UsingInserterTest.cpp Index: unittests/clang-tidy/UsingInserterTest.cpp === --- /dev/null +++ unittests/clang-tidy/UsingInserterTest.cpp @@ -0,0 +1,115 @@ +//=== UsingInserterTest.cpp - clang-tidy ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "../clang-tidy/utils/UsingInserter.h" + +#include "ClangTidyTest.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "gtest/gtest.h" + +namespace clang { +namespace tidy { +namespace utils { + +// Replace all function calls with calls to foo::func. Inserts using +// declarations as necessary. This checker is for testing only. It +// can only run on one test case (e.g. wih one SourceManager). +class InsertUsingCheck : public clang::tidy::ClangTidyCheck { +public: + using clang::tidy::ClangTidyCheck::ClangTidyCheck; + void registerMatchers(clang::ast_matchers::MatchFinder *Finder) override { +Finder->addMatcher(clang::ast_matchers::callExpr().bind("foo"), this); + } + void + check(const clang::ast_matchers::MatchFinder::MatchResult &Result) override { +if (!Inserter) + Inserter.reset(new UsingInserter(*Result.SourceManager, + Result.Context->getLangOpts())); + +const clang::CallExpr *Call = +Result.Nodes.getNodeAs("foo"); +assert(Call != nullptr && "Did not find node \"foo\""); +auto Hint = +Inserter->createUsingDeclaration(*Result.Context, *Call, "::foo::func"); + +if (Hint.hasValue()) + diag(Call->getLocStart(), "Fix for testing") << Hint.getValue(); + +diag(Call->getLocStart(), "insert call") +<< clang::FixItHint::CreateReplacement( + Call->getCallee()->getSourceRange(), + Inserter->getShortName(*Result.Context, *Call, "::foo::func")); + } + +private: + std::unique_ptr Inserter; +}; + +template +std::string runChecker(StringRef Code, int ExpectedWarningCount) { + std::map AdditionalFileContents = {{"foo.h", +"namespace foo {\n" +"namespace bar {\n" +"}\n" +"void func() { }\n" +"}"}}; + std::vector errors; + + std::string result = + test::runCheckOnCode(Code, &errors, "foo.cc", None, + ClangTidyOptions(), AdditionalFileContents); + + EXPECT_EQ(ExpectedWarningCount, errors.size()); + return result; +} + +TEST(UsingInserterTest, ReusesExisting) { + EXPECT_EQ("#include \"foo.h\"\n" +"namespace {" +"using ::foo::func;\n" +"void f() { func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "namespace {" + "using ::foo::func;\n" + "void f() { f(); }" + "}", + 1)); +} + +TEST(UsingInserterTest, ReusesExistingGlobal) { + EXPECT_EQ("#include \"foo.h\"\n" +"using ::foo::func;\n" +"namespace {" +"void f() { func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "using ::foo::func;\n" + "namespace {" + "void f() { f(); }" + "}", + 1)); +} + +TEST(UsingInserterTest, AvoidsConflict) { + EXPECT_EQ("#include \"foo.h\"\n" +"namespace {" +"void f() { int func; ::foo::func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "namespace {" + "void f() { int func; f(); }" + "}", + 1)); +} + +} // namespace utils +} // namespace tidy +} // namespace clang Index: unittests/clang-tidy/NamespaceAliaserTest.cpp
[PATCH] D24997: [ClangTidy] Add UsingInserter and NamespaceAliaser
jbangert marked an inline comment as done. jbangert added a comment. Thanks for the review! https://reviews.llvm.org/D24997 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D24997: [ClangTidy] Add UsingInserter and NamespaceAliaser
Apologies for the breakage. I investigated and it turns out my open-source checkout does not build clang-tidy. I have checked out llvm into ~/llvm, clang into ~/llvm/tools/clang and clang-extra-tools into ~/llvm/tools/clang/tools/extra. In ~/llvm-build I run cmake ../llvm && make -j 32 and it doesn't compile clang tidy. I also tried cmake -DCLANG_ENABLE_STATIC_ANALYZER=true ../llvm/ but that doesn't make a difference. Any ideas? On Wed, Oct 12, 2016 at 1:34 AM Haojian Wu wrote: > hokein added a comment. > > @jbangert, your patch broke the buildbot, and I reverted it in r283985. > You need to add the new source files to the CMakefile. (I saw other > compilation errors after I updated the cmake files, Could you take a look > on it? ) > > > Repository: > rL LLVM > > https://reviews.llvm.org/D24997 > > > > ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D24997: [ClangTidy] Add UsingInserter and NamespaceAliaser
jbangert removed rL LLVM as the repository for this revision. jbangert updated this revision to Diff 74737. Herald added subscribers: mgorny, beanz. https://reviews.llvm.org/D24997 Files: clang-tidy/utils/ASTUtils.cpp clang-tidy/utils/ASTUtils.h clang-tidy/utils/CMakeLists.txt clang-tidy/utils/NamespaceAliaser.cpp clang-tidy/utils/NamespaceAliaser.h clang-tidy/utils/UsingInserter.cpp clang-tidy/utils/UsingInserter.h unittests/clang-tidy/CMakeLists.txt unittests/clang-tidy/NamespaceAliaserTest.cpp unittests/clang-tidy/UsingInserterTest.cpp Index: unittests/clang-tidy/UsingInserterTest.cpp === --- /dev/null +++ unittests/clang-tidy/UsingInserterTest.cpp @@ -0,0 +1,115 @@ +//=== UsingInserterTest.cpp - clang-tidy ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "../clang-tidy/utils/UsingInserter.h" + +#include "ClangTidyTest.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "gtest/gtest.h" + +namespace clang { +namespace tidy { +namespace utils { + +// Replace all function calls with calls to foo::func. Inserts using +// declarations as necessary. This checker is for testing only. It +// can only run on one test case (e.g. wih one SourceManager). +class InsertUsingCheck : public clang::tidy::ClangTidyCheck { +public: + using clang::tidy::ClangTidyCheck::ClangTidyCheck; + void registerMatchers(clang::ast_matchers::MatchFinder *Finder) override { +Finder->addMatcher(clang::ast_matchers::callExpr().bind("foo"), this); + } + void + check(const clang::ast_matchers::MatchFinder::MatchResult &Result) override { +if (!Inserter) + Inserter.reset(new UsingInserter(*Result.SourceManager, + Result.Context->getLangOpts())); + +const clang::CallExpr *Call = +Result.Nodes.getNodeAs("foo"); +assert(Call != nullptr && "Did not find node \"foo\""); +auto Hint = +Inserter->createUsingDeclaration(*Result.Context, *Call, "::foo::func"); + +if (Hint.hasValue()) + diag(Call->getLocStart(), "Fix for testing") << Hint.getValue(); + +diag(Call->getLocStart(), "insert call") +<< clang::FixItHint::CreateReplacement( + Call->getCallee()->getSourceRange(), + Inserter->getShortName(*Result.Context, *Call, "::foo::func")); + } + +private: + std::unique_ptr Inserter; +}; + +template +std::string runChecker(StringRef Code, int ExpectedWarningCount) { + std::map AdditionalFileContents = {{"foo.h", +"namespace foo {\n" +"namespace bar {\n" +"}\n" +"void func() { }\n" +"}"}}; + std::vector errors; + + std::string result = + test::runCheckOnCode(Code, &errors, "foo.cc", None, + ClangTidyOptions(), AdditionalFileContents); + + EXPECT_EQ(ExpectedWarningCount, errors.size()); + return result; +} + +TEST(UsingInserterTest, ReusesExisting) { + EXPECT_EQ("#include \"foo.h\"\n" +"namespace {" +"using ::foo::func;\n" +"void f() { func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "namespace {" + "using ::foo::func;\n" + "void f() { f(); }" + "}", + 1)); +} + +TEST(UsingInserterTest, ReusesExistingGlobal) { + EXPECT_EQ("#include \"foo.h\"\n" +"using ::foo::func;\n" +"namespace {" +"void f() { func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "using ::foo::func;\n" + "namespace {" + "void f() { f(); }" + "}", + 1)); +} + +TEST(UsingInserterTest, AvoidsConflict) { + EXPECT_EQ("#include \"foo.h\"\n" +"namespace {" +"void f() { int func; ::foo::func(); }" +"}", +runChecker("#include \"foo.h\"\n" + "namespace {" + "void f() { int func; f(); }" + "}", + 1)); +} + +}
Re: [PATCH] D24997: [ClangTidy] Add UsingInserter and NamespaceAliaser
I figured out make clang-tidy. Compiles now (the typedef was the wrong way around, and i never noticed because make with the default target continued to work). Updated the diff. On Fri, Oct 14, 2016 at 12:49 PM Julian Bangert wrote: > Apologies for the breakage. I investigated and it turns out my open-source > checkout does not build clang-tidy. I have checked out llvm into ~/llvm, > clang into ~/llvm/tools/clang and clang-extra-tools into > ~/llvm/tools/clang/tools/extra. > In ~/llvm-build I run cmake ../llvm && make -j 32 and it doesn't compile > clang tidy. I also tried cmake -DCLANG_ENABLE_STATIC_ANALYZER=true > ../llvm/ but that doesn't make a difference. Any ideas? > > > On Wed, Oct 12, 2016 at 1:34 AM Haojian Wu wrote: > > hokein added a comment. > > @jbangert, your patch broke the buildbot, and I reverted it in r283985. > You need to add the new source files to the CMakefile. (I saw other > compilation errors after I updated the cmake files, Could you take a look > on it? ) > > > Repository: > rL LLVM > > https://reviews.llvm.org/D24997 > > > > ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Add hasInClassInitializer matcher
This adds a matcher for C++ in Class initializers. --- include/clang/ASTMatchers/ASTMatchers.h | 14 ++ unittests/ASTMatchers/ASTMatchersTest.cpp | 7 +++ 2 files changed, 21 insertions(+) diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 21a4969..6b0a5d6 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -2848,6 +2848,20 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) { return Node.isMemberInitializer(); } +/// \brief Matches a C++ inClassInitializer matching the given matcher +/// +/// Given: +/// \code +/// class A { int x = 1; }; +/// \endcode +/// +/// \c hasInClassInitializer(integerLiteral()) matches int x = 1 +AST_MATCHER_P(FieldDecl, hasInClassInitializer, + internal::Matcher, InnerMatcher) { + return Node.hasInClassInitializer() + && InnerMatcher.matches(*Node.getInClassInitializer(), Finder, Builder); +} + /// \brief Matches any argument of a call expression or a constructor call /// expression. /// diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp index 133dc70..15776d7 100644 --- a/unittests/ASTMatchers/ASTMatchersTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTest.cpp @@ -2402,6 +2402,13 @@ TEST(HasAnyConstructorInitializer, IsBaseInitializer) { hasName("E"); } +TEST(Matcher, inClassInitializer) { + EXPECT_TRUE(matches("class A{ int x = 1; };", + fieldDecl(hasInClassInitializer(integerLiteral(); + EXPECT_FALSE(matches("class A{ int x; void b() { x = 1; } };", + fieldDecl(hasInClassInitializer(integerLiteral(); +} + TEST(Matcher, NewExpression) { StatementMatcher New = cxxNewExpr(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: Add hasInClassInitializer matcher
In case my MUA messed up the formatting, see the attached On Wed, Mar 2, 2016 at 1:14 PM Julian Bangert wrote: > Here is a patch to SVN with the requested changes (documentation, renamed > and added to registry): > > Index: docs/LibASTMatchersReference.html > === > --- docs/LibASTMatchersReference.html (revision 262512) > +++ docs/LibASTMatchersReference.html (working copy) > @@ -2412,7 +2412,7 @@ > > > > -Matcher<http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html";>NamedDecl> class="name" onclick="toggle('hasName0')"> name="hasName0Anchor">hasNamestd::string Name > +Matcher<http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html";>NamedDecl> class="name" onclick="toggle('hasName0')"> name="hasName0Anchor">hasNamestd::string Name > Matches NamedDecl > nodes that have the specified name. > > Supports specifying enclosing namespaces or classes by prefixing the name > @@ -3107,7 +3107,7 @@ > > This matcher is only provided as a performance optimization of hasName. > hasAnyName(a, b, c) > - is equivalent but faster than > + is equivalent to, but faster than > anyOf(hasName(a), hasName(b), hasName(c)) > > > @@ -4180,6 +4180,16 @@ > > > > +Matcher<http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html";>FieldDecl> class="name" onclick="toggle('hasDefaultMemberInitializer0')"> name="hasDefaultMemberInitializer0Anchor">hasDefaultMemberInitializerMatcher< href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr> > InnerMatcher > + id="hasDefaultMemberInitializer0">Matches a C++ default member > initializer matching the given matcher > + > +Given: > + class A { int x = 1; }; > + > +hasDefaultMemberInitializer(integerLiteral()) matches int x = 1 > + > + > + > Matcher<http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html";>ForStmt> class="name" onclick="toggle('hasBody1')"> name="hasBody1Anchor">hasBodyMatcher<http://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt> > InnerMatcher > Matches a 'for', > 'while', 'do while' statement or a function > definition that has a given body. > Index: include/clang/ASTMatchers/ASTMatchers.h > === > --- include/clang/ASTMatchers/ASTMatchers.h (revision 262512) > +++ include/clang/ASTMatchers/ASTMatchers.h (working copy) > @@ -2848,6 +2848,20 @@ >return Node.isMemberInitializer(); > } > > +/// \brief Matches a C++ default member initializer matching the given > matcher > +/// > +/// Given: > +/// \code > +/// class A { int x = 1; }; > +/// \endcode > +/// > +/// \c hasDefaultMemberInitializer(integerLiteral()) matches int x = 1 > +AST_MATCHER_P(FieldDecl, hasDefaultMemberInitializer, > + internal::Matcher, InnerMatcher) { > + return Node.hasInClassInitializer() > + && InnerMatcher.matches(*Node.getInClassInitializer(), Finder, > Builder); > +} > + > /// \brief Matches any argument of a call expression or a constructor call > /// expression. > /// > Index: lib/ASTMatchers/Dynamic/Registry.cpp > === > --- lib/ASTMatchers/Dynamic/Registry.cpp (revision 262512) > +++ lib/ASTMatchers/Dynamic/Registry.cpp (working copy) > @@ -210,6 +210,7 @@ >REGISTER_MATCHER(hasDeclaration); >REGISTER_MATCHER(hasDeclContext); >REGISTER_MATCHER(hasDeducedType); > + REGISTER_MATCHER(hasDefaultMemberInitializer); >REGISTER_MATCHER(hasDescendant); >REGISTER_MATCHER(hasDestinationType); >REGISTER_MATCHER(hasEitherOperand); > Index: unittests/ASTMatchers/ASTMatchersTest.cpp > === > --- unittests/ASTMatchers/ASTMatchersTest.cpp (revision 262512) > +++ unittests/ASTMatchers/ASTMatchersTest.cpp (working copy) > @@ -2402,6 +2402,13 @@ > hasName("E"); > } > > +TEST(Matcher, inDefaultMemberInitializer) { > + EXPECT_TRUE(matches("class A{ int x = 1; };", > + > fieldDecl(hasDefaultMemberInitializer(integerLiteral(); > + EXPECT_TRUE(notMatches("class A{ int x; void b() { x = 1; } };", > + > fieldDecl(hasDefaultMemberInitializer(integerLiteral(); > +} > + > TEST(Matcher, NewExpression) { >StatementMatcher New = cxxNewExpr(); > > > > On Wed, Mar 2, 2016
Re: Add hasInClassInitializer matcher
Here is a patch to SVN with the requested changes (documentation, renamed and added to registry): Index: docs/LibASTMatchersReference.html === --- docs/LibASTMatchersReference.html (revision 262512) +++ docs/LibASTMatchersReference.html (working copy) @@ -2412,7 +2412,7 @@ -Matcher<http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html";>NamedDecl>hasNamestd::string Name +Matcher<http://clang.llvm.org/doxygen/classclang_1_1NamedDecl.html";>NamedDecl>hasNamestd::string Name Matches NamedDecl nodes that have the specified name. Supports specifying enclosing namespaces or classes by prefixing the name @@ -3107,7 +3107,7 @@ This matcher is only provided as a performance optimization of hasName. hasAnyName(a, b, c) - is equivalent but faster than + is equivalent to, but faster than anyOf(hasName(a), hasName(b), hasName(c)) @@ -4180,6 +4180,16 @@ +Matcher<http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html";>FieldDecl>hasDefaultMemberInitializerMatcher<http://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr> InnerMatcher +Matches a C++ default member initializer matching the given matcher + +Given: + class A { int x = 1; }; + +hasDefaultMemberInitializer(integerLiteral()) matches int x = 1 + + + Matcher<http://clang.llvm.org/doxygen/classclang_1_1ForStmt.html";>ForStmt>hasBodyMatcher<http://clang.llvm.org/doxygen/classclang_1_1Stmt.html";>Stmt> InnerMatcher Matches a 'for', 'while', 'do while' statement or a function definition that has a given body. Index: include/clang/ASTMatchers/ASTMatchers.h === --- include/clang/ASTMatchers/ASTMatchers.h (revision 262512) +++ include/clang/ASTMatchers/ASTMatchers.h (working copy) @@ -2848,6 +2848,20 @@ return Node.isMemberInitializer(); } +/// \brief Matches a C++ default member initializer matching the given matcher +/// +/// Given: +/// \code +/// class A { int x = 1; }; +/// \endcode +/// +/// \c hasDefaultMemberInitializer(integerLiteral()) matches int x = 1 +AST_MATCHER_P(FieldDecl, hasDefaultMemberInitializer, + internal::Matcher, InnerMatcher) { + return Node.hasInClassInitializer() + && InnerMatcher.matches(*Node.getInClassInitializer(), Finder, Builder); +} + /// \brief Matches any argument of a call expression or a constructor call /// expression. /// Index: lib/ASTMatchers/Dynamic/Registry.cpp === --- lib/ASTMatchers/Dynamic/Registry.cpp (revision 262512) +++ lib/ASTMatchers/Dynamic/Registry.cpp (working copy) @@ -210,6 +210,7 @@ REGISTER_MATCHER(hasDeclaration); REGISTER_MATCHER(hasDeclContext); REGISTER_MATCHER(hasDeducedType); + REGISTER_MATCHER(hasDefaultMemberInitializer); REGISTER_MATCHER(hasDescendant); REGISTER_MATCHER(hasDestinationType); REGISTER_MATCHER(hasEitherOperand); Index: unittests/ASTMatchers/ASTMatchersTest.cpp === --- unittests/ASTMatchers/ASTMatchersTest.cpp (revision 262512) +++ unittests/ASTMatchers/ASTMatchersTest.cpp (working copy) @@ -2402,6 +2402,13 @@ hasName("E"); } +TEST(Matcher, inDefaultMemberInitializer) { + EXPECT_TRUE(matches("class A{ int x = 1; };", + fieldDecl(hasDefaultMemberInitializer(integerLiteral(); + EXPECT_TRUE(notMatches("class A{ int x; void b() { x = 1; } };", + fieldDecl(hasDefaultMemberInitializer(integerLiteral(); +} + TEST(Matcher, NewExpression) { StatementMatcher New = cxxNewExpr(); On Wed, Mar 2, 2016 at 12:23 PM Richard Smith wrote: > On Wed, Mar 2, 2016 at 12:06 PM, Aaron Ballman via cfe-commits > wrote: > > On Wed, Mar 2, 2016 at 2:01 PM, Julian Bangert via cfe-commits > > wrote: > >> This adds a matcher for C++ in Class initializers. > >> > >> --- > >> include/clang/ASTMatchers/ASTMatchers.h | 14 ++ > >> unittests/ASTMatchers/ASTMatchersTest.cpp | 7 +++ > >> 2 files changed, 21 insertions(+) > >> > >> diff --git a/include/clang/ASTMatchers/ASTMatchers.h > >> b/include/clang/ASTMatchers/ASTMatchers.h > > > > Please also generate the AST matcher documentation by running > > dump-ast-matchers.py and register the function in Registry.cpp. Also, > > if you can provide an svn patch instead of a git patch, it would be > > appreciated (especially if you need someone to commit on your behalf). > > Please also name this "hasDefaultMemberInitializer" to match the C++ > standard's (fairly new) name for this feature. We'll rename Clang's > internals to match at some point soon. > > >> index