r341958 - [ASTMatchers] add three matchers for dependent expressions
Jonas Toth via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 11 09:09:19 PDT 2018
Author: jonastoth
Date: Tue Sep 11 09:09:19 2018
New Revision: 341958
URL: http://llvm.org/viewvc/llvm-project?rev=341958&view=rev
Log:
[ASTMatchers] add three matchers for dependent expressions
Summary:
The new matchers can be used to check if an expression is type-, value- or instantiation-dependent
in a templated context.
These matchers are used in a clang-tidy check and generally useful as the
problem of unresolved templates occurs more often in clang-tidy and they
provide an easy way to check for this issue.
Reviewers: aaron.ballman, alexfh, klimek
Reviewed By: aaron.ballman
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D51880
Modified:
cfe/trunk/docs/LibASTMatchersReference.html
cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Modified: cfe/trunk/docs/LibASTMatchersReference.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LibASTMatchersReference.html?rev=341958&r1=341957&r2=341958&view=diff
==============================================================================
--- cfe/trunk/docs/LibASTMatchersReference.html (original)
+++ cfe/trunk/docs/LibASTMatchersReference.html Tue Sep 11 09:09:19 2018
@@ -2758,6 +2758,46 @@ enum class Y {};
</pre></td></tr>
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('isInstantiationDependent0')"><a name="isInstantiationDependent0Anchor">isInstantiationDependent</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isInstantiationDependent0"><pre>Matches expressions that are instantiation-dependent even if it is
+neither type- nor value-dependent.
+
+In the following example, the expression sizeof(sizeof(T() + T()))
+is instantiation-dependent (since it involves a template parameter T),
+but is neither type- nor value-dependent, since the type of the inner
+sizeof is known (std::size_t) and therefore the size of the outer
+sizeof is known.
+ template<typename T>
+ void f(T x, T y) { sizeof(sizeof(T() + T()); }
+expr(isInstantiationDependent()) matches sizeof(sizeof(T() + T())
+</pre></td></tr>
+
+
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('isTypeDependent0')"><a name="isTypeDependent0Anchor">isTypeDependent</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isTypeDependent0"><pre>Matches expressions that are type-dependent because the template type
+is not yet instantiated.
+
+For example, the expressions "x" and "x + y" are type-dependent in
+the following code, but "y" is not type-dependent:
+ template<typename T>
+ void add(T x, int y) {
+ x + y;
+ }
+expr(isTypeDependent()) matches x + y
+</pre></td></tr>
+
+
+<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>></td><td class="name" onclick="toggle('isValueDependent0')"><a name="isValueDependent0Anchor">isValueDependent</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isValueDependent0"><pre>Matches expression that are value-dependent because they contain a
+non-type template parameter.
+
+For example, the array bound of "Chars" in the following example is
+value-dependent.
+ template<int Size> int f() { return Size; }
+expr(isValueDependent()) matches return Size
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1FieldDecl.html">FieldDecl</a>></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 of the specified
bit width.
Modified: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h?rev=341958&r1=341957&r2=341958&view=diff
==============================================================================
--- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h (original)
+++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h Tue Sep 11 09:09:19 2018
@@ -816,6 +816,48 @@ AST_MATCHER_P(QualType, ignoringParens,
return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder);
}
+/// Matches expressions that are instantiation-dependent even if it is
+/// neither type- nor value-dependent.
+///
+/// In the following example, the expression sizeof(sizeof(T() + T()))
+/// is instantiation-dependent (since it involves a template parameter T),
+/// but is neither type- nor value-dependent, since the type of the inner
+/// sizeof is known (std::size_t) and therefore the size of the outer
+/// sizeof is known.
+/// \code
+/// template<typename T>
+/// void f(T x, T y) { sizeof(sizeof(T() + T()); }
+/// \endcode
+/// expr(isInstantiationDependent()) matches sizeof(sizeof(T() + T())
+AST_MATCHER(Expr, isInstantiationDependent) {
+ return Node.isInstantiationDependent();
+}
+
+/// Matches expressions that are type-dependent because the template type
+/// is not yet instantiated.
+///
+/// For example, the expressions "x" and "x + y" are type-dependent in
+/// the following code, but "y" is not type-dependent:
+/// \code
+/// template<typename T>
+/// void add(T x, int y) {
+/// x + y;
+/// }
+/// \endcode
+/// expr(isTypeDependent()) matches x + y
+AST_MATCHER(Expr, isTypeDependent) { return Node.isTypeDependent(); }
+
+/// Matches expression that are value-dependent because they contain a
+/// non-type template parameter.
+///
+/// For example, the array bound of "Chars" in the following example is
+/// value-dependent.
+/// \code
+/// template<int Size> int f() { return Size; }
+/// \endcode
+/// expr(isValueDependent()) matches return Size
+AST_MATCHER(Expr, isValueDependent) { return Node.isValueDependent(); }
+
/// Matches classTemplateSpecializations, templateSpecializationType and
/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
///
Modified: cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp?rev=341958&r1=341957&r2=341958&view=diff
==============================================================================
--- cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp (original)
+++ cfe/trunk/lib/ASTMatchers/Dynamic/Registry.cpp Tue Sep 11 09:09:19 2018
@@ -357,6 +357,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isExpansionInSystemHeader);
REGISTER_MATCHER(isInteger);
REGISTER_MATCHER(isIntegral);
+ REGISTER_MATCHER(isInstantiationDependent);
REGISTER_MATCHER(isInTemplateInstantiation);
REGISTER_MATCHER(isLambda);
REGISTER_MATCHER(isListInitialization);
@@ -376,8 +377,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isStaticStorageClass);
REGISTER_MATCHER(isStruct);
REGISTER_MATCHER(isTemplateInstantiation);
+ REGISTER_MATCHER(isTypeDependent);
REGISTER_MATCHER(isUnion);
REGISTER_MATCHER(isUnsignedInteger);
+ REGISTER_MATCHER(isValueDependent);
REGISTER_MATCHER(isVariadic);
REGISTER_MATCHER(isVirtual);
REGISTER_MATCHER(isVirtualAsWritten);
Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp?rev=341958&r1=341957&r2=341958&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Tue Sep 11 09:09:19 2018
@@ -1768,6 +1768,48 @@ TEST(IsInTemplateInstantiation, Sharing)
Matcher));
}
+TEST(IsInstantiationDependent, MatchesNonValueTypeDependent) {
+ EXPECT_TRUE(matches(
+ "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsInstantiationDependent, MatchesValueDependent) {
+ EXPECT_TRUE(matches("template<int T> int f() { return T; }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsInstantiationDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isInstantiationDependent())));
+}
+
+TEST(IsTypeDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isTypeDependent())));
+}
+
+TEST(IsTypeDependent, NotMatchesValueDependent) {
+ EXPECT_TRUE(notMatches("template<int T> int f() { return T; }",
+ expr(isTypeDependent())));
+}
+
+TEST(IsValueDependent, MatchesValueDependent) {
+ EXPECT_TRUE(matches("template<int T> int f() { return T; }",
+ expr(isValueDependent())));
+}
+
+TEST(IsValueDependent, MatchesTypeDependent) {
+ EXPECT_TRUE(matches("template<typename T> T f() { return T(); }",
+ expr(isValueDependent())));
+}
+
+TEST(IsValueDependent, MatchesInstantiationDependent) {
+ EXPECT_TRUE(matches(
+ "template<typename T> void f() { (void) sizeof(sizeof(T() + T())); }",
+ expr(isValueDependent())));
+}
+
TEST(IsExplicitTemplateSpecialization,
DoesNotMatchPrimaryTemplate) {
EXPECT_TRUE(notMatches(
More information about the cfe-commits
mailing list