From 7e3d158f1baee9fe6ce34c89b09b54e68c26d077 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Wed, 6 Jul 2016 18:25:16 +0000 Subject: [PATCH] Add AST matchers for handling bit-fields and narrowing based on their width. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274652 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersReference.html | 29 ++++++++++++++++- include/clang/ASTMatchers/ASTMatchers.h | 32 +++++++++++++++++++ lib/ASTMatchers/Dynamic/Registry.cpp | 2 ++ .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 8 +++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index fff5366775..a8a47d5b54 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -1453,7 +1453,7 @@ c and d. Given enum C { Green }; - enum S { Red }; + enum class S { Red }; C c; S s; @@ -2418,6 +2418,33 @@ designatorCountIs(2) +Matcher<FieldDecl>hasBitWidthunsigned Width +
Matches non-static data members that are bit-fields.
+
+Given
+  class C {
+    int a : 2;
+    int b : 4;
+    int c : 2;
+  };
+fieldDecl(isBitField())
+  matches 'int a;' and 'int c;' but not 'int b;'.
+
+ + +Matcher<FieldDecl>isBitField +
Matches non-static data members that are bit-fields.
+
+Given
+  class C {
+    int a : 2;
+    int b;
+  };
+fieldDecl(isBitField())
+  matches 'int a;' but not 'int b;'.
+
+ + Matcher<FloatingLiteral>equalsValueT Value
Matches literals that are equal to the given value.
 
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 5ba154d335..a546518993 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -519,6 +519,38 @@ AST_MATCHER(Decl, isPrivate) {
   return Node.getAccess() == AS_private;
 }
 
+/// \brief Matches non-static data members that are bit-fields.
+///
+/// Given
+/// \code
+///   class C {
+///     int a : 2;
+///     int b;
+///   };
+/// \endcode
+/// fieldDecl(isBitField())
+///   matches 'int a;' but not 'int b;'.
+AST_MATCHER(FieldDecl, isBitField) {
+  return Node.isBitField();
+}
+
+/// \brief Matches non-static data members that are bit-fields.
+///
+/// Given
+/// \code
+///   class C {
+///     int a : 2;
+///     int b : 4;
+///     int c : 2;
+///   };
+/// \endcode
+/// fieldDecl(isBitField())
+///   matches 'int a;' and 'int c;' but not 'int b;'.
+AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) {
+  return Node.isBitField() &&
+         Node.getBitWidthValue(Finder->getASTContext()) == Width;
+}
+
 /// \brief Matches a declaration that has been implicitly added
 /// by the compiler (eg. implicit default/copy constructors).
 AST_MATCHER(Decl, isImplicit) {
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index b6479b0931..d8ddf55733 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -208,6 +208,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(hasAttr);
   REGISTER_MATCHER(hasAutomaticStorageDuration);
   REGISTER_MATCHER(hasBase);
+  REGISTER_MATCHER(hasBitWidth);
   REGISTER_MATCHER(hasBody);
   REGISTER_MATCHER(hasCanonicalType);
   REGISTER_MATCHER(hasCaseConstant);
@@ -283,6 +284,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(isAnyPointer);
   REGISTER_MATCHER(isArrow);
   REGISTER_MATCHER(isBaseInitializer);
+  REGISTER_MATCHER(isBitField);
   REGISTER_MATCHER(isCatchAll);
   REGISTER_MATCHER(isClass);
   REGISTER_MATCHER(isConst);
diff --git a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 7deed85440..28b462e746 100644
--- a/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -1366,6 +1366,14 @@ TEST(Member, MatchesMember) {
     memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
 }
 
+TEST(Member, BitFields) {
+  EXPECT_TRUE(matches("class C { int a : 2; int b; };",
+                      fieldDecl(isBitField(), hasName("a"))));
+  EXPECT_TRUE(notMatches("class C { int a : 2; int b; };",
+                         fieldDecl(isBitField(), hasName("b"))));
+  EXPECT_TRUE(matches("class C { int a : 2; int b : 4; };",
+                      fieldDecl(isBitField(), hasBitWidth(2), hasName("a"))));
+}
 
 TEST(Member, UnderstandsAccess) {
   EXPECT_TRUE(matches(
-- 
2.50.1