Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern);
}
}
+ void
+ VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT) {
+ Outer.add(STTPT->getReplacementType(), Flags);
+ }
void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT) {
Outer.add(TTPT->getDecl(), Flags);
}
QualType VisitExpr(const Expr *S) {
return S->IgnoreImplicitAsWritten()->getType();
}
+ QualType VisitMemberExpr(const MemberExpr *S) {
+ // The `foo` in `s.foo()` pretends not to have a real type!
+ if (S->getType()->isSpecificBuiltinType(BuiltinType::BoundMember))
+ return Expr::findBoundMemberType(S);
+ return VisitExpr(S);
+ }
// Exceptions for void expressions that operate on a type in some way.
QualType VisitCXXDeleteExpr(const CXXDeleteExpr *S) {
return S->getDestroyedType();
struct $Target[[Target]] { operator int() const; };
struct Aggregate { Target a, b; };
Target t;
+ Target make();
- template <typename T> class $smart_ptr[[smart_ptr]] {
+ template <typename T> struct $smart_ptr[[smart_ptr]] {
T& operator*();
T* operator->();
T* get();
"void x() { ^if (t) {} }",
"void x() { ^while (t) {} }",
"void x() { ^do { } while (t); }",
+ "void x() { ^make(); }",
+ "void x(smart_ptr<Target> &t) { t.^get(); }",
"^auto x = []() { return t; };",
"Target* ^tptr = &t;",
"Target ^tarray[3];",