bool ReduceClassTemplateParameterRewriteVisitor:: VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc Loc) { // Invalidation can be introduced by constructor's initialization list, e.g.: // template<typename T1, typename T2> class A { }; // class B : public A<int, int> { // int m; // B(int x) : m(x) {} // }; // In RecursiveASTVisitor.h, TraverseConstructorInitializer will visit the part // of initializing base class's, i.e. through base's default constructor if (Loc.getBeginLoc().isInvalid()) return true; const TemplateSpecializationType *Ty = dyn_cast<TemplateSpecializationType>(Loc.getTypePtr()); TransAssert(Ty && "Invalid TemplateSpecializationType!"); TemplateName TmplName = Ty->getTemplateName(); if (!ConsumerInstance->referToTheTemplateDecl(TmplName)) return true; unsigned NumArgs = Loc.getNumArgs(); // I would put a stronger assert here, i.e., // " (ConsumerInstance->TheParameterIndex >= NumArgs) && // ConsumerInstance->hasDefaultArg " // but sometimes ill-formed input could yield incomplete // info, e.g., for two template decls which refer to the same // template def, one decl could have a non-null default arg, // while another decl's default arg field could be null. if (ConsumerInstance->TheParameterIndex >= NumArgs) return true; TransAssert((ConsumerInstance->TheParameterIndex < NumArgs) && "TheParameterIndex cannot be greater than NumArgs!"); TemplateArgumentLoc ArgLoc = Loc.getArgLoc(ConsumerInstance->TheParameterIndex); SourceRange Range = ArgLoc.getSourceRange(); if (NumArgs == 1) { ConsumerInstance->TheRewriter.ReplaceText(SourceRange(Loc.getLAngleLoc(), Loc.getRAngleLoc()), "<>"); } else if ((ConsumerInstance->TheParameterIndex + 1) == NumArgs) { SourceLocation EndLoc = Loc.getRAngleLoc(); EndLoc = EndLoc.getLocWithOffset(-1); ConsumerInstance->RewriteHelper->removeTextFromLeftAt( Range, ',', EndLoc); } else { ConsumerInstance->RewriteHelper->removeTextUntil(Range, ','); } return true; }
bool ClassTemplateToClassSpecializationTypeRewriteVisitor:: VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc Loc) { const TemplateSpecializationType *Ty = dyn_cast<TemplateSpecializationType>(Loc.getTypePtr()); TransAssert(Ty && "Invalid TemplateSpecializationType!"); TemplateName TmplName = Ty->getTemplateName(); if (!ConsumerInstance->referToTheTemplateDecl(TmplName)) return true; SourceLocation TmplKeyLoc = Loc.getTemplateKeywordLoc(); if (TmplKeyLoc.isValid()) ConsumerInstance->TheRewriter.RemoveText(TmplKeyLoc, 8); // it's necessary to check the validity of locations, otherwise // we will get assertion errors... // note that some implicit typeloc has been visited by Clang, e.g. // template < typename > struct A { }; // struct B:A < int > { // B ( ) { } // }; // base initializer A<int> is not presented in the code but visited, // so, we need to make sure locations are valid. SourceLocation LAngleLoc = Loc.getLAngleLoc(); if (LAngleLoc.isInvalid()) return true; SourceLocation RAngleLoc = Loc.getRAngleLoc(); if (RAngleLoc.isInvalid()) return true; ConsumerInstance->TheRewriter.RemoveText(SourceRange(LAngleLoc, RAngleLoc)); return true; }
bool ClassTemplateToClassSpecializationTypeRewriteVisitor:: VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc Loc) { const TemplateSpecializationType *Ty = dyn_cast<TemplateSpecializationType>(Loc.getTypePtr()); TransAssert(Ty && "Invalid TemplateSpecializationType!"); TemplateName TmplName = Ty->getTemplateName(); if (!ConsumerInstance->referToTheTemplateDecl(TmplName)) return true; SourceLocation TmplKeyLoc = Loc.getTemplateKeywordLoc(); if (TmplKeyLoc.isValid()) ConsumerInstance->TheRewriter.RemoveText(TmplKeyLoc, 8); ConsumerInstance->TheRewriter.RemoveText(SourceRange(Loc.getLAngleLoc(), Loc.getRAngleLoc())); return true; }
virtual SourceRange getRange(const TypeLoc &Node) { TemplateSpecializationTypeLoc T = Node.getUnqualifiedLoc().castAs<TemplateSpecializationTypeLoc>(); assert(!T.isNull()); return SourceRange(T.getLAngleLoc(), T.getRAngleLoc()); }