forked from OSchip/llvm-project
[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 llvm-svn: 341958
This commit is contained in:
parent
e2da5c525e
commit
2253878a40
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue