Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
Add cxxStdInitializerListExpr AST matcher
Browse files Browse the repository at this point in the history
Summary:
This adds a new ASTMatcher for CXXStdInitializerListExprs that matches C++ initializer list expressions.

The primary motivation is to use it to fix [[ https://bugs.llvm.org/show_bug.cgi?id=32896 | PR32896 ]] (review here [[ https://reviews.llvm.org/D32767 | D32767 ]]).

Reviewers: alexfh, Prazek, aaron.ballman

Reviewed By: alexfh, aaron.ballman

Subscribers: malcolm.parsons, cfe-commits, klimek

Differential Revision: https://reviews.llvm.org/D32810

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@302287 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
kuhar committed May 5, 2017
1 parent aa751c3 commit b64b36b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 2 deletions.
17 changes: 15 additions & 2 deletions docs/LibASTMatchersReference.html
Expand Up @@ -924,6 +924,19 @@ <h2 id="decl-matchers">Node Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxStdInitializerListExpr0')"><a name="cxxStdInitializerListExpr0Anchor">cxxStdInitializerListExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXStdInitializerListExpr.html">CXXStdInitializerListExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxStdInitializerListExpr0"><pre>Matches C++ initializer list expressions.

Given
std::vector&lt;int&gt; a({ 1, 2, 3 });
std::vector&lt;int&gt; b = { 4, 5 };
int c[] = { 6, 7 };
std::pair&lt;int, int&gt; d = { 8, 9 };
cxxStdInitializerListExpr()
matches "{ 1, 2, 3 }" and "{ 4, 5 }"
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('cxxTemporaryObjectExpr0')"><a name="cxxTemporaryObjectExpr0Anchor">cxxTemporaryObjectExpr</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXTemporaryObjectExpr.html">CXXTemporaryObjectExpr</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="cxxTemporaryObjectExpr0"><pre>Matches functional cast expressions having N != 1 arguments

Expand Down Expand Up @@ -1160,7 +1173,7 @@ <h2 id="decl-matchers">Node Matchers</h2>
<tr><td colspan="4" class="doc" id="materializeTemporaryExpr0"><pre>Matches nodes where temporaries are materialized.

Example: Given
struct T {void func()};
struct T {void func();};
T f();
void g(T);
materializeTemporaryExpr() matches 'f()' in these statements
Expand Down Expand Up @@ -5233,7 +5246,7 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
<tr><td colspan="4" class="doc" id="hasReceiverType0"><pre>Matches on the receiver of an ObjectiveC Message expression.

Example
matcher = objCMessageExpr(hasRecieverType(asString("UIWebView *")));
matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *")));
matches the [webView ...] message invocation.
NSString *webViewJavaScript = ...
UIWebView *webView = ...
Expand Down
14 changes: 14 additions & 0 deletions include/clang/ASTMatchers/ASTMatchers.h
Expand Up @@ -1223,6 +1223,20 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm,
InnerMatcher.matches(*SyntForm, Finder, Builder));
}

/// \brief Matches C++ initializer list expressions.
///
/// Given
/// \code
/// std::vector<int> a({ 1, 2, 3 });
/// std::vector<int> b = { 4, 5 };
/// int c[] = { 6, 7 };
/// std::pair<int, int> d = { 8, 9 };
/// \endcode
/// cxxStdInitializerListExpr()
/// matches "{ 1, 2, 3 }" and "{ 4, 5 }"
const internal::VariadicDynCastAllOfMatcher<Stmt,
CXXStdInitializerListExpr> cxxStdInitializerListExpr;

/// \brief Matches implicit initializers of init list expressions.
///
/// Given
Expand Down
1 change: 1 addition & 0 deletions lib/ASTMatchers/Dynamic/Registry.cpp
Expand Up @@ -153,6 +153,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(cxxRecordDecl);
REGISTER_MATCHER(cxxReinterpretCastExpr);
REGISTER_MATCHER(cxxStaticCastExpr);
REGISTER_MATCHER(cxxStdInitializerListExpr);
REGISTER_MATCHER(cxxTemporaryObjectExpr);
REGISTER_MATCHER(cxxThisExpr);
REGISTER_MATCHER(cxxThrowExpr);
Expand Down
23 changes: 23 additions & 0 deletions unittests/ASTMatchers/ASTMatchersNodeTest.cpp
Expand Up @@ -1020,6 +1020,29 @@ TEST(InitListExpression, MatchesInitListExpression) {
matches("int i[1] = {42, [0] = 43};", integerLiteral(equals(42))));
}

TEST(CXXStdInitializerListExpression, MatchesCXXStdInitializerListExpression) {
const std::string code = "namespace std {"
"template <typename> class initializer_list {"
" public: initializer_list() noexcept {}"
"};"
"}"
"struct A {"
" A(std::initializer_list<int>) {}"
"};";
EXPECT_TRUE(matches(code + "A a{0};",
cxxConstructExpr(has(cxxStdInitializerListExpr()),
hasDeclaration(cxxConstructorDecl(
ofClass(hasName("A")))))));
EXPECT_TRUE(matches(code + "A a = {0};",
cxxConstructExpr(has(cxxStdInitializerListExpr()),
hasDeclaration(cxxConstructorDecl(
ofClass(hasName("A")))))));

EXPECT_TRUE(notMatches("int a[] = { 1, 2 };", cxxStdInitializerListExpr()));
EXPECT_TRUE(notMatches("struct B { int x, y; }; B b = { 5, 6 };",
cxxStdInitializerListExpr()));
}

TEST(UsingDeclaration, MatchesUsingDeclarations) {
EXPECT_TRUE(matches("namespace X { int x; } using X::x;",
usingDecl()));
Expand Down

0 comments on commit b64b36b

Please sign in to comment.