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 RewriteUtils::getVarDeclTypeLocEnd(const VarDecl *VD) { TypeLoc VarTypeLoc = VD->getTypeSourceInfo()->getTypeLoc(); const IdentifierInfo *Id = VD->getType().getBaseTypeIdentifier(); // handle a special case shown as below: // x; // *y[]; // (*z)[]; // void foo(void) {...} // where x implicitly has type of int, whereas y has type of int * if (!Id) { SourceLocation EndLoc = VD->getLocation(); const char *Buf = SrcManager->getCharacterData(EndLoc); int Offset = -1; SourceLocation NewEndLoc = EndLoc.getLocWithOffset(Offset); if (!NewEndLoc.isValid()) return EndLoc; Buf--; while (isspace(*Buf) || (*Buf == '*') || (*Buf == '(')) { Offset--; NewEndLoc = EndLoc.getLocWithOffset(Offset); if (!NewEndLoc.isValid()) return EndLoc.getLocWithOffset(Offset+1); Buf--; } return EndLoc.getLocWithOffset(Offset+1); } TypeLoc NextTL = VarTypeLoc.getNextTypeLoc(); while (!NextTL.isNull()) { VarTypeLoc = NextTL; NextTL = NextTL.getNextTypeLoc(); } SourceRange TypeLocRange = VarTypeLoc.getSourceRange(); SourceLocation EndLoc = getEndLocationFromBegin(TypeLocRange); TransAssert(EndLoc.isValid() && "Invalid EndLoc!"); const Type *Ty = VarTypeLoc.getTypePtr(); // I am not sure why, but for a declaration like below: // unsigned int a; (or long long a;) // TypeLoc.getBeginLoc() returns the position of 'u' // TypeLoc.getEndLoc() also returns the position of 'u' // The size of TypeLoc.getSourceRange() is 8, which is the // length of "unsigned" // Then we are getting trouble, because now EndLoc is right // after 'd', but we need it points to the location after "int". // skipPossibleTypeRange corrects the above deviation // Or am I doing something horrible here? EndLoc = skipPossibleTypeRange(Ty, EndLoc, VD->getLocation()); return EndLoc; }
SourceLocation RewriteUtils::getVarDeclTypeLocBegin(const VarDecl *VD) { TypeLoc VarTypeLoc = VD->getTypeSourceInfo()->getTypeLoc(); TypeLoc NextTL = VarTypeLoc.getNextTypeLoc(); while (!NextTL.isNull()) { VarTypeLoc = NextTL; NextTL = NextTL.getNextTypeLoc(); } return VarTypeLoc.getLocStart(); }
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 DeclaratorDecl::getTypeSpecStartLoc() const { if (DeclInfo) { TypeLoc TL = DeclInfo->getTypeLoc(); while (true) { TypeLoc NextTL = TL.getNextTypeLoc(); if (!NextTL) return TL.getSourceRange().getBegin(); TL = NextTL; } } return SourceLocation(); }
void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { VisitValueDecl(DD); QualType InfoTy = Reader.GetType(Record[Idx++]); if (InfoTy.isNull()) return; DeclaratorInfo *DInfo = Reader.getContext()->CreateDeclaratorInfo(InfoTy); TypeLocReader TLR(Reader, Record, Idx); for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) TLR.Visit(TL); DD->setDeclaratorInfo(DInfo); }
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(); }
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(); }
void TypeLoc::copy(TypeLoc other) { assert(getFullDataSize() == other.getFullDataSize()); // If both data pointers are aligned to the maximum alignment, we // can memcpy because getFullDataSize() accurately reflects the // layout of the data. if (reinterpret_cast<uintptr_t>(Data) == llvm::alignTo(reinterpret_cast<uintptr_t>(Data), TypeLocMaxDataAlign) && reinterpret_cast<uintptr_t>(other.Data) == llvm::alignTo(reinterpret_cast<uintptr_t>(other.Data), TypeLocMaxDataAlign)) { memcpy(Data, other.Data, getFullDataSize()); return; } // Copy each of the pieces. TypeLoc TL(getType(), Data); do { TypeLocCopier(other).Visit(TL); other = other.getNextTypeLoc(); } while ((TL = TL.getNextTypeLoc())); }
/// \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(TypeLoc TL, SourceLocation Loc) { do { TypeLocInitializer(Loc).Visit(TL); } while ((TL = TL.getNextTypeLoc())); }
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(); }