forked from OSchip/llvm-project
Add an AST matcher for string-literal length
Summary: This patch is adding support for a matcher to check string literal length. This matcher is used in clang-tidy checkers and is part of this refactoring: see: http://reviews.llvm.org/D19841 Reviewers: sbenza, klimek, aaron.ballman Subscribers: alexfh, klimek, cfe-commits Differential Revision: http://reviews.llvm.org/D19876 llvm-svn: 269274
This commit is contained in:
parent
33e694a807
commit
3588be7fa1
|
@ -644,7 +644,8 @@ Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral),
|
|||
though.
|
||||
|
||||
Example matches 'a', L'a'
|
||||
char ch = 'a'; wchar_t chw = L'a';
|
||||
char ch = 'a';
|
||||
wchar_t chw = L'a';
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
|
@ -652,7 +653,8 @@ Example matches 'a', L'a'
|
|||
<tr><td colspan="4" class="doc" id="compoundLiteralExpr0"><pre>Matches compound (i.e. non-scalar) literals
|
||||
|
||||
Example match: {1}, (1, 2)
|
||||
int array[4] = {1}; vector int myvec = (vector int)(1, 2);
|
||||
int array[4] = {1};
|
||||
vector int myvec = (vector int)(1, 2);
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
|
@ -1217,7 +1219,8 @@ Example match: ({ int X = 4; X; })
|
|||
<tr><td colspan="4" class="doc" id="stringLiteral0"><pre>Matches string literals (also matches wide string literals).
|
||||
|
||||
Example matches "abcd", L"abcd"
|
||||
char *s = "abcd"; wchar_t *ws = L"abcd"
|
||||
char *s = "abcd";
|
||||
wchar_t *ws = L"abcd";
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
|
@ -2191,14 +2194,19 @@ compoundStmt(statementCountIs(0)))
|
|||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ConstantArrayType.html">ConstantArrayType</a>></td><td class="name" onclick="toggle('hasSize0')"><a name="hasSize0Anchor">hasSize</a></td><td>unsigned N</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasSize0"><pre>Matches ConstantArrayType nodes that have the specified size.
|
||||
<tr><td colspan="4" class="doc" id="hasSize0"><pre>Matches nodes that have the specified size.
|
||||
|
||||
Given
|
||||
int a[42];
|
||||
int b[2 * 21];
|
||||
int c[41], d[43];
|
||||
char *s = "abcd";
|
||||
wchar_t *ws = L"abcd";
|
||||
char *w = "a";
|
||||
constantArrayType(hasSize(42))
|
||||
matches "int a[42]" and "int b[2 * 21]"
|
||||
stringLiteral(hasSize(4))
|
||||
matches "abcd", L"abcd"
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
|
@ -2955,6 +2963,23 @@ Usable as: Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1StringLiteral.html">StringLiteral</a>></td><td class="name" onclick="toggle('hasSize1')"><a name="hasSize1Anchor">hasSize</a></td><td>unsigned N</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="hasSize1"><pre>Matches nodes that have the specified size.
|
||||
|
||||
Given
|
||||
int a[42];
|
||||
int b[2 * 21];
|
||||
int c[41], d[43];
|
||||
char *s = "abcd";
|
||||
wchar_t *ws = L"abcd";
|
||||
char *w = "a";
|
||||
constantArrayType(hasSize(42))
|
||||
matches "int a[42]" and "int b[2 * 21]"
|
||||
stringLiteral(hasSize(4))
|
||||
matches "abcd", L"abcd"
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>></td><td class="name" onclick="toggle('isDefinition0')"><a name="isDefinition0Anchor">isDefinition</a></td><td></td></tr>
|
||||
<tr><td colspan="4" class="doc" id="isDefinition0"><pre>Matches if a declaration has a body attached.
|
||||
|
||||
|
|
|
@ -1560,7 +1560,8 @@ const internal::VariadicDynCastAllOfMatcher<
|
|||
///
|
||||
/// Example matches "abcd", L"abcd"
|
||||
/// \code
|
||||
/// char *s = "abcd"; wchar_t *ws = L"abcd"
|
||||
/// char *s = "abcd";
|
||||
/// wchar_t *ws = L"abcd";
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Stmt,
|
||||
|
@ -1573,7 +1574,8 @@ const internal::VariadicDynCastAllOfMatcher<
|
|||
///
|
||||
/// Example matches 'a', L'a'
|
||||
/// \code
|
||||
/// char ch = 'a'; wchar_t chw = L'a';
|
||||
/// char ch = 'a';
|
||||
/// wchar_t chw = L'a';
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Stmt,
|
||||
|
@ -1609,7 +1611,8 @@ const internal::VariadicDynCastAllOfMatcher<
|
|||
///
|
||||
/// Example match: {1}, (1, 2)
|
||||
/// \code
|
||||
/// int array[4] = {1}; vector int myvec = (vector int)(1, 2);
|
||||
/// int array[4] = {1};
|
||||
/// vector int myvec = (vector int)(1, 2);
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Stmt,
|
||||
|
@ -4228,18 +4231,26 @@ AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement,
|
|||
/// matches "int a[2]"
|
||||
AST_TYPE_MATCHER(ConstantArrayType, constantArrayType);
|
||||
|
||||
/// \brief Matches \c ConstantArrayType nodes that have the specified size.
|
||||
/// \brief Matches nodes that have the specified size.
|
||||
///
|
||||
/// Given
|
||||
/// \code
|
||||
/// int a[42];
|
||||
/// int b[2 * 21];
|
||||
/// int c[41], d[43];
|
||||
/// char *s = "abcd";
|
||||
/// wchar_t *ws = L"abcd";
|
||||
/// char *w = "a";
|
||||
/// \endcode
|
||||
/// constantArrayType(hasSize(42))
|
||||
/// matches "int a[42]" and "int b[2 * 21]"
|
||||
AST_MATCHER_P(ConstantArrayType, hasSize, unsigned, N) {
|
||||
return Node.getSize() == N;
|
||||
/// stringLiteral(hasSize(4))
|
||||
/// matches "abcd", L"abcd"
|
||||
AST_POLYMORPHIC_MATCHER_P(hasSize,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(ConstantArrayType,
|
||||
StringLiteral),
|
||||
unsigned, N) {
|
||||
return internal::HasSizeMatcher<NodeType>::hasSize(Node, N);
|
||||
}
|
||||
|
||||
/// \brief Matches C++ arrays whose size is a value-dependent expression.
|
||||
|
|
|
@ -1650,6 +1650,19 @@ inline const Stmt *GetBodyMatcher<FunctionDecl>::get(const FunctionDecl &Node) {
|
|||
return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr;
|
||||
}
|
||||
|
||||
template <typename Ty>
|
||||
struct HasSizeMatcher {
|
||||
static bool hasSize(const Ty &Node, unsigned int N) {
|
||||
return Node.getSize() == N;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool HasSizeMatcher<StringLiteral>::hasSize(
|
||||
const StringLiteral &Node, unsigned int N) {
|
||||
return Node.getLength() == N;
|
||||
}
|
||||
|
||||
template <typename Ty>
|
||||
struct GetSourceExpressionMatcher {
|
||||
static const Expr *get(const Ty &Node) {
|
||||
|
|
|
@ -51,7 +51,6 @@ TEST(Finder, DynamicOnlyAcceptsSomeMatchers) {
|
|||
|
||||
// Do not accept non-toplevel matchers.
|
||||
EXPECT_FALSE(Finder.addDynamicMatcher(isArrow(), nullptr));
|
||||
EXPECT_FALSE(Finder.addDynamicMatcher(hasSize(2), nullptr));
|
||||
EXPECT_FALSE(Finder.addDynamicMatcher(hasName("x"), nullptr));
|
||||
}
|
||||
|
||||
|
@ -2536,6 +2535,17 @@ TEST(Matcher, StringLiterals) {
|
|||
EXPECT_TRUE(notMatches("const char s[1] = {'a'};", Literal));
|
||||
}
|
||||
|
||||
TEST(StringLiteral, HasSize) {
|
||||
StatementMatcher Literal = stringLiteral(hasSize(4));
|
||||
EXPECT_TRUE(matches("const char *s = \"abcd\";", Literal));
|
||||
// wide string
|
||||
EXPECT_TRUE(matches("const wchar_t *s = L\"abcd\";", Literal));
|
||||
// with escaped characters
|
||||
EXPECT_TRUE(matches("const char *s = \"\x05\x06\x07\x08\";", Literal));
|
||||
// no matching, too small
|
||||
EXPECT_TRUE(notMatches("const char *s = \"ab\";", Literal));
|
||||
}
|
||||
|
||||
TEST(Matcher, CharacterLiterals) {
|
||||
StatementMatcher CharLiteral = characterLiteral();
|
||||
EXPECT_TRUE(matches("const char c = 'c';", CharLiteral));
|
||||
|
|
Loading…
Reference in New Issue