Add AST matchers for handling bit-fields and narrowing based on their width.

llvm-svn: 274652
This commit is contained in:
Aaron Ballman 2016-07-06 18:25:16 +00:00
parent 78fa242ec2
commit 5c574341f5
4 changed files with 70 additions and 1 deletions

View File

@ -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)
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('hasBitWidth0')"><a name="hasBitWidth0Anchor">hasBitWidth</a></td><td>unsigned Width</td></tr>
<tr><td colspan="4" class="doc" id="hasBitWidth0"><pre>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;'.
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>&gt;</td><td class="name" onclick="toggle('isBitField0')"><a name="isBitField0Anchor">isBitField</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isBitField0"><pre>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;'.
</pre></td></tr>
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FloatingLiteral.html">FloatingLiteral</a>&gt;</td><td class="name" onclick="toggle('equals1')"><a name="equals1Anchor">equals</a></td><td>ValueT Value</td></tr>
<tr><td colspan="4" class="doc" id="equals1"><pre>Matches literals that are equal to the given value.

View File

@ -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) {

View File

@ -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);

View File

@ -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(