From 5c574341f505fbf489d1c6b848c13b7538d57dfe 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. llvm-svn: 274652 --- clang/docs/LibASTMatchersReference.html | 29 ++++++++++++++++- clang/include/clang/ASTMatchers/ASTMatchers.h | 32 +++++++++++++++++++ clang/lib/ASTMatchers/Dynamic/Registry.cpp | 2 ++ .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 8 +++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index fff5366775cd..a8a47d5b54bd 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/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/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 5ba154d335ae..a5465189930c 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/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/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index b6479b093109..d8ddf55733fd 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/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/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 7deed85440d0..28b462e746f0 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/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(