[clang] Add isTrivial() and isTriviallyCopyable() AST matchers (PR #90634)

via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 30 10:40:13 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (higher-performance)

<details>
<summary>Changes</summary>

There are currently no AST matchers for the equivalent of `std::is_trivial`, `std::is_trivially_default_constructible`, `std::is_trivially_copyable`, and the like.

This pull request adds matchers to check if records and their member functions are trivial.

It does _not_ attempt to handle other trivial entities (such as pointers).

---
Full diff: https://github.com/llvm/llvm-project/pull/90634.diff


2 Files Affected:

- (modified) clang/include/clang/ASTMatchers/ASTMatchers.h (+37) 
- (modified) clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (+27) 


``````````diff
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 2f71053d030f68..f8529105f8d034 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -5440,6 +5440,43 @@ AST_MATCHER(FunctionDecl, isDefaulted) {
   return Node.isDefaulted();
 }
 
+/// Matches trivial methods and types.
+///
+/// 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:
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 87774b00956a5a..9c648588ba970c 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1849,6 +1849,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;

``````````

</details>


https://github.com/llvm/llvm-project/pull/90634


More information about the cfe-commits mailing list