SourceLocation TypeLoc::getBeginLoc() const { TypeLoc Cur = *this; TypeLoc LeftMost = Cur; while (true) { switch (Cur.getTypeLocClass()) { case Elaborated: LeftMost = Cur; break; case FunctionProto: if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) { LeftMost = Cur; break; } /* Fall through */ case FunctionNoProto: case ConstantArray: case DependentSizedArray: case IncompleteArray: case VariableArray: // FIXME: Currently QualifiedTypeLoc does not have a source range case Qualified: Cur = Cur.getNextTypeLoc(); continue; default: if (!Cur.getLocalSourceRange().getBegin().isInvalid()) LeftMost = Cur; Cur = Cur.getNextTypeLoc(); if (Cur.isNull()) break; continue; } // switch break; } // while return LeftMost.getLocalSourceRange().getBegin(); }
SourceLocation TypeLoc::getEndLoc() const { TypeLoc Cur = *this; TypeLoc Last; while (true) { switch (Cur.getTypeLocClass()) { default: if (!Last) Last = Cur; return Last.getLocalSourceRange().getEnd(); case Paren: case ConstantArray: case DependentSizedArray: case IncompleteArray: case VariableArray: case FunctionProto: case FunctionNoProto: Last = Cur; break; case Pointer: case BlockPointer: case MemberPointer: case LValueReference: case RValueReference: case PackExpansion: if (!Last) Last = Cur; break; case Qualified: case Elaborated: break; } Cur = Cur.getNextTypeLoc(); } }
SourceLocation TypeLoc::getEndLoc() const { TypeLoc Cur = *this; while (true) { switch (Cur.getTypeLocClass()) { default: break; case Qualified: case Elaborated: Cur = Cur.getNextTypeLoc(); continue; } break; } return Cur.getLocalSourceRange().getEnd(); }
/// \brief Initializes a type location, and all of its children /// recursively, as if the entire tree had been written in the /// given location. void TypeLoc::initializeImpl(ASTContext &Context, TypeLoc TL, SourceLocation Loc) { while (true) { switch (TL.getTypeLocClass()) { #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ case CLASS: { \ CLASS##TypeLoc TLCasted = TL.castAs<CLASS##TypeLoc>(); \ TLCasted.initializeLocal(Context, Loc); \ TL = TLCasted.getNextTypeLoc(); \ if (!TL) return; \ continue; \ } #include "clang/AST/TypeLocNodes.def" } } }
SourceLocation TypeLoc::getBeginLoc() const { TypeLoc Cur = *this; while (true) { switch (Cur.getTypeLocClass()) { // FIXME: Currently QualifiedTypeLoc does not have a source range // case Qualified: case Elaborated: break; default: TypeLoc Next = Cur.getNextTypeLoc(); if (Next.isNull()) break; Cur = Next; continue; } break; } return Cur.getLocalSourceRange().getBegin(); }
// I didn't factor out the common part of this function // into RewriteUtils, because the common part has implicit // dependency on VisitTemplateSpecializationTypeLoc. If in another // transformation we use this utility without implementing // VisitTemplateSpecializationTypeLoc, we will be in trouble. bool RemoveNamespaceRewriteVisitor::VisitCXXDestructorDecl( CXXDestructorDecl *DtorDecl) { if (ConsumerInstance->isForUsingNamedDecls) return true; const DeclContext *Ctx = DtorDecl->getDeclContext(); const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(Ctx); TransAssert(CXXRD && "Invalid CXXRecordDecl"); std::string Name; if (!ConsumerInstance->getNewNamedDeclName(CXXRD, Name)) return true; // Avoid duplicated VisitDtor. // For example, in the code below: // template<typename T> // class SomeClass { // public: // ~SomeClass<T>() {} // }; // ~SomeClass<T>'s TypeLoc is represented as TemplateSpecializationTypeLoc // In this case, ~SomeClass will be renamed from // VisitTemplateSpecializationTypeLoc. DeclarationNameInfo NameInfo = DtorDecl->getNameInfo(); if ( TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) { TypeLoc DtorLoc = TSInfo->getTypeLoc(); if (!DtorLoc.isNull() && (DtorLoc.getTypeLocClass() == TypeLoc::TemplateSpecialization)) return true; } ConsumerInstance->RewriteHelper->replaceCXXDestructorDeclName(DtorDecl, Name); return true; }
SourceLocation TypeLoc::getBeginLoc() const { TypeLoc Cur = *this; SourceLocation SavedParenLoc; while (true) { switch (Cur.getTypeLocClass()) { // FIXME: Currently QualifiedTypeLoc does not have a source range // case Qualified: case Elaborated: case DependentName: case DependentTemplateSpecialization: break; case Paren: // Save local source begin, if still unset. if (SavedParenLoc.isInvalid()) SavedParenLoc = Cur.getLocalSourceRange().getBegin(); Cur = Cur.getNextTypeLoc(); assert(!Cur.isNull()); continue; break; case Pointer: case BlockPointer: case MemberPointer: case ObjCObjectPointer: case LValueReference: case RValueReference: case ConstantArray: case DependentSizedArray: case IncompleteArray: case VariableArray: case FunctionNoProto: // Discard previously saved paren loc, if any. SavedParenLoc = SourceLocation(); Cur = Cur.getNextTypeLoc(); assert(!Cur.isNull()); continue; break; case FunctionProto: // Discard previously saved paren loc, if any. SavedParenLoc = SourceLocation(); if (cast<FunctionProtoTypeLoc>(&Cur)->getTypePtr()->hasTrailingReturn()) return Cur.getLocalSourceRange().getBegin(); Cur = Cur.getNextTypeLoc(); assert(!Cur.isNull()); continue; break; default: TypeLoc Next = Cur.getNextTypeLoc(); if (Next.isNull()) break; Cur = Next; continue; } break; } return SavedParenLoc.isValid() ? SavedParenLoc : Cur.getLocalSourceRange().getBegin(); }
void TypeRenameTransform::processTypeLoc(TypeLoc TL, bool forceRewriteMacro) { if (TL.isNull()) { return; } auto BL = TL.getBeginLoc(); // ignore system headers if (shouldIgnore(BL)) { return; } // is a result from macro expansion? sorry... if (BL.isMacroID() && !forceRewriteMacro) { llvm::errs() << "Cannot rename type from macro expansion at: " << loc(BL) << "\n"; return; } // TODO: Take care of spelling loc finesses // BL = sema->getSourceManager().getSpellingLoc(BL); pushIndent(); auto QT = TL.getType(); // llvm::errs() << indent() // << "TypeLoc" // << ", typeLocClass: " << typeLocClassName(TL.getTypeLocClass()) // << "\n" << indent() << "qualType as str: " << QT.getAsString() // << "\n" << indent() << "beginLoc: " << loc(TL.getBeginLoc()) // << "\n"; switch(TL.getTypeLocClass()) { case TypeLoc::FunctionProto: { if (auto FTL = dyn_cast<FunctionTypeLoc>(&TL)) { for (unsigned I = 0, E = FTL->getNumArgs(); I != E; ++I) { processParmVarDecl(FTL->getArg(I)); } } break; } // an elaborated type loc captures the "prefix" of a type // for example, the elaborated type loc of "A::B::C" is A::B // we need to know if A::B and A are types we are renaming // (so that we can handle nested classes, in-class typedefs, etc.) case TypeLoc::Elaborated: { if (auto ETL = dyn_cast<ElaboratedTypeLoc>(&TL)) { processQualifierLoc(ETL->getQualifierLoc(), forceRewriteMacro); } break; } case TypeLoc::ObjCObject: { if (auto OT = dyn_cast<ObjCObjectTypeLoc>(&TL)) { for (unsigned I = 0, E = OT->getNumProtocols(); I != E; ++I) { if (auto P = OT->getProtocol(I)) { std::string newName; if (nameMatches(P, newName, true)) { renameLocation(OT->getProtocolLoc(I), newName); } } } } break; } case TypeLoc::InjectedClassName: { if (auto TSTL = dyn_cast<InjectedClassNameTypeLoc>(&TL)) { auto CD = TSTL->getDecl(); std::string newName; if (nameMatches(CD, newName, true)) { renameLocation(BL, newName); } } break; } case TypeLoc::TemplateSpecialization: { if (auto TSTL = dyn_cast<TemplateSpecializationTypeLoc>(&TL)) { // See if it's the template name that needs renaming auto T = TL.getTypePtr(); if (auto TT = dyn_cast<TemplateSpecializationType>(T)) { auto TN = TT->getTemplateName(); auto TD = TN.getAsTemplateDecl(); auto TTD = TD->getTemplatedDecl(); std::string newName; if (nameMatches(TTD, newName, true)) { renameLocation(TSTL->getTemplateNameLoc(), newName); } } // iterate through the args for (unsigned I = 0, E = TSTL->getNumArgs(); I != E; ++I) { // need to see if the template argument is also a type // (we skip things like Foo<1> ) auto AL = TSTL->getArgLoc(I); auto A = AL.getArgument(); if (A.getKind() != TemplateArgument::Type) { continue; } if (auto TSI = AL.getTypeSourceInfo()) { processTypeLoc(TSI->getTypeLoc(), forceRewriteMacro); } } } break; } // typedef is tricky case TypeLoc::Typedef: { auto T = TL.getTypePtr(); if (auto TDT = dyn_cast<TypedefType>(T)) { auto TDD = TDT->getDecl(); std::string newName; if (nameMatches(TDD, newName, true)) { renameLocation(BL, newName); } } break; } // leaf types // TODO: verify correctness, need test cases for each // TODO: Check if Builtin works case TypeLoc::Builtin: case TypeLoc::Enum: case TypeLoc::Record: case TypeLoc::ObjCInterface: case TypeLoc::TemplateTypeParm: { // skip if it's an anonymous type // read Clang`s definition (in RecordDecl) -- not exactly what you think // so we use the length of name std::string newName; if (auto TT = dyn_cast<TagType>(TL.getTypePtr())) { auto TD = TT->getDecl(); if (nameMatches(TD, newName, true)) { renameLocation(BL, newName); } } else { if (stringMatches(QT.getAsString(), newName)) { renameLocation(BL, newName); } } break; } default: break; } processTypeLoc(TL.getNextTypeLoc(), forceRewriteMacro); popIndent(); }