Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -5444,6 +5444,43 @@ AST_MATCHER(FunctionDecl, isDefaulted) {
return Node.isDefaulted();
}

/// Matches trivial methods and types.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think is actually matches types, but rather classes or CXXRecordDecl.
And the question is: should it?

I believe we could extend this matcher to also work on types and type locs.
Do you see any downsides to that? (same for the other matcher)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, yeah. I don't think we want to support that since the other matchers don't do that either (e.g., isSameOrDerivedFrom). That seems like a higher-level design change that should be made uniformly if it's desired.

///
/// Given:
/// \code
/// class A { A(); };
/// A::A() = default;
/// class B { B() = default; };
/// \endcode
/// cxxMethodDecl(isTrivial())
/// matches the declaration of B, but not A.
AST_POLYMORPHIC_MATCHER(isTrivial,
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXMethodDecl,
CXXRecordDecl)) {
if (const auto *E = dyn_cast<CXXMethodDecl>(&Node))
return E->isTrivial();
if (const auto *E = dyn_cast<CXXRecordDecl>(&Node)) {
const auto *Def = Node.getDefinition();
return Def && Def->isTrivial();
}
return false;
}

/// Matches trivially copyable types.
///
/// Given:
/// \code
/// class A { A(const A &); };
/// A::A(const A &) = default;
/// class B { B(const B &) = default; };
/// \endcode
/// cxxMethodDecl(isTriviallyCopyable())
/// matches the declaration of B, but not A.
AST_MATCHER(CXXRecordDecl, isTriviallyCopyable) {
CXXRecordDecl *Def = Node.getDefinition();
return Def && Def->isTriviallyCopyable();
}

/// Matches weak function declarations.
///
/// Given:
Expand Down
27 changes: 27 additions & 0 deletions clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1850,6 +1850,33 @@ TEST_P(ASTMatchersTest, IsDeleted) {
functionDecl(hasName("Func"), isDeleted())));
}

TEST_P(ASTMatchersTest, IsTrivial) {
if (!GetParam().isCXX()) {
return;
}

EXPECT_TRUE(notMatches("class A { A(); };",
cxxRecordDecl(hasName("A"), isTrivial())));
EXPECT_TRUE(matches("class B { B() = default; };",
cxxRecordDecl(hasName("B"), isTrivial())));

EXPECT_TRUE(notMatches("class A { ~A(); }; A::~A() = default;",
cxxMethodDecl(hasName("~A"), isTrivial())));
EXPECT_TRUE(matches("class B { ~B() = default; };",
cxxMethodDecl(hasName("~B"), isTrivial())));
}

TEST_P(ASTMatchersTest, IsTriviallyCopyable) {
if (!GetParam().isCXX()) {
return;
}

EXPECT_TRUE(notMatches("class A { ~A(); }; A::~A() = default;",
cxxRecordDecl(hasName("A"), isTriviallyCopyable())));
EXPECT_TRUE(matches("class B { ~B() = default; };",
cxxRecordDecl(hasName("B"), isTriviallyCopyable())));
}

TEST_P(ASTMatchersTest, IsNoThrow_DynamicExceptionSpec) {
if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
return;
Expand Down