[clang] a156a0e - [ASTMatchers] Add hasPlacementArg and hasAnyPlacementArg traversal matcher for CXXNewExpr
Nathan James via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 30 02:16:11 PST 2020
Author: Nathan James
Date: 2020-01-30T10:16:04Z
New Revision: a156a0e28df4751f812c84437321339c2eb33af3
URL: https://github.com/llvm/llvm-project/commit/a156a0e28df4751f812c84437321339c2eb33af3
DIFF: https://github.com/llvm/llvm-project/commit/a156a0e28df4751f812c84437321339c2eb33af3.diff
LOG: [ASTMatchers] Add hasPlacementArg and hasAnyPlacementArg traversal matcher for CXXNewExpr
Summary: Adds new traversal matchers called `hasPlacementArg` and `hasAnyPlacementArg` that matches on arguments to `placement new` operators.
Reviewers: aaron.ballman
Reviewed By: aaron.ballman
Subscribers: merge_guards_bot, mehdi_amini, hiraditya, steven_wu, dexonsmith, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73562
Added:
Modified:
clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp
clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
clang/docs/LibASTMatchersReference.html
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/lib/ASTMatchers/Dynamic/Registry.cpp
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp
index 48eee8e6949d..749b8f192aeb 100644
--- a/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cert/DefaultOperatorNewAlignmentCheck.cpp
@@ -16,16 +16,13 @@ namespace clang {
namespace tidy {
namespace cert {
-AST_MATCHER(CXXNewExpr, isPlacementNew) {
- return Node.getNumPlacementArgs() > 0;
-}
-
void DefaultOperatorNewAlignmentCheck::registerMatchers(MatchFinder *Finder) {
// Check not applicable in C++17 (or newer).
if (getLangOpts().CPlusPlus17)
return;
- Finder->addMatcher(cxxNewExpr(unless(isPlacementNew())).bind("new"), this);
+ Finder->addMatcher(
+ cxxNewExpr(unless(hasAnyPlacementArg(anything()))).bind("new"), this);
}
void DefaultOperatorNewAlignmentCheck::check(
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
index 12d3f6290394..20a7c45c7cbc 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -84,6 +84,8 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
auto CanCallCtor = unless(has(ignoringImpCasts(
cxxConstructExpr(hasDeclaration(decl(unless(isPublic())))))));
+ auto IsPlacement = hasAnyPlacementArg(anything());
+
Finder->addMatcher(
cxxBindTemporaryExpr(has(ignoringParenImpCasts(
cxxConstructExpr(
@@ -91,7 +93,7 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
hasArgument(0,
cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
equalsBoundNode(PointerType))))),
- CanCallCtor)
+ CanCallCtor, unless(IsPlacement))
.bind(NewExpression)),
unless(isInTemplateInstantiation()))
.bind(ConstructorCall)))),
@@ -101,7 +103,9 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
cxxMemberCallExpr(
thisPointerType(getSmartPointerTypeMatcher()),
callee(cxxMethodDecl(hasName("reset"))),
- hasArgument(0, cxxNewExpr(CanCallCtor).bind(NewExpression)),
+ hasArgument(
+ 0,
+ cxxNewExpr(CanCallCtor, unless(IsPlacement)).bind(NewExpression)),
unless(isInTemplateInstantiation()))
.bind(ResetCall),
this);
@@ -119,8 +123,6 @@ void MakeSmartPtrCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Type = Result.Nodes.getNodeAs<QualType>(PointerType);
const auto *New = Result.Nodes.getNodeAs<CXXNewExpr>(NewExpression);
- if (New->getNumPlacementArgs() != 0)
- return;
// Skip when this is a new-expression with `auto`, e.g. new auto(1)
if (New->getType()->getPointeeType()->getContainedAutoType())
return;
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index 907353d1d9bb..95328dcd82eb 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -5311,6 +5311,16 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('hasAnyPlacementArg0')"><a name="hasAnyPlacementArg0Anchor">hasAnyPlacementArg</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasAnyPlacementArg0"><pre>Matches any placement new expression arguments.
+
+Given:
+ MyClass *p1 = new (Storage) MyClass();
+cxxNewExpr(hasAnyPlacementArg(anything()))
+ matches the expression 'new (Storage, 16) MyClass()'.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('hasArraySize0')"><a name="hasArraySize0Anchor">hasArraySize</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasArraySize0"><pre>Matches array new expressions with a given array size.
@@ -5355,6 +5365,16 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXNewExpr.html">CXXNewExpr</a>></td><td class="name" onclick="toggle('hasPlacementArg0')"><a name="hasPlacementArg0Anchor">hasPlacementArg</a></td><td>unsigned Index, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="hasPlacementArg0"><pre>Matches placement new expression arguments.
+
+Given:
+ MyClass *p1 = new (Storage, 16) MyClass();
+cxxNewExpr(hasPlacementArg(1, integerLiteral(equals(16))))
+ matches the expression 'new (Storage, 16) MyClass()'.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>></td><td class="name" onclick="toggle('hasMethod0')"><a name="hasMethod0Anchor">hasMethod</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>> InnerMatcher</td></tr>
<tr><td colspan="4" class="doc" id="hasMethod0"><pre>Matches the first method of a class or struct that satisfies InnerMatcher.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index f105586a4d62..4fdbf3e3ba6e 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -6783,6 +6783,35 @@ AST_MATCHER(CXXNewExpr, isArray) {
return Node.isArray();
}
+/// Matches placement new expression arguments.
+///
+/// Given:
+/// \code
+/// MyClass *p1 = new (Storage, 16) MyClass();
+/// \endcode
+/// cxxNewExpr(hasPlacementArg(1, integerLiteral(equals(16))))
+/// matches the expression 'new (Storage, 16) MyClass()'.
+AST_MATCHER_P2(CXXNewExpr, hasPlacementArg, unsigned, Index,
+ internal::Matcher<Expr>, InnerMatcher) {
+ return Node.getNumPlacementArgs() > Index &&
+ InnerMatcher.matches(*Node.getPlacementArg(Index), Finder, Builder);
+}
+
+/// Matches any placement new expression arguments.
+///
+/// Given:
+/// \code
+/// MyClass *p1 = new (Storage) MyClass();
+/// \endcode
+/// cxxNewExpr(hasAnyPlacementArg(anything()))
+/// matches the expression 'new (Storage, 16) MyClass()'.
+AST_MATCHER_P(CXXNewExpr, hasAnyPlacementArg, internal::Matcher<Expr>,
+ InnerMatcher) {
+ return llvm::any_of(Node.placement_arguments(), [&](const Expr *Arg) {
+ return InnerMatcher.matches(*Arg, Finder, Builder);
+ });
+}
+
/// Matches array new expressions with a given array size.
///
/// Given:
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index 4fd5abffc791..8c6dcfaaf52f 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -243,6 +243,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasAnyDeclaration);
REGISTER_MATCHER(hasAnyName);
REGISTER_MATCHER(hasAnyParameter);
+ REGISTER_MATCHER(hasAnyPlacementArg);
REGISTER_MATCHER(hasAnySelector);
REGISTER_MATCHER(hasAnySubstatement);
REGISTER_MATCHER(hasAnyTemplateArgument);
@@ -304,6 +305,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(hasReceiverType);
REGISTER_MATCHER(hasReplacementType);
REGISTER_MATCHER(hasReturnValue);
+ REGISTER_MATCHER(hasPlacementArg);
REGISTER_MATCHER(hasSelector);
REGISTER_MATCHER(hasSingleDecl);
REGISTER_MATCHER(hasSize);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 29f30cb658a6..4afff6b50fa2 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -3124,5 +3124,45 @@ TEST(ClassTemplateSpecializationDecl, HasSpecializedTemplate) {
EXPECT_TRUE(notMatches("template<typename T> class A {};", Matcher));
}
+TEST(CXXNewExpr, Array) {
+ StatementMatcher NewArray = cxxNewExpr(isArray());
+
+ EXPECT_TRUE(matches("void foo() { int *Ptr = new int[10]; }", NewArray));
+ EXPECT_TRUE(notMatches("void foo() { int *Ptr = new int; }", NewArray));
+
+ StatementMatcher NewArraySize10 =
+ cxxNewExpr(hasArraySize(integerLiteral(equals(10))));
+ EXPECT_TRUE(
+ matches("void foo() { int *Ptr = new int[10]; }", NewArraySize10));
+ EXPECT_TRUE(
+ notMatches("void foo() { int *Ptr = new int[20]; }", NewArraySize10));
+}
+
+TEST(CXXNewExpr, PlacementArgs) {
+ StatementMatcher IsPlacementNew = cxxNewExpr(hasAnyPlacementArg(anything()));
+
+ EXPECT_TRUE(matches(R"(
+ void* operator new(decltype(sizeof(void*)), void*);
+ int *foo(void* Storage) {
+ return new (Storage) int;
+ })",
+ IsPlacementNew));
+
+ EXPECT_TRUE(matches(R"(
+ void* operator new(decltype(sizeof(void*)), void*, unsigned);
+ int *foo(void* Storage) {
+ return new (Storage, 16) int;
+ })",
+ cxxNewExpr(hasPlacementArg(
+ 1, ignoringImpCasts(integerLiteral(equals(16)))))));
+
+ EXPECT_TRUE(notMatches(R"(
+ void* operator new(decltype(sizeof(void*)), void*);
+ int *foo(void* Storage) {
+ return new int;
+ })",
+ IsPlacementNew));
+}
+
} // namespace ast_matchers
} // namespace clang
More information about the cfe-commits
mailing list