SilensAngelusNex updated this revision to Diff 343106. SilensAngelusNex added a comment.
Rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101572/new/ https://reviews.llvm.org/D101572 Files: clang/include/clang/ASTMatchers/ASTMatchers.h clang/include/clang/ASTMatchers/ASTMatchersInternal.h clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -11,6 +11,7 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Host.h" #include "gtest/gtest.h" @@ -375,15 +376,104 @@ typedefNameDecl(hasType(asString("foo")), hasName("bar")))); } -TEST(HasTypeLoc, MatchesDeclaratorDecls) { +TEST(HasTypeLoc, MatchesBlockDecl) { + EXPECT_TRUE(matchesConditionally( + "auto x = ^int (int a, int b) { return a + b; };", + blockDecl(hasTypeLoc(loc(asString("int (int, int)")))), true, + {"-fblocks"})); +} + +TEST(HasTypeLoc, MatchesCXXBaseSpecifierAndCtorInitializer) { + llvm::StringRef code = R"cpp( + class Foo {}; + class Bar : public Foo { + Bar() : Foo() {} + }; + )cpp"; + + EXPECT_TRUE(matches( + code, cxxRecordDecl(hasAnyBase(hasTypeLoc(loc(asString("class Foo"))))))); + EXPECT_TRUE(matches( + code, cxxCtorInitializer(hasTypeLoc(loc(asString("class Foo")))))); +} + +TEST(HasTypeLoc, MatchesCXXFunctionalCastExpr) { + EXPECT_TRUE(matches("auto x = int(3);", + cxxFunctionalCastExpr(hasTypeLoc(loc(asString("int")))))); +} + +TEST(HasTypeLoc, MatchesCXXNewExpr) { + EXPECT_TRUE(matches("auto* x = new int(3);", + cxxNewExpr(hasTypeLoc(loc(asString("int")))))); + EXPECT_TRUE(matches("class Foo{}; auto* x = new Foo();", + cxxNewExpr(hasTypeLoc(loc(asString("class Foo")))))); +} + +TEST(HasTypeLoc, MatchesCXXTemporaryObjectExpr) { + EXPECT_TRUE( + matches("struct Foo { Foo(int, int); }; auto x = Foo(1, 2);", + cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("struct Foo")))))); +} + +TEST(HasTypeLoc, MatchesCXXUnresolvedConstructExpr) { + EXPECT_TRUE( + matches("template <typename T> T make() { return T(); }", + cxxUnresolvedConstructExpr(hasTypeLoc(loc(asString("T")))))); +} + +TEST(HasTypeLoc, MatchesClassTemplateSpecializationDecl) { + EXPECT_TRUE(matches( + "template <typename T> class Foo; template <> class Foo<int> {};", + classTemplateSpecializationDecl(hasTypeLoc(loc(asString("Foo<int>")))))); +} + +TEST(HasTypeLoc, MatchesCompoundLiteralExpr) { + EXPECT_TRUE( + matches("int* x = (int [2]) { 0, 1 };", + compoundLiteralExpr(hasTypeLoc(loc(asString("int [2]")))))); +} + +TEST(HasTypeLoc, MatchesDeclaratorDecl) { EXPECT_TRUE(matches("int x;", varDecl(hasName("x"), hasTypeLoc(loc(asString("int")))))); + EXPECT_TRUE(matches("int x(3);", + varDecl(hasName("x"), hasTypeLoc(loc(asString("int")))))); + EXPECT_TRUE( + matches("struct Foo { Foo(int, int); }; Foo x(1, 2);", + varDecl(hasName("x"), hasTypeLoc(loc(asString("struct Foo")))))); // Make sure we don't crash on implicit constructors. EXPECT_TRUE(notMatches("class X {}; X x;", declaratorDecl(hasTypeLoc(loc(asString("int")))))); } +TEST(HasTypeLoc, MatchesExplicitCastExpr) { + EXPECT_TRUE(matches("auto x = (int) 3;", + explicitCastExpr(hasTypeLoc(loc(asString("int")))))); + EXPECT_TRUE(matches("auto x = static_cast<int>(3);", + explicitCastExpr(hasTypeLoc(loc(asString("int")))))); +} + +TEST(HasTypeLoc, MatchesObjCPropertyDecl) { + EXPECT_TRUE(matchesObjC(R"objc( + @interface Foo + @property int enabled; + @end + )objc", + objcPropertyDecl(hasTypeLoc(loc(asString("int")))))); +} + +TEST(HasTypeLoc, MatchesTemplateArgumentLoc) { + EXPECT_TRUE(matches("template <typename T> class Foo {}; Foo<int> x;", + templateArgumentLoc(hasTypeLoc(loc(asString("int")))))); +} + +TEST(HasTypeLoc, MatchesTypedefNameDecl) { + EXPECT_TRUE(matches("typedef int X;", + typedefNameDecl(hasTypeLoc(loc(asString("int")))))); + EXPECT_TRUE(matches("using X = int;", + typedefNameDecl(hasTypeLoc(loc(asString("int")))))); +} TEST(Callee, MatchesDeclarations) { StatementMatcher CallMethodX = callExpr(callee(cxxMethodDecl(hasName("x")))); Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -135,6 +135,47 @@ return Node.getType(); } +template <typename... T> struct disjunction; +template <typename T> struct disjunction<T> : public T {}; +template <typename Head, typename... Tail> struct disjunction<Head, Tail...> { + using type = + typename std::conditional<Head::value, Head, disjunction<Tail...>>::type; + static constexpr bool value = type::value; +}; + +template <typename... Expected> struct is_one_of { + template <typename T> + static constexpr bool value = + disjunction<std::is_base_of<Expected, T>...>::value; +}; + +/// Unifies obtaining a `TypeSourceInfo` from different node types. +template <typename T, + std::enable_if_t<is_one_of< + CXXBaseSpecifier, CXXCtorInitializer, CXXTemporaryObjectExpr, + CXXUnresolvedConstructExpr, CompoundLiteralExpr, DeclaratorDecl, + ObjCPropertyDecl, TemplateArgumentLoc, TypedefNameDecl>::value<T>> + * = nullptr> +inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) { + return Node.getTypeSourceInfo(); +} +template <typename T, + std::enable_if_t<is_one_of<CXXFunctionalCastExpr, + ExplicitCastExpr>::value<T>> * = nullptr> +inline TypeSourceInfo *GetTypeSourceInfo(const T &Node) { + return Node.getTypeInfoAsWritten(); +} +inline TypeSourceInfo *GetTypeSourceInfo(const BlockDecl &Node) { + return Node.getSignatureAsWritten(); +} +inline TypeSourceInfo *GetTypeSourceInfo(const CXXNewExpr &Node) { + return Node.getAllocatedTypeSourceInfo(); +} +inline TypeSourceInfo * +GetTypeSourceInfo(const ClassTemplateSpecializationDecl &Node) { + return Node.getTypeAsWritten(); +} + /// Unifies obtaining the FunctionProtoType pointer from both /// FunctionProtoType and FunctionDecl nodes.. inline const FunctionProtoType * Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -3896,20 +3896,42 @@ return false; } -/// Matches if the type location of the declarator decl's type matches -/// the inner matcher. +/// Matches if the type location of a node matches the inner matcher. /// -/// Given +/// Examples: /// \code /// int x; /// \endcode /// declaratorDecl(hasTypeLoc(loc(asString("int")))) /// matches int x -AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) { - if (!Node.getTypeSourceInfo()) +/// +/// \code +/// auto x = int(3); +/// \code +/// cxxTemporaryObjectExpr(hasTypeLoc(loc(asString("int")))) +/// matches int(3) +/// +/// \code +/// struct Foo { Foo(int, int); }; +/// auto x = Foo(1, 2); +/// \code +/// cxxFunctionalCastExpr(hasTypeLoc(loc(asString("struct Foo")))) +/// matches Foo(1, 2) +AST_POLYMORPHIC_MATCHER_P( + hasTypeLoc, + AST_POLYMORPHIC_SUPPORTED_TYPES( + BlockDecl, CXXBaseSpecifier, CXXCtorInitializer, CXXFunctionalCastExpr, + CXXNewExpr, CXXTemporaryObjectExpr, CXXUnresolvedConstructExpr, + ClassTemplateSpecializationDecl, CompoundLiteralExpr, DeclaratorDecl, + ExplicitCastExpr, ObjCPropertyDecl, TemplateArgumentLoc, + TypedefNameDecl), + internal::Matcher<TypeLoc>, Inner) { + TypeSourceInfo *source = internal::GetTypeSourceInfo(Node); + if (source == nullptr) { // This happens for example for implicit destructors. return false; - return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder); + } + return Inner.matches(source->getTypeLoc(), Finder, Builder); } /// Matches if the matched type is represented by the given string.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits