LegalizeAdulthood added inline comments. ================ Comment at: unittests/ASTMatchers/ASTMatchersTest.cpp:4994 @@ +4993,3 @@ + EXPECT_TRUE(matches("typedef int hasUnderlyingTypeTest;", + typedefDecl(hasUnderlyingType(asString("int"))))); + EXPECT_TRUE(matches("typedef const int T;", ---------------- aaron.ballman wrote: > LegalizeAdulthood wrote: > > aaron.ballman wrote: > > > Thank you for those examples! Given the following code: > > > ``` > > > typedef int foo; > > > typedef foo bar; > > > > > > bar i; > > > ``` > > > clang-query> match varDecl(hasType(asString("int"))) > > > 0 matches. > > > clang-query> match varDecl(hasType(asString("foo"))) > > > 0 matches. > > > clang-query> match varDecl(hasType(asString("bar"))) > > > > > > Match #1: > > > > > > E:\Desktop\t.cpp:4:1: note: "root" binds here > > > bar i; > > > ^~~~~ > > > 1 match. > > > > > > So hasType() looks at what the immediate type is for the declaration > > > (which we document, yay us!). Based on that, I don't think > > > hasUnderlyingType() makes sense -- you should modify hasType() to work on > > > a TypedefNameDecl (not just a TypedefDecl!) so that it looks at the > > > immediate type of the type definition. I would expect your tests then to > > > result in: > > > ``` > > > 1: typedef void (fn)(void); > > > 2: typedef fn foo; > > > 3: typedef int bar; > > > 4: typedef int (f); > > > 5: typedef int (fn2)(int); > > > clang-query> match typedefDecl(hasType(asString("int"))) > > > > > > Match #1: > > > > > > /tmp/a.cpp:3:1: note: "root" binds here > > > typedef int bar; > > > ^~~~~~~~~~~~~~~ > > > > > > Match #2: > > > > > > /tmp/a.cpp:4:1: note: "root" binds here > > > typedef int (f); > > > ^~~~~~~~~~~~~~~ > > > 2 matches. > > > clang-query> match typedefDecl(hasType(typedefType())) > > > > > > Match #1: > > > > > > /tmp/a.cpp:2:1: note: "root" binds here > > > typedef fn foo; > > > ^~~~~~~~~~~~~~ > > > 1 match. > > > clang-query> match typedefDecl(hasType(parenType())) > > > > > > Match #1: > > > > > > /tmp/a.cpp:1:1: note: "root" binds here > > > typedef void (fn)(void); > > > ^~~~~~~~~~~~~~~~~~~~~~~ > > > > > > Match #2: > > > > > > /tmp/a.cpp:4:1: note: "root" binds here > > > typedef int (f); > > > ^~~~~~~~~~~~~~~ > > > > > > Match #3: > > > > > > /tmp/a.cpp:5:1: note: "root" binds here > > > typedef int (fn2)(int); > > > ^~~~~~~~~~~~~~~~~~~~~~ > > > 3 matches. > > > clang-query> match > > > typedefDecl(hasType(parenType(innerType(functionType())))) > > > > > > Match #1: > > > > > > /tmp/a.cpp:1:1: note: "root" binds here > > > typedef void (fn)(void); > > > ^~~~~~~~~~~~~~~~~~~~~~~ > > > > > > Match #2: > > > > > > /tmp/a.cpp:5:1: note: "root" binds here > > > typedef int (fn2)(int); > > > ^~~~~~~~~~~~~~~~~~~~~~ > > > 2 matches. > > > ``` > > > The end results are the same, so this is just changing the way the > > > information is surfaced to the user that is logically consistent. > > > ValueDecls have an immediate type, and so do TypedefDecls. By using > > > TypedefNameDecl instead of TypedefDecl, this also covers the case where > > > hasType() is useful for an alias-declaration. (We don't expose the > > > matcher for that yet, but it seems quite reasonable to add in the future, > > > and it would be nice for hasType to automatically work with that.) > > > > > > You can implement this with a helper function to handle abstracting away > > > the call to getType() vs getUnderlyingType(), then updating the hasType() > > > matchers to use it. Something like: > > > ``` > > > template <typename Ty> > > > struct UnderlyingTypeGetter { > > > static QualType get(const Ty &Node) { > > > return Node.getType(); > > > } > > > }; > > > > > > template <> > > > QualType UnderlyingTypeGetter<TypedefNameDecl>::get(const TypedefNameDecl > > > &Node) { > > > return Node.getUnderlyingType(); > > > } > > > ``` > > > (Somewhere in ASTMatchersInternal.h most likely.) > > > > > When I try to extend `hasType` to work on `TypedefDecl`, I get this error: > > > > ``` > > error: static assertion failed: right polymorphic conversion > > static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, > > ``` > > > > ...because `TypedefDecl` is derived from `NamedDecl` and the existing > > definition for `hasType` looks like this: > > > > ``` > > AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasType, > > AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, > > > > ValueDecl), > > internal::Matcher<Decl>, InnerMatcher, > > 1) { > > return qualType(hasDeclaration(InnerMatcher)) > > .matches(Node.getType(), Finder, Builder); > > } > > ``` > > > > So I'll need some guidance on how to extend `hasType` to work for > > `TypedefNamedDecl` nodes. I don't understand exactly what all these nasty > > macros do. So far, I've simply made changes by imitation, but my approach > > didn't work this time. > This ({F1302460}) does all of what you need (sans documentation, testing, > etc). > > (File should be attached, but if you need me to send it to you via email, I > can do so -- I've never tried this with Phab before.) What you had was very similar to what I attempted. You wrote:
```AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypdefNameDecl, ValueDecl)``` and I wrote ```AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, ValueDecl, TypedefNameDecl)``` so apparently the derivation relations between the arguments to this macro are order dependent? http://reviews.llvm.org/D8149 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits