CXCursor cxcursor::getTypeRefCursor(CXCursor cursor) { if (cursor.kind != CXCursor_CallExpr) return cursor; if (cursor.xdata == 0) return cursor; const Expr *E = getCursorExpr(cursor); TypeSourceInfo *Type = 0; if (const CXXUnresolvedConstructExpr * UnCtor = dyn_cast<CXXUnresolvedConstructExpr>(E)) { Type = UnCtor->getTypeSourceInfo(); } else if (const CXXTemporaryObjectExpr *Tmp = dyn_cast<CXXTemporaryObjectExpr>(E)){ Type = Tmp->getTypeSourceInfo(); } if (!Type) return cursor; CXTranslationUnit TU = getCursorTU(cursor); QualType Ty = Type->getType(); TypeLoc TL = Type->getTypeLoc(); SourceLocation Loc = TL.getBeginLoc(); if (const ElaboratedType *ElabT = Ty->getAs<ElaboratedType>()) { Ty = ElabT->getNamedType(); ElaboratedTypeLoc ElabTL = TL.castAs<ElaboratedTypeLoc>(); Loc = ElabTL.getNamedTypeLoc().getBeginLoc(); } if (const TypedefType *Typedef = Ty->getAs<TypedefType>()) return MakeCursorTypeRef(Typedef->getDecl(), Loc, TU); if (const TagType *Tag = Ty->getAs<TagType>()) return MakeCursorTypeRef(Tag->getDecl(), Loc, TU); if (const TemplateTypeParmType *TemplP = Ty->getAs<TemplateTypeParmType>()) return MakeCursorTypeRef(TemplP->getDecl(), Loc, TU); return cursor; }
bool VisitTypeLoc(TypeLoc TypeLocation) { Match(TypeLocation.getType().getAsString(), TypeLocation.getBeginLoc()); return true; }
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(); }