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; }
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, SourceLocation ColonColonLoc) { Representation = NestedNameSpecifier::Create(Context, Representation, TemplateKWLoc.isValid(), TL.getTypePtr()); // Push source-location info into the buffer. SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); }
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(); }