Add isConstinit matcher

Support C++20 constinit variables for AST Matchers.
This commit is contained in:
Evgeny Shulgin 2022-01-24 08:35:42 -05:00 committed by Aaron Ballman
parent 6184e565ad
commit 589a939072
5 changed files with 52 additions and 0 deletions

View File

@ -5628,6 +5628,19 @@ ifStmt(isConstexpr())
</pre></td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isConstinit0')"><a name="isConstinit0Anchor">isConstinit</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isConstinit0"><pre>Matches constinit variable declarations.
Given:
constinit int foo = 42;
constinit const char* bar = "baz";
int baz = 42;
[[clang::require_constant_initialization]] int xyz = 42;
varDecl(isConstinit())
matches the declaration of `foo` and `bar`, but not `baz` and `xyz`.
</pre></td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition1')"><a name="isDefinition1Anchor">isDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefinition1"><pre>Matches if a declaration has a body attached.

View File

@ -331,6 +331,8 @@ AST Matchers
underlying type.
- Added the ``isConsteval`` matcher to match ``consteval`` function
declarations as well as `if consteval` and `if ! consteval` statements.
- Added the ``isConstinit`` matcher to match ``constinit`` variable
declarations.
clang-format
------------

View File

@ -5211,6 +5211,23 @@ AST_POLYMORPHIC_MATCHER(isConstexpr,
return Node.isConstexpr();
}
/// Matches constinit variable declarations.
///
/// Given:
/// \code
/// constinit int foo = 42;
/// constinit const char* bar = "bar";
/// int baz = 42;
/// [[clang::require_constant_initialization]] int xyz = 42;
/// \endcode
/// varDecl(isConstinit())
/// matches the declaration of `foo` and `bar`, but not `baz` and `xyz`.
AST_MATCHER(VarDecl, isConstinit) {
if (const auto *CIA = Node.getAttr<ConstInitAttr>())
return CIA->isConstinit();
return false;
}
/// Matches selection statements with initializer.
///
/// Given:

View File

@ -406,6 +406,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isConstQualified);
REGISTER_MATCHER(isConsteval);
REGISTER_MATCHER(isConstexpr);
REGISTER_MATCHER(isConstinit);
REGISTER_MATCHER(isCopyAssignmentOperator);
REGISTER_MATCHER(isCopyConstructor);
REGISTER_MATCHER(isDefaultConstructor);

View File

@ -1841,6 +1841,25 @@ TEST_P(ASTMatchersTest, IsConstexpr_MatchesIfConstexpr) {
notMatches("void baz() { if (1 > 0) {} }", ifStmt(isConstexpr())));
}
TEST_P(ASTMatchersTest, IsConstinit) {
if (!GetParam().isCXX20OrLater())
return;
EXPECT_TRUE(matches("constinit int foo = 1;",
varDecl(hasName("foo"), isConstinit())));
EXPECT_TRUE(matches("extern constinit int foo;",
varDecl(hasName("foo"), isConstinit())));
EXPECT_TRUE(matches("constinit const char* foo = \"bar\";",
varDecl(hasName("foo"), isConstinit())));
EXPECT_TRUE(
notMatches("[[clang::require_constant_initialization]] int foo = 1;",
varDecl(hasName("foo"), isConstinit())));
EXPECT_TRUE(notMatches("constexpr int foo = 1;",
varDecl(hasName("foo"), isConstinit())));
EXPECT_TRUE(notMatches("static inline int foo = 1;",
varDecl(hasName("foo"), isConstinit())));
}
TEST_P(ASTMatchersTest, HasInitStatement_MatchesSelectionInitializers) {
EXPECT_TRUE(notMatches("void baz() { if (1 > 0) {} }",
ifStmt(hasInitStatement(anything()))));