ASTConsumer *InsertBracesFrontendAction::CreateASTConsumer( CompilerInstance &Compiler, StringRef InFile) { ASTContext *ctx = &Compiler.getASTContext(); rewriter = Rewriter(ctx->getSourceManager(), ctx->getLangOpts()); return new InsertBracesASTConsumer(rewriter); }
bool VisitCallExpr(CallExpr *E) { llvm::errs() << "I see a CallExpr\n"; E->dump(); Expr *callee = E->getCallee(); if (ImplicitCastExpr *ica = llvm::dyn_cast<ImplicitCastExpr>(callee)) { callee = ica->getSubExpr(); } if (DeclRefExpr *dref = llvm::dyn_cast<DeclRefExpr>(callee)) { llvm::errs() << "declref:\n"; dref->dump(); NamedDecl *d = dref->getFoundDecl(); ASTContext &Context = d->getASTContext(); SourceManager &SM = Context.getSourceManager(); if (dref->hasQualifier()) { llvm::errs() << " has qualifier in name.\n"; NestedNameSpecifierLoc lc = dref->getQualifierLoc(); llvm::errs() << " begin loc: " << lc.getBeginLoc().printToString(SM) << "\n"; llvm::errs() << " end loc: " << lc.getEndLoc().printToString(SM) << "\n"; } if (UsingShadowDecl *sh = llvm::dyn_cast<UsingShadowDecl>(d)) { NamedDecl *td = sh->getTargetDecl(); FoundRealDecl(td); //d->dump(); } else { FoundRealDecl(d); //d->dump(); } } else if (UnresolvedLookupExpr *ule = dyn_cast<UnresolvedLookupExpr>(callee)) { llvm::errs() << "unresolved\n"; ASTContext* Context; SourceManager* SM; for (const auto *d : ule->decls()) { FoundRealDecl(d); Context = &d->getASTContext(); SM = &Context->getSourceManager(); } llvm::errs() << " begin loc: " << ule->getLocStart().printToString(*SM) << "\n"; llvm::errs() << " end loc: " << ule->getLocEnd().printToString(*SM) << "\n"; NestedNameSpecifierLoc ll = ule->getQualifierLoc(); llvm::errs() << " nested begin loc: " << ll.getBeginLoc().printToString(*SM) << "\n"; llvm::errs() << " nested end loc: " << ll.getEndLoc().printToString(*SM) << "\n"; } return true; }
/// \brief \arg Loc is the end of a statement range. This returns the location /// of the token of expected type following the statement. /// If no token of this type is found or the location is inside a macro, the returned /// source location will be invalid. SourceLocation findTokenAfterLocation(SourceLocation loc, ASTContext& Ctx, tok::TokenKind tokenType) { SourceManager &SM = Ctx.getSourceManager(); if (loc.isMacroID()) { if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc)) return SourceLocation(); } loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts()); // Break down the source location. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc); // Try to load the file buffer. bool invalidTemp = false; StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); if (invalidTemp) return SourceLocation(); const char *tokenBegin = file.data() + locInfo.second; // Lex from the start of the given location. Lexer lexer(SM.getLocForStartOfFile(locInfo.first), Ctx.getLangOpts(), file.begin(), tokenBegin, file.end()); Token tok; lexer.LexFromRawLexer(tok); if (tok.isNot(tokenType)) return SourceLocation(); return tok.getLocation(); }
void HandleTranslationUnit(ASTContext &Context) override { const auto &SourceMgr = Context.getSourceManager(); std::vector<SourceLocation> RenamingCandidates; std::vector<SourceLocation> NewCandidates; for (const auto &USR : USRs) { NewCandidates = getLocationsOfUSR(USR, Context.getTranslationUnitDecl()); RenamingCandidates.insert(RenamingCandidates.end(), NewCandidates.begin(), NewCandidates.end()); NewCandidates.clear(); } auto PrevNameLen = PrevName.length(); if (PrintLocations) for (const auto &Loc : RenamingCandidates) { FullSourceLoc FullLoc(Loc, SourceMgr); errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(Loc) << ":" << FullLoc.getSpellingLineNumber() << ":" << FullLoc.getSpellingColumnNumber() << "\n"; Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen, NewName)); } else for (const auto &Loc : RenamingCandidates) Replaces.insert(tooling::Replacement(SourceMgr, Loc, PrevNameLen, NewName)); }
void HandleOneRename(ASTContext &Context, const std::string &NewName, const std::string &PrevName, const std::vector<std::string> &USRs) { const SourceManager &SourceMgr = Context.getSourceManager(); SymbolOccurrences Occurrences = tooling::getOccurrencesOfUSRs( USRs, PrevName, Context.getTranslationUnitDecl()); if (PrintLocations) { for (const auto &Occurrence : Occurrences) { FullSourceLoc FullLoc(Occurrence.getNameRanges()[0].getBegin(), SourceMgr); errs() << "clang-rename: renamed at: " << SourceMgr.getFilename(FullLoc) << ":" << FullLoc.getSpellingLineNumber() << ":" << FullLoc.getSpellingColumnNumber() << "\n"; } } // FIXME: Support multi-piece names. // FIXME: better error handling (propagate error out). StringRef NewNameRef = NewName; Expected<std::vector<AtomicChange>> Change = createRenameReplacements(Occurrences, SourceMgr, NewNameRef); if (!Change) { llvm::errs() << "Failed to create renaming replacements for '" << PrevName << "'! " << llvm::toString(Change.takeError()) << "\n"; return; } convertChangesToFileReplacements(*Change, &FileToReplaces); }
void SynthesizeRemovalConsumer::renameLocation(SourceLocation L, std::string& N) { if (L.isMacroID()) { // TODO: emit error using diagnostics SourceManager &SM = astContext->getSourceManager(); if (SM.isMacroArgExpansion(L) || SM.isInSystemMacro(L)) { // see if it's the macro expansion we can handle // e.g. // #define call(x) x // call(y()); // if we want to rename y() L = SM.getSpellingLoc(L); // this falls through to the rename routine below } else { // if the spelling location is from an actual file that we can // touch, then do the replacement, but show a warning SourceManager &SM = astContext->getSourceManager(); auto SL = SM.getSpellingLoc(L); FullSourceLoc FSL(SL, SM); const FileEntry *FE = SM.getFileEntryForID(FSL.getFileID()); if (FE) { llvm::errs() << "Warning: Rename attempted as a result of macro " << "expansion may break things, at: " << loc(L) << "\n"; L = SL; // this falls through to the rename routine below } else { // cannot handle this case llvm::errs() << "Error: Token is resulted from macro expansion" " and is therefore not renamed, at: " << loc(L) << "\n"; return; } } } if (shouldIgnore(L)) { return; } auto LE = preprocessor->getLocForEndOfToken(L); if (LE.isValid()) { // getLocWithOffset returns the location *past* the token, hence -1 auto E = LE.getLocWithOffset(-1); rewriter.ReplaceText(SourceRange(L, E), N); } }
void Initialize(ASTContext &context) { //llvm::errs() << "initializing consumer\n"; Context = &context; SM = &Context->getSourceManager(); // Get the ID and start/end of the main file. MainFileID = SM->getMainFileID(); }
static void printSourceLocation(SourceLocation loc, ASTContext &Ctx, raw_ostream &OS) { SourceManager &SM = Ctx.getSourceManager(); PresumedLoc PL = SM.getPresumedLoc(loc); OS << llvm::sys::path::filename(PL.getFilename()); OS << ":" << PL.getLine() << ":" << PL.getColumn(); }
/// \brief The LoopFixer callback, which determines if loops discovered by the /// matchers are convertible, printing information about the loops if so. void LoopFixer::run(const MatchFinder::MatchResult &Result) { const BoundNodes &Nodes = Result.Nodes; Confidence ConfidenceLevel(TCK_Safe); ASTContext *Context = Result.Context; const ForStmt *TheLoop = Nodes.getStmtAs<ForStmt>(LoopName); if (!Context->getSourceManager().isFromMainFile(TheLoop->getForLoc())) return; // Check that we have exactly one index variable and at most one end variable. const VarDecl *LoopVar = Nodes.getDeclAs<VarDecl>(IncrementVarName); const VarDecl *CondVar = Nodes.getDeclAs<VarDecl>(ConditionVarName); const VarDecl *InitVar = Nodes.getDeclAs<VarDecl>(InitVarName); if (!areSameVariable(LoopVar, CondVar) || !areSameVariable(LoopVar, InitVar)) return; const VarDecl *EndVar = Nodes.getDeclAs<VarDecl>(EndVarName); const VarDecl *ConditionEndVar = Nodes.getDeclAs<VarDecl>(ConditionEndVarName); if (EndVar && !areSameVariable(EndVar, ConditionEndVar)) return; // If the end comparison isn't a variable, we can try to work with the // expression the loop variable is being tested against instead. const CXXMemberCallExpr *EndCall = Nodes.getStmtAs<CXXMemberCallExpr>(EndCallName); const Expr *BoundExpr = Nodes.getStmtAs<Expr>(ConditionBoundName); // If the loop calls end()/size() after each iteration, lower our confidence // level. if (FixerKind != LFK_Array && !EndVar) ConfidenceLevel.lowerTo(TCK_Reasonable); const Expr *ContainerExpr = NULL; bool ContainerNeedsDereference = false; // FIXME: Try to put most of this logic inside a matcher. Currently, matchers // don't allow the right-recursive checks in digThroughConstructors. if (FixerKind == LFK_Iterator) ContainerExpr = findContainer(Context, LoopVar->getInit(), EndVar ? EndVar->getInit() : EndCall, &ContainerNeedsDereference); else if (FixerKind == LFK_PseudoArray) { if (!EndCall) return; ContainerExpr = EndCall->getImplicitObjectArgument(); const MemberExpr *Member = dyn_cast<MemberExpr>(EndCall->getCallee()); if (!Member) return; ContainerNeedsDereference = Member->isArrow(); } // We must know the container or an array length bound. if (!ContainerExpr && !BoundExpr) return; findAndVerifyUsages(Context, LoopVar, EndVar, ContainerExpr, BoundExpr, ContainerNeedsDereference, TheLoop, ConfidenceLevel); }
void HandleTranslationUnit(ASTContext &Context) override { const SourceManager &SourceMgr = Context.getSourceManager(); for (unsigned Offset : SymbolOffsets) { if (!FindSymbol(Context, SourceMgr, Offset, "")) return; } for (const std::string &QualifiedName : QualifiedNames) { if (!FindSymbol(Context, SourceMgr, 0, QualifiedName)) return; } }
void HandleInlineMethodDefinition(CXXMethodDecl *D) override { PrettyStackTraceDecl CrashInfo(D, SourceLocation(), Context->getSourceManager(), "LLVM IR generation of inline method"); if (llvm::TimePassesIsEnabled) LLVMIRGeneration.startTimer(); Gen->HandleInlineMethodDefinition(D); if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); }
// This gets called only when the full TU is completely parsed. void HandleTranslationUnit(ASTContext &Context) { llvm::errs() << "********* The whole TU *************\n"; Context.getTranslationUnitDecl()->dump(); llvm::errs() << "****** going over the decls stored in it:\n"; for (auto *D : Context.getTranslationUnitDecl()->decls()) { llvm::errs() << "Decl in the TU:\n"; D->dump(); llvm::errs() << "Its start location is: '" << D->getLocStart().printToString(Context.getSourceManager()) << "'\n"; } }
virtual void HandleTopLevelDecl(DeclGroupRef D) { PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), Context->getSourceManager(), "LLVM IR generation of declaration"); if (llvm::TimePassesIsEnabled) LLVMIRGeneration.startTimer(); Gen->HandleTopLevelDecl(D); if (llvm::TimePassesIsEnabled) LLVMIRGeneration.stopTimer(); }
void MethodMoveTransform::HandleTranslationUnit(ASTContext &C) { auto movingSpec = TransformRegistry::get().config["MethodMove"].begin(); movingClassName = movingSpec->first.as<std::string>(); clang::SourceManager &SM = C.getSourceManager(); clang::FileManager &FM = SM.getFileManager(); if(FM.getFile(movingSpec->second.as<std::string>()) == SM.getFileEntryForID(SM.getMainFileID())) { llvm::errs() << "MovingClassName: " << movingClassName << "\n"; llvm::errs() << SM.getFileEntryForID(SM.getMainFileID())->getName() << "\n"; auto TUD = C.getTranslationUnitDecl(); processDeclContext(TUD); } }
void CommentToXMLConverter::convertCommentToXML(const FullComment *FC, SmallVectorImpl<char> &XML, const ASTContext &Context) { if (!FormatContext || (FormatInMemoryUniqueId % 1000) == 0) { // Create a new format context, or re-create it after some number of // iterations, so the buffers don't grow too large. FormatContext.reset(new SimpleFormatContext(Context.getLangOpts())); } CommentASTToXMLConverter Converter(FC, XML, Context.getCommentCommandTraits(), Context.getSourceManager(), *FormatContext, FormatInMemoryUniqueId++); Converter.visit(FC); }
SourceRange StackAddrEscapeChecker::genName(raw_ostream &os, const MemRegion *R, ASTContext &Ctx) { // Get the base region, stripping away fields and elements. R = R->getBaseRegion(); SourceManager &SM = Ctx.getSourceManager(); SourceRange range; os << "Address of "; // Check if the region is a compound literal. if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) { const CompoundLiteralExpr *CL = CR->getLiteralExpr(); os << "stack memory associated with a compound literal " "declared on line " << SM.getExpansionLineNumber(CL->getLocStart()) << " returned to caller"; range = CL->getSourceRange(); } else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) { const Expr *ARE = AR->getExpr(); SourceLocation L = ARE->getLocStart(); range = ARE->getSourceRange(); os << "stack memory allocated by call to alloca() on line " << SM.getExpansionLineNumber(L); } else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) { const BlockDecl *BD = BR->getCodeRegion()->getDecl(); SourceLocation L = BD->getLocStart(); range = BD->getSourceRange(); os << "stack-allocated block declared on line " << SM.getExpansionLineNumber(L); } else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { os << "stack memory associated with local variable '" << VR->getString() << '\''; range = VR->getDecl()->getSourceRange(); } else if (const CXXTempObjectRegion *TOR = dyn_cast<CXXTempObjectRegion>(R)) { QualType Ty = TOR->getValueType().getLocalUnqualifiedType(); os << "stack memory associated with temporary object of type '"; Ty.print(os, Ctx.getPrintingPolicy()); os << "'"; range = TOR->getExpr()->getSourceRange(); } else { llvm_unreachable("Invalid region in ReturnStackAddressChecker."); } return range; }
void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl(); for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end(); D != DEnd; ++D) { if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D)) migrateObjCInterfaceDecl(Ctx, CDecl); } Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); RewritesReceiver Rec(rewriter); Editor->applyRewrites(Rec); for (Rewriter::buffer_iterator I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { FileID FID = I->first; RewriteBuffer &buf = I->second; const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); assert(file); SmallString<512> newText; llvm::raw_svector_ostream vecOS(newText); buf.write(vecOS); vecOS.flush(); llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy( StringRef(newText.data(), newText.size()), file->getName()); SmallString<64> filePath(file->getName()); FileMgr.FixupRelativePath(filePath); Remapper.remap(filePath.str(), memBuf); } if (IsOutputFile) { Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics()); } else { Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics()); } }
void CommentToXMLConverter::convertCommentToXML(const FullComment *FC, SmallVectorImpl<char> &XML, const ASTContext &Context) { if (!FormatContext) { FormatContext = new SimpleFormatContext(Context.getLangOpts()); } else if ((FormatInMemoryUniqueId % 1000) == 0) { // Delete after some number of iterations, so the buffers don't grow // too large. delete FormatContext; FormatContext = new SimpleFormatContext(Context.getLangOpts()); } CommentASTToXMLConverter Converter(FC, XML, Context.getCommentCommandTraits(), Context.getSourceManager(), *FormatContext, FormatInMemoryUniqueId++); Converter.visit(FC); }
/// \brief If the member expression is operator-> (overloaded or not) on /// IndexVar, include it as a valid usage and prune the traversal. /// /// For example, given /// \code /// struct Foo { int bar(); int x; }; /// vector<Foo> v; /// \endcode /// the following uses will be considered convertible: /// \code /// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) { /// int b = i->bar(); /// int k = i->x + 1; /// } /// \endcode /// though /// \code /// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) { /// int k = i.insert(1); /// } /// for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) { /// int b = e->bar(); /// } /// \endcode /// will not. bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) { const Expr *Base = Member->getBase(); const DeclRefExpr *Obj = getDeclRef(Base); const Expr *ResultExpr = Member; QualType ExprType; if (const CXXOperatorCallExpr *Call = dyn_cast<CXXOperatorCallExpr>(Base->IgnoreParenImpCasts())) { // If operator->() is a MemberExpr containing a CXXOperatorCallExpr, then // the MemberExpr does not have the expression we want. We therefore catch // that instance here. // For example, if vector<Foo>::iterator defines operator->(), then the // example `i->bar()` at the top of this function is a CXXMemberCallExpr // referring to `i->` as the member function called. We want just `i`, so // we take the argument to operator->() as the base object. if(Call->getOperator() == OO_Arrow) { assert(Call->getNumArgs() == 1 && "Operator-> takes more than one argument"); Obj = getDeclRef(Call->getArg(0)); ResultExpr = Obj; ExprType = Call->getCallReturnType(); } } if (Member->isArrow() && Obj && exprReferencesVariable(IndexVar, Obj)) { if (ExprType.isNull()) ExprType = Obj->getType(); assert(ExprType->isPointerType() && "Operator-> returned non-pointer type"); // FIXME: This works around not having the location of the arrow operator. // Consider adding OperatorLoc to MemberExpr? SourceLocation ArrowLoc = Lexer::getLocForEndOfToken(Base->getExprLoc(), 0, Context->getSourceManager(), Context->getLangOpts()); // If something complicated is happening (i.e. the next token isn't an // arrow), give up on making this work. if (!ArrowLoc.isInvalid()) { Usages.push_back(Usage(ResultExpr, /*IsArrow=*/true, SourceRange(Base->getExprLoc(), ArrowLoc))); return true; } } return TraverseStmt(Member->getBase()); }
static void printSourceRange(CharSourceRange range, ASTContext &Ctx, raw_ostream &OS) { SourceManager &SM = Ctx.getSourceManager(); const LangOptions &langOpts = Ctx.getLangOpts(); PresumedLoc PL = SM.getPresumedLoc(range.getBegin()); OS << llvm::sys::path::filename(PL.getFilename()); OS << " [" << PL.getLine() << ":" << PL.getColumn(); OS << " - "; SourceLocation end = range.getEnd(); PL = SM.getPresumedLoc(end); unsigned endCol = PL.getColumn() - 1; if (!range.isTokenRange()) endCol += Lexer::MeasureTokenLength(end, SM, langOpts); OS << PL.getLine() << ":" << endCol << "]"; }
void UnnecessaryValueParamCheck::handleMoveFix(const ParmVarDecl &Var, const DeclRefExpr &CopyArgument, const ASTContext &Context) { auto Diag = diag(CopyArgument.getLocStart(), "parameter %0 is passed by value and only copied once; " "consider moving it to avoid unnecessary copies") << &Var; // Do not propose fixes in macros since we cannot place them correctly. if (CopyArgument.getLocStart().isMacroID()) return; const auto &SM = Context.getSourceManager(); auto EndLoc = Lexer::getLocForEndOfToken(CopyArgument.getLocation(), 0, SM, Context.getLangOpts()); Diag << FixItHint::CreateInsertion(CopyArgument.getLocStart(), "std::move(") << FixItHint::CreateInsertion(EndLoc, ")"); if (auto IncludeFixit = Inserter->CreateIncludeInsertion( SM.getFileID(CopyArgument.getLocStart()), "utility", /*IsAngled=*/true)) Diag << *IncludeFixit; }
static bool isEmptyARCMTMacroStatement(NullStmt *S, std::vector<SourceLocation> &MacroLocs, ASTContext &Ctx) { if (!S->hasLeadingEmptyMacro()) return false; SourceLocation SemiLoc = S->getSemiLoc(); if (SemiLoc.isInvalid() || SemiLoc.isMacroID()) return false; if (MacroLocs.empty()) return false; SourceManager &SM = Ctx.getSourceManager(); std::vector<SourceLocation>::iterator I = std::upper_bound(MacroLocs.begin(), MacroLocs.end(), SemiLoc, BeforeThanCompare<SourceLocation>(SM)); --I; SourceLocation AfterMacroLoc = I->getLocWithOffset(getARCMTMacroName().size()); assert(AfterMacroLoc.isFileID()); if (AfterMacroLoc == SemiLoc) return true; int RelOffs = 0; if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs)) return false; if (RelOffs < 0) return false; // We make the reasonable assumption that a semicolon after 100 characters // means that it is not the next token after our macro. If this assumption // fails it is not critical, we will just fail to clear out, e.g., an empty // 'if'. if (RelOffs - getARCMTMacroName().size() > 100) return false; SourceLocation AfterMacroSemiLoc = findSemiAfterLocation(AfterMacroLoc, Ctx); return AfterMacroSemiLoc == SemiLoc; }
string HtDesign::getSourceLine(ASTContext &Context, SourceLocation Loc) { SourceManager & SM = Context.getSourceManager(); // Decompose the location into a FID/Offset pair. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); FileID FID = LocInfo.first; unsigned FileOffset = LocInfo.second; // Get information about the buffer it points into. bool Invalid = false; const char *BufStart = SM.getBufferData(FID, &Invalid).data(); //if (Invalid) //return; unsigned LineNo = SM.getLineNumber(FID, FileOffset); unsigned ColNo = SM.getColumnNumber(FID, FileOffset); // Arbitrarily stop showing snippets when the line is too long. //static const size_t MaxLineLengthToPrint = 4096; //if (ColNo > MaxLineLengthToPrint) //return; // Rewind from the current position to the start of the line. const char *TokPtr = BufStart+FileOffset; const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based. // Compute the line end. Scan forward from the error position to the end of // the line. const char *LineEnd = TokPtr; while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0') ++LineEnd; // Arbitrarily stop showing snippets when the line is too long. //if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint) //return; // Copy the line of code into an std::string for ease of manipulation. return string(LineStart, LineEnd); }
bool HandleTopLevelDecl(DeclGroupRef D) override { PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), Context->getSourceManager(), "LLVM IR generation of declaration"); // Recurse. if (llvm::TimePassesIsEnabled) { LLVMIRGenerationRefCount += 1; if (LLVMIRGenerationRefCount == 1) LLVMIRGeneration.startTimer(); } Gen->HandleTopLevelDecl(D); if (llvm::TimePassesIsEnabled) { LLVMIRGenerationRefCount -= 1; if (LLVMIRGenerationRefCount == 0) LLVMIRGeneration.stopTimer(); } return true; }
void HandleTranslationUnit(ASTContext &Context) override { const auto &SourceMgr = Context.getSourceManager(); // The file we look for the USR in will always be the main source file. const auto Point = SourceMgr.getLocForStartOfFile( SourceMgr.getMainFileID()).getLocWithOffset(SymbolOffset); if (!Point.isValid()) return; const NamedDecl *FoundDecl = nullptr; if (OldName.empty()) { FoundDecl = getNamedDeclAt(Context, Point); } else { FoundDecl = getNamedDeclFor(Context, OldName); } if (FoundDecl == nullptr) { FullSourceLoc FullLoc(Point, SourceMgr); errs() << "clang-rename: could not find symbol at " << SourceMgr.getFilename(Point) << ":" << FullLoc.getSpellingLineNumber() << ":" << FullLoc.getSpellingColumnNumber() << " (offset " << SymbolOffset << ").\n"; return; } // If the decl is a constructor or destructor, we want to instead take the // decl of the parent record. if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl)) FoundDecl = CtorDecl->getParent(); else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl)) FoundDecl = DtorDecl->getParent(); // If the decl is in any way relatedpp to a class, we want to make sure we // search for the constructor and destructor as well as everything else. if (const auto *Record = dyn_cast<CXXRecordDecl>(FoundDecl)) *USRs = getAllConstructorUSRs(Record); USRs->push_back(getUSRForDecl(FoundDecl)); *SpellingName = FoundDecl->getNameAsString(); }
virtual bool VisitObjCMessageExpr(ObjCMessageExpr *E) { if (E->getReceiverKind() == ObjCMessageExpr::Class) { QualType ReceiverType = E->getClassReceiver(); Selector Sel = E->getSelector(); string TypeName = ReceiverType.getAsString(); string SelName = Sel.getAsString(); if (TypeName == "Observer" && SelName == "observerWithTarget:action:") { Expr *Receiver = E->getArg(0)->IgnoreParenCasts(); ObjCSelectorExpr* SelExpr = cast<ObjCSelectorExpr>(E->getArg(1)->IgnoreParenCasts()); Selector Sel = SelExpr->getSelector(); if (const ObjCObjectPointerType *OT = Receiver->getType()->getAs<ObjCObjectPointerType>()) { ObjCInterfaceDecl *decl = OT->getInterfaceDecl(); if (! decl->lookupInstanceMethod(Sel)) { errs() << "Warning: class " << TypeName << " does not implement selector " << Sel.getAsString() << "\n"; SourceLocation Loc = E->getExprLoc(); PresumedLoc PLoc = astContext->getSourceManager().getPresumedLoc(Loc); errs() << "in " << PLoc.getFilename() << " <" << PLoc.getLine() << ":" << PLoc.getColumn() << ">\n"; } } } } return true; }
/// \brief \arg Loc is the end of a statement range. This returns the location /// of the semicolon following the statement. /// If no semicolon is found or the location is inside a macro, the returned /// source location will be invalid. SourceLocation trans::findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, bool IsDecl) { SourceManager &SM = Ctx.getSourceManager(); if (loc.isMacroID()) { if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc)) return SourceLocation(); } loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts()); // Break down the source location. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc); // Try to load the file buffer. bool invalidTemp = false; StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); if (invalidTemp) return SourceLocation(); const char *tokenBegin = file.data() + locInfo.second; // Lex from the start of the given location. Lexer lexer(SM.getLocForStartOfFile(locInfo.first), Ctx.getLangOpts(), file.begin(), tokenBegin, file.end()); Token tok; lexer.LexFromRawLexer(tok); if (tok.isNot(tok::semi)) { if (!IsDecl) return SourceLocation(); // Declaration may be followed with other tokens; such as an __attribute, // before ending with a semicolon. return findSemiAfterLocation(tok.getLocation(), Ctx, /*IsDecl*/true); } return tok.getLocation(); }
void HandleTranslationUnit(ASTContext &Context) override { const SourceManager &SourceMgr = Context.getSourceManager(); // The file we look for the USR in will always be the main source file. const SourceLocation Point = SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()) .getLocWithOffset(SymbolOffset); if (!Point.isValid()) return; const NamedDecl *FoundDecl = nullptr; if (OldName.empty()) { FoundDecl = getNamedDeclAt(Context, Point); } else { FoundDecl = getNamedDeclFor(Context, OldName); } if (FoundDecl == nullptr) { FullSourceLoc FullLoc(Point, SourceMgr); errs() << "clang-rename: could not find symbol at " << SourceMgr.getFilename(Point) << ":" << FullLoc.getSpellingLineNumber() << ":" << FullLoc.getSpellingColumnNumber() << " (offset " << SymbolOffset << ").\n"; return; } // If FoundDecl is a constructor or destructor, we want to instead take the // Decl of the corresponding class. if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl)) { FoundDecl = CtorDecl->getParent(); } else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl)) { FoundDecl = DtorDecl->getParent(); } *SpellingName = FoundDecl->getNameAsString(); AdditionalUSRFinder Finder(FoundDecl, Context, USRs); Finder.Find(); }
bool SynthesizeRemovalConsumer::shouldIgnore(SourceLocation L) { if (!L.isValid()) { return true; } SourceManager &SM = astContext->getSourceManager(); FullSourceLoc FSL(L, SM); const FileEntry *FE = SM.getFileEntryForID(FSL.getFileID()); if (!FE) { // attempt to get the spelling location auto SL = SM.getSpellingLoc(L); if (!SL.isValid()) { return true; } FullSourceLoc FSL2(SL, SM); FE = SM.getFileEntryForID(FSL2.getFileID()); if (!FE) { return true; } } return false; }
bool TraverseStmt(Stmt *x) { std::string classname_logendl = "logendl"; // int id = ++_count; // outs() << "BEGIN TraverseStmt [" << id << "]\n"; bool found_interesting_statement_in_this_recursion = false; bool found_first_lessless_of_ilogline = false; if (x != nullptr) { // auto stmt_class_name = x->getStmtClassName(); // outs() << " Stmt ClassName='" << stmt_class_name << "'\n"; // Try to figure out if it's an expression we can determine a type for Expr* expr = nullptr; switch( x->getStmtClass() ) { case Stmt::CXXOperatorCallExprClass: { _output_enabled = true; found_interesting_statement_in_this_recursion = true; //outs() << " Found Expr of interest!\n"; CXXOperatorCallExpr* cxxoper_expr = reinterpret_cast<CXXOperatorCallExpr*>(x); expr = cxxoper_expr; if( cxxoper_expr) { //outs() << " QualType as string: " << get_qual_type_string(cxxoper_expr) << "\n"; if( isLessLessOfILogLine( cxxoper_expr ) ) { if( !_found_logging ) { found_first_lessless_of_ilogline = true; _found_logging = true; //outs() << " Found logging!\n"; } if (found_first_lessless_of_ilogline && isLessLessOnLogEndl(cxxoper_expr)) { _found_endl_at_end = true; //outs() << " Found endl at end!\n"; } } } } break; default: break; } } //outs() << "DIVE TraverseStmt [" << id << "]\n"; ++_depth; RecursiveASTVisitor<FindNamedClassVisitor>::TraverseStmt(x); --_depth; //outs() << "END TraverseStmt [" << id << "]\n"; if( found_interesting_statement_in_this_recursion ) { if( _found_logging && !_found_endl_at_end ) { /* if( outs().has_colors() ) { outs().changeColor(raw_ostream::RED); } */ FullSourceLoc FullLocation = Context->getFullLoc(x->getLocStart()); SourceManager& SourceMgr = Context->getSourceManager(); PresumedLoc pLoc = SourceMgr.getPresumedLoc( FullLocation ); outs() << "ERROR on " << pLoc.getFilename() << " " << pLoc.getLine() << ":" << pLoc.getColumn() << ": Found statement in which the logger is used, but endl isn't at the end\n"; /* if( outs().has_colors() ) { outs().changeColor(raw_ostream::WHITE, false); } */ } reset_after_recusion_into_interesting(); } return true; }