void XCTMigrator::migrateRef(NamedDecl *D, SourceLocation Loc) { if (!D || Loc.isInvalid()) return; llvm::DenseMap<IdentifierInfo *, IdentifierInfo *>::iterator DI = DeclsMap.find(D->getDeclName().getAsIdentifierInfo()); if (DI == DeclsMap.end()) return; if (!isFromSenTestInclude(D->getLocation()) || isFromSenTestInclude(Loc)) return; assert(DI->second); edit::Commit commit(Editor); commit.replace(Loc, DI->second->getName()); Editor.commit(commit); }
CXSourceLocation lfort_getLocationForOffset(CXProgram tu, CXFile file, unsigned offset) { if (!tu || !file) return lfort_getNullLocation(); ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->PgmData); SourceLocation SLoc = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset); if (SLoc.isInvalid()) return lfort_getNullLocation(); return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); }
void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const { SourceLocation TheLoc = Loc; if (TheLoc.isInvalid() && TheDecl) TheLoc = TheDecl->getLocation(); if (TheLoc.isValid()) { TheLoc.print(OS, SM); OS << ": "; } OS << Message; if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl)) OS << " '" << DN->getQualifiedNameAsString() << '\''; OS << '\n'; }
// Parses module references in the given lines. Returns the module references, // and a pointer to the first "main code" line if that is adjacent to the // affected lines of module references, nullptr otherwise. std::pair<SmallVector<JsModuleReference, 16>, AnnotatedLine*> parseModuleReferences(const AdditionalKeywords &Keywords, SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) { SmallVector<JsModuleReference, 16> References; SourceLocation Start; AnnotatedLine *FirstNonImportLine = nullptr; bool AnyImportAffected = false; for (auto Line : AnnotatedLines) { Current = Line->First; LineEnd = Line->Last; skipComments(); if (Start.isInvalid() || References.empty()) // After the first file level comment, consider line comments to be part // of the import that immediately follows them by using the previously // set Start. Start = Line->First->Tok.getLocation(); if (!Current) { // Only comments on this line. Could be the first non-import line. FirstNonImportLine = Line; continue; } JsModuleReference Reference; Reference.Range.setBegin(Start); if (!parseModuleReference(Keywords, Reference)) { if (!FirstNonImportLine) FirstNonImportLine = Line; // if no comment before. break; } FirstNonImportLine = nullptr; AnyImportAffected = AnyImportAffected || Line->Affected; Reference.Range.setEnd(LineEnd->Tok.getEndLoc()); DEBUG({ llvm::dbgs() << "JsModuleReference: {" << "is_export: " << Reference.IsExport << ", cat: " << Reference.Category << ", url: " << Reference.URL << ", prefix: " << Reference.Prefix; for (size_t i = 0; i < Reference.Symbols.size(); ++i) llvm::dbgs() << ", " << Reference.Symbols[i].Symbol << " as " << Reference.Symbols[i].Alias; llvm::dbgs() << ", text: " << getSourceText(Reference.Range); llvm::dbgs() << "}\n"; }); References.push_back(Reference); Start = SourceLocation(); }
static void addUsage(IdentifierNamingCheck::NamingCheckFailureMap &Failures, const IdentifierNamingCheck::NamingCheckId &Decl, SourceRange Range, SourceManager *SourceMgr = nullptr) { // Do nothing if the provided range is invalid. if (Range.getBegin().isInvalid() || Range.getEnd().isInvalid()) return; // If we have a source manager, use it to convert to the spelling location for // performing the fix. This is necessary because macros can map the same // spelling location to different source locations, and we only want to fix // the token once, before it is expanded by the macro. SourceLocation FixLocation = Range.getBegin(); if (SourceMgr) FixLocation = SourceMgr->getSpellingLoc(FixLocation); if (FixLocation.isInvalid()) return; // Try to insert the identifier location in the Usages map, and bail out if it // is already in there auto &Failure = Failures[Decl]; if (!Failure.RawUsageLocs.insert(FixLocation.getRawEncoding()).second) return; if (!Failure.ShouldFix) return; // Check if the range is entirely contained within a macro argument. SourceLocation MacroArgExpansionStartForRangeBegin; SourceLocation MacroArgExpansionStartForRangeEnd; bool RangeIsEntirelyWithinMacroArgument = SourceMgr && SourceMgr->isMacroArgExpansion(Range.getBegin(), &MacroArgExpansionStartForRangeBegin) && SourceMgr->isMacroArgExpansion(Range.getEnd(), &MacroArgExpansionStartForRangeEnd) && MacroArgExpansionStartForRangeBegin == MacroArgExpansionStartForRangeEnd; // Check if the range contains any locations from a macro expansion. bool RangeContainsMacroExpansion = RangeIsEntirelyWithinMacroArgument || Range.getBegin().isMacroID() || Range.getEnd().isMacroID(); bool RangeCanBeFixed = RangeIsEntirelyWithinMacroArgument || !RangeContainsMacroExpansion; Failure.ShouldFix = RangeCanBeFixed; }
void TextDiagnosticPrinter:: PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) { if (Loc.isInvalid()) return; PresumedLoc PLoc = SM.getPresumedLoc(Loc); if (PLoc.isInvalid()) return; // Print out the other include frames first. PrintIncludeStack(PLoc.getIncludeLoc(), SM); if (DiagOpts->ShowLocation) OS << "In file included from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; else OS << "In included file:\n"; }
/// \brief Helper to recursivly walk up the include stack and print each layer /// on the way back down. void TextDiagnostic::emitIncludeStackRecursively(SourceLocation Loc) { if (Loc.isInvalid()) return; PresumedLoc PLoc = SM.getPresumedLoc(Loc); if (PLoc.isInvalid()) return; // Emit the other include frames first. emitIncludeStackRecursively(PLoc.getIncludeLoc()); if (DiagOpts.ShowLocation) OS << "In file included from " << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n"; else OS << "In included file:\n"; }
void MakeSmartPtrCheck::checkReset(SourceManager &SM, const CXXMemberCallExpr *Reset, const CXXNewExpr *New) { const auto *Expr = cast<MemberExpr>(Reset->getCallee()); SourceLocation OperatorLoc = Expr->getOperatorLoc(); SourceLocation ResetCallStart = Reset->getExprLoc(); SourceLocation ExprStart = Expr->getLocStart(); SourceLocation ExprEnd = Lexer::getLocForEndOfToken(Expr->getLocEnd(), 0, SM, getLangOpts()); bool InMacro = ExprStart.isMacroID(); if (InMacro && IgnoreMacros) { return; } // There are some cases where we don't have operator ("." or "->") of the // "reset" expression, e.g. call "reset()" method directly in the subclass of // "std::unique_ptr<>". We skip these cases. if (OperatorLoc.isInvalid()) { return; } auto Diag = diag(ResetCallStart, "use %0 instead") << MakeSmartPtrFunctionName; // Disable the fix in macros. if (InMacro) { return; } if (!replaceNew(Diag, New, SM)) { return; } Diag << FixItHint::CreateReplacement( CharSourceRange::getCharRange(OperatorLoc, ExprEnd), (llvm::Twine(" = ") + MakeSmartPtrFunctionName + "<" + GetNewExprName(New, SM, getLangOpts()) + ">") .str()); if (Expr->isArrow()) Diag << FixItHint::CreateInsertion(ExprStart, "*"); insertHeader(Diag, SM.getFileID(OperatorLoc)); }
bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor, const NamedDecl *Parent, const DeclContext *DC, const Expr *E, CXIdxEntityRefKind Kind) { if (!CB.indexEntityReference) return false; if (!D) return false; if (Loc.isInvalid()) return false; if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) return false; if (isNotFromSourceFile(D->getLocation())) return false; if (D->isImplicit() && shouldIgnoreIfImplicit(D)) return false; if (shouldSuppressRefs()) { if (markEntityOccurrenceInFile(D, Loc)) return false; // already occurred. } ScratchAlloc SA(*this); EntityInfo RefEntity, ParentEntity; getEntityInfo(D, RefEntity, SA); if (!RefEntity.USR) return false; getEntityInfo(Parent, ParentEntity, SA); ContainerInfo Container; getContainerInfo(DC, Container); CXIdxEntityRefInfo Info = { Kind, Cursor, getIndexLoc(Loc), &RefEntity, Parent ? &ParentEntity : nullptr, &Container }; CB.indexEntityReference(ClientData, &Info); return true; }
void BackendConsumer::EmitOptimizationRemark( const llvm::DiagnosticInfoOptimizationRemarkBase &D, unsigned DiagID) { // We only support remarks. assert(D.getSeverity() == llvm::DS_Remark); SourceManager &SourceMgr = Context->getSourceManager(); FileManager &FileMgr = SourceMgr.getFileManager(); StringRef Filename; unsigned Line, Column; D.getLocation(&Filename, &Line, &Column); SourceLocation DILoc; const FileEntry *FE = FileMgr.getFile(Filename); if (FE && Line > 0) { // If -gcolumn-info was not used, Column will be 0. This upsets the // source manager, so pass 1 if Column is not set. DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1); } // If a location isn't available, try to approximate it using the associated // function definition. We use the definition's right brace to differentiate // from diagnostics that genuinely relate to the function itself. FullSourceLoc Loc(DILoc, SourceMgr); if (Loc.isInvalid()) if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) Loc = FD->getASTContext().getFullLoc(FD->getBodyRBrace()); Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName()) << D.getMsg().str(); if (Line == 0) // If we could not extract a source location for the diagnostic, // inform the user how they can get source locations back. // // FIXME: We should really be generating !srcloc annotations when // -Rpass is used. !srcloc annotations need to be emitted in // approximately the same spots as !dbg nodes. Diags.Report(Loc, diag::note_fe_backend_optimization_remark_missing_loc); else if (DILoc.isInvalid()) // If we were not able to translate the file:line:col information // back to a SourceLocation, at least emit a note stating that // we could not translate this location. This can happen in the // case of #line directives. Diags.Report(Loc, diag::note_fe_backend_optimization_remark_invalid_loc) << Filename << Line << Column; }
static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, bool IsNSIntegerType) { std::string ClassString = IsNSIntegerType ? "typedef NS_ENUM(NSInteger, " : "typedef NS_OPTIONS(NSUInteger, "; ClassString += TypedefDcl->getIdentifier()->getName(); ClassString += ')'; SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart()); commit.replace(R, ClassString); SourceLocation EndOfTypedefLoc = TypedefDcl->getLocEnd(); EndOfTypedefLoc = trans::findLocationAfterSemi(EndOfTypedefLoc, NS.getASTContext()); if (!EndOfTypedefLoc.isInvalid()) { commit.remove(SourceRange(TypedefDcl->getLocStart(), EndOfTypedefLoc)); return true; } return false; }
/// \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()); }
void BackendConsumer::OptimizationRemarkHandler( const llvm::DiagnosticInfoOptimizationRemark &D) { // We only support remarks. assert(D.getSeverity() == llvm::DS_Remark); // Optimization remarks are active only if -Rpass=regexp is given and the // regular expression pattern in 'regexp' matches the name of the pass // name in \p D. if (CodeGenOpts.OptimizationRemarkPattern && CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) { SourceManager &SourceMgr = Context->getSourceManager(); FileManager &FileMgr = SourceMgr.getFileManager(); StringRef Filename; unsigned Line, Column; D.getLocation(&Filename, &Line, &Column); SourceLocation Loc; const FileEntry *FE = FileMgr.getFile(Filename); if (FE && Line > 0) { // If -gcolumn-info was not used, Column will be 0. This upsets the // source manager, so if Column is not set, set it to 1. if (Column == 0) Column = 1; Loc = SourceMgr.translateFileLineCol(FE, Line, Column); } Diags.Report(Loc, diag::remark_fe_backend_optimization_remark) << AddFlagValue(D.getPassName()) << D.getMsg().str(); if (Line == 0) // If we could not extract a source location for the diagnostic, // inform the user how they can get source locations back. // // FIXME: We should really be generating !srcloc annotations when // -Rpass is used. !srcloc annotations need to be emitted in // approximately the same spots as !dbg nodes. Diags.Report(diag::note_fe_backend_optimization_remark_missing_loc); else if (Loc.isInvalid()) // If we were not able to translate the file:line:col information // back to a SourceLocation, at least emit a note stating that // we could not translate this location. This can happen in the // case of #line directives. Diags.Report(diag::note_fe_backend_optimization_remark_invalid_loc) << Filename << Line << Column; } }
static void WriteSourceLocation(llvm::raw_ostream &OS, SourceManager *SM, SourceLocation Location) { if (!SM || Location.isInvalid()) { // If we don't have a source manager or this location is invalid, // just write an invalid location. WriteUnsigned(OS, 0); WriteUnsigned(OS, 0); WriteUnsigned(OS, 0); return; } Location = SM->getInstantiationLoc(Location); std::pair<FileID, unsigned> Decomposed = SM->getDecomposedLoc(Location); WriteString(OS, SM->getFileEntryForID(Decomposed.first)->getName()); WriteUnsigned(OS, SM->getLineNumber(Decomposed.first, Decomposed.second)); WriteUnsigned(OS, SM->getColumnNumber(Decomposed.first, Decomposed.second)); }
/// \brief Helper to recursivly walk up the import stack and print each layer /// on the way back down. void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName, const SourceManager &SM) { if (Loc.isInvalid()) { return; } PresumedLoc PLoc = SM.getPresumedLoc(Loc); if (PLoc.isInvalid()) return; // Emit the other import frames first. std::pair<SourceLocation, StringRef> NextImportLoc = SM.getModuleImportLoc(Loc); emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM); // Emit the inclusion text/note. emitImportLocation(Loc, PLoc, ModuleName, SM); }
void SDiagsWriter::AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record, unsigned TokSize) { if (Loc.isInvalid()) { // Emit a "sentinel" location. Record.push_back((unsigned)0); // File. Record.push_back((unsigned)0); // Line. Record.push_back((unsigned)0); // Column. Record.push_back((unsigned)0); // Offset. return; } SourceManager &SM = Diags.getSourceManager(); Loc = SM.getSpellingLoc(Loc); Record.push_back(getEmitFile(Loc)); Record.push_back(SM.getSpellingLineNumber(Loc)); Record.push_back(SM.getSpellingColumnNumber(Loc)+TokSize); Record.push_back(SM.getFileOffset(Loc)); }
void BackendConsumer::EmitOptimizationMessage( const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { // We only support warnings and remarks. assert(D.getSeverity() == llvm::DS_Remark || D.getSeverity() == llvm::DS_Warning); SourceManager &SourceMgr = Context->getSourceManager(); FileManager &FileMgr = SourceMgr.getFileManager(); StringRef Filename; unsigned Line, Column; SourceLocation DILoc; if (D.isLocationAvailable()) { D.getLocation(&Filename, &Line, &Column); const FileEntry *FE = FileMgr.getFile(Filename); if (FE && Line > 0) { // If -gcolumn-info was not used, Column will be 0. This upsets the // source manager, so pass 1 if Column is not set. DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1); } } // If a location isn't available, try to approximate it using the associated // function definition. We use the definition's right brace to differentiate // from diagnostics that genuinely relate to the function itself. FullSourceLoc Loc(DILoc, SourceMgr); if (Loc.isInvalid()) if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) Loc = FD->getASTContext().getFullLoc(FD->getBodyRBrace()); Diags.Report(Loc, DiagID) << AddFlagValue(D.getPassName() ? D.getPassName() : "") << D.getMsg().str(); if (DILoc.isInvalid() && D.isLocationAvailable()) // If we were not able to translate the file:line:col information // back to a SourceLocation, at least emit a note stating that // we could not translate this location. This can happen in the // case of #line directives. Diags.Report(Loc, diag::note_fe_backend_optimization_remark_invalid_loc) << Filename << Line << Column; }
/// \brief Require that the context specified by SS be complete. /// /// If SS refers to a type, this routine checks whether the type is /// complete enough (or can be made complete enough) for name lookup /// into the DeclContext. A type that is not yet completed can be /// considered "complete enough" if it is a class/struct/union/enum /// that is currently being defined. Or, if we have a type that names /// a class template specialization that is not a complete type, we /// will attempt to instantiate that class template. bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, DeclContext *DC) { assert(DC != 0 && "given null context"); if (TagDecl *tag = dyn_cast<TagDecl>(DC)) { // If this is a dependent type, then we consider it complete. if (tag->isDependentContext()) return false; // If we're currently defining this type, then lookup into the // type is okay: don't complain that it isn't complete yet. QualType type = Context.getTypeDeclType(tag); const TagType *tagType = type->getAs<TagType>(); if (tagType && tagType->isBeingDefined()) return false; SourceLocation loc = SS.getLastQualifierNameLoc(); if (loc.isInvalid()) loc = SS.getRange().getBegin(); // The type must be complete. if (RequireCompleteType(loc, type, PDiag(diag::err_incomplete_nested_name_spec) << SS.getRange())) { SS.SetInvalid(SS.getRange()); return true; } // Fixed enum types are complete, but they aren't valid as scopes // until we see a definition, so awkwardly pull out this special // case. if (const EnumType *enumType = dyn_cast_or_null<EnumType>(tagType)) { if (!enumType->getDecl()->isCompleteDefinition()) { Diag(loc, diag::err_incomplete_nested_name_spec) << type << SS.getRange(); SS.SetInvalid(SS.getRange()); return true; } } } return false; }
void clang_indexLoc_getFileLocation(CXIdxLoc location, CXIdxClientFile *indexFile, CXFile *file, unsigned *line, unsigned *column, unsigned *offset) { if (indexFile) *indexFile = 0; if (file) *file = 0; if (line) *line = 0; if (column) *column = 0; if (offset) *offset = 0; SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); if (!location.ptr_data[0] || Loc.isInvalid()) return; IndexingContext &IndexCtx = *static_cast<IndexingContext*>(location.ptr_data[0]); IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset); }
CXSourceLocation clang_getLocationForOffset(CXTranslationUnit TU, CXFile file, unsigned offset) { if (cxtu::isNotUsableTU(TU)) { LOG_BAD_TU(TU); return clang_getNullLocation(); } if (!file) return clang_getNullLocation(); ASTUnit *CXXUnit = cxtu::getASTUnit(TU); SourceLocation SLoc = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset); if (SLoc.isInvalid()) return clang_getNullLocation(); return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); }
bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc, const SourceManager &SM, SmallVectorImpl<char> &Buf) { // Don't generate USRs for things with invalid locations. if (MacroName.empty() || Loc.isInvalid()) return true; llvm::raw_svector_ostream Out(Buf); // Assume that system headers are sane. Don't put source location // information into the USR if the macro comes from a system header. bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc); Out << getUSRSpacePrefix(); if (ShouldGenerateLocation) printLoc(Out, Loc, SM, /*IncludeOffset=*/true); Out << "@macro@"; Out << MacroName; return false; }
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; }
void lfort_getExpansionLocation(CXSourceLocation location, CXFile *file, unsigned *line, unsigned *column, unsigned *offset) { if (!isASTUnitSourceLocation(location)) { CXLoadedDiagnostic::decodeLocation(location, file, line, column, offset); return; } SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); if (!location.ptr_data[0] || Loc.isInvalid()) { createNullLocation(file, line, column, offset); return; } const SourceManager &SM = *static_cast<const SourceManager*>(location.ptr_data[0]); SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc); // Check that the FileID is invalid on the expansion location. // This can manifest in invalid code. FileID fileID = SM.getFileID(ExpansionLoc); bool Invalid = false; const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid); if (Invalid || !sloc.isFile()) { createNullLocation(file, line, column, offset); return; } if (file) *file = (void *)SM.getFileEntryForSLocEntry(sloc); if (line) *line = SM.getExpansionLineNumber(ExpansionLoc); if (column) *column = SM.getExpansionColumnNumber(ExpansionLoc); if (offset) *offset = SM.getDecomposedLoc(ExpansionLoc).second; }
bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc) { if (!D || Loc.isInvalid()) return true; SourceManager &SM = Ctx->getSourceManager(); D = getEntityDecl(D); std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc)); FileID FID = LocInfo.first; if (FID.isInvalid()) return true; const FileEntry *FE = SM.getFileEntryForID(FID); if (!FE) return true; RefFileOccurrence RefOccur(FE, D); std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool> res = RefFileOccurrences.insert(RefOccur); return !res.second; // already in map }
AnalysisConsumer::AnalysisMode AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) { if (!Opts->AnalyzeSpecificFunction.empty() && getFunctionName(D) != Opts->AnalyzeSpecificFunction) return AM_None; // Unless -analyze-all is specified, treat decls differently depending on // where they came from: // - Main source file: run both path-sensitive and non-path-sensitive checks. // - Header files: run non-path-sensitive checks only. // - System headers: don't run any checks. SourceManager &SM = Ctx->getSourceManager(); SourceLocation SL = SM.getExpansionLoc(D->getLocation()); if (!Opts->AnalyzeAll && !SM.isInMainFile(SL)) { if (SL.isInvalid() || SM.isInSystemHeader(SL)) return AM_None; return Mode & ~AM_Path; } return Mode; }
/// \returns true on error. static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, const SourceManager &SM, bool IncludeOffset) { if (Loc.isInvalid()) { return true; } Loc = SM.getExpansionLoc(Loc); const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(Loc); const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); if (FE) { OS << llvm::sys::path::filename(FE->getName()); } else { // This case really isn't interesting. return true; } if (IncludeOffset) { // Use the offest into the FileID to represent the location. Using // a line/column can cause us to look back at the original source file, // which is expensive. OS << '@' << Decomposed.second; } return false; }
void RewriteBlocks::HandleTopLevelSingleDecl(Decl *D) { // Two cases: either the decl could be in the main file, or it could be in a // #included file. If the former, rewrite it now. If the later, check to see // if we rewrote the #include/#import. SourceLocation Loc = D->getLocation(); Loc = SM->getInstantiationLoc(Loc); // If this is for a builtin, ignore it. if (Loc.isInvalid()) return; if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) RewriteInterfaceDecl(MD); else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) RewriteCategoryDecl(CD); else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) RewriteProtocolDecl(PD); // If we have a decl in the main file, see if we should rewrite it. if (SM->isFromMainFile(Loc)) HandleDeclInMainFile(D); return; }
bool IndexingContext::importedModule(const ImportDecl *ImportD) { SourceLocation Loc; auto IdLocs = ImportD->getIdentifierLocs(); if (!IdLocs.empty()) Loc = IdLocs.front(); else Loc = ImportD->getLocation(); SourceManager &SM = Ctx->getSourceManager(); Loc = SM.getFileLoc(Loc); if (Loc.isInvalid()) return true; FileID FID; unsigned Offset; std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); if (FID.isInvalid()) return true; bool Invalid = false; const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); if (Invalid || !SEntry.isFile()) return true; if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { switch (IndexOpts.SystemSymbolFilter) { case IndexingOptions::SystemSymbolFilterKind::None: return true; case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: case IndexingOptions::SystemSymbolFilterKind::All: break; } } SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration; if (ImportD->isImplicit()) Roles |= (unsigned)SymbolRole::Implicit; return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset); }
/// Build scope information for a captured block literal variables. void JumpScopeChecker::BuildScopeInformation(VarDecl *D, const BlockDecl *BDecl, unsigned &ParentScope) { // exclude captured __block variables; there's no destructor // associated with the block literal for them. if (D->hasAttr<BlocksAttr>()) return; QualType T = D->getType(); QualType::DestructionKind destructKind = T.isDestructedType(); if (destructKind != QualType::DK_none) { std::pair<unsigned,unsigned> Diags; switch (destructKind) { case QualType::DK_cxx_destructor: Diags = ScopePair(diag::note_enters_block_captures_cxx_obj, diag::note_exits_block_captures_cxx_obj); break; case QualType::DK_objc_strong_lifetime: Diags = ScopePair(diag::note_enters_block_captures_strong, diag::note_exits_block_captures_strong); break; case QualType::DK_objc_weak_lifetime: Diags = ScopePair(diag::note_enters_block_captures_weak, diag::note_exits_block_captures_weak); break; case QualType::DK_nontrivial_c_struct: Diags = ScopePair(diag::note_enters_block_captures_non_trivial_c_struct, diag::note_exits_block_captures_non_trivial_c_struct); break; case QualType::DK_none: llvm_unreachable("non-lifetime captured variable"); } SourceLocation Loc = D->getLocation(); if (Loc.isInvalid()) Loc = BDecl->getLocation(); Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second, Loc)); ParentScope = Scopes.size()-1; } }
bool RewriteUtils::replaceRecordType(RecordTypeLoc &RTLoc, const std::string &Name) { const IdentifierInfo *TypeId = RTLoc.getType().getBaseTypeIdentifier(); SourceLocation LocStart = RTLoc.getLocStart(); // Loc could be invalid, for example: // class AAA { }; // class BBB:AAA { // public: // BBB () { } // }; // In Clang's internal representation, BBB's Ctor is BBB() : AAA() {} // The implicit AAA() will be visited here // This is the only case where RTLoc is invalid, so the question is - // Is the guard below too strong? It is possible it could mask other // potential bugs? if (LocStart.isInvalid()) return true; return !(TheRewriter->ReplaceText(LocStart, TypeId->getLength(), Name)); }