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( _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits