bool SemaAnnotator::walkToDeclPre(Decl *D) { if (isDone()) return false; bool ShouldVisitChildren; if (shouldIgnore(D, ShouldVisitChildren)) return ShouldVisitChildren; SourceLoc Loc = D->getLoc(); unsigned NameLen = 0; if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { if (VD->hasName()) NameLen = VD->getName().getLength(); } else if (ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D)) { SourceRange SR = ED->getExtendedTypeLoc().getSourceRange(); Loc = SR.Start; if (Loc.isValid()) NameLen = ED->getASTContext().SourceMgr.getByteDistance(SR.Start, SR.End); } else if (auto Import = dyn_cast<ImportDecl>(D)) { if (!handleImports(Import)) return false; } else { return true; } CharSourceRange Range = (Loc.isValid()) ? CharSourceRange(Loc, NameLen) : CharSourceRange(); return SEWalker.walkToDeclPre(D, Range); }
static void mapping(llvm::yaml::IO &io, Remark<KindT> &R) { assert(io.outputting() && "input not implemented"); if (io.mapTag("!Passed", std::is_same<KindT, RemarkPassed>::value)) ; else if (io.mapTag("!Missed", std::is_same<KindT, RemarkMissed>::value)) ; else llvm_unreachable("Unknown remark type"); // The attributes are read-only for now since we're only support outputting // them. StringRef PassName = R.getPassName(); io.mapRequired("Pass", PassName); std::string Id = (Twine("sil.") + R.getIdentifier()).str(); io.mapRequired("Name", Id); SourceLoc Loc = R.getLocation(); if (!io.outputting() || Loc.isValid()) io.mapOptional("DebugLoc", Loc); std::string FN = Demangle::demangleSymbolAsString( R.getFunction()->getName(), Demangle::DemangleOptions::SimplifiedUIDemangleOptions()); io.mapRequired("Function", FN); io.mapOptional("Args", R.getArgs()); }
bool SemaAnnotator::passCallArgNames(Expr *Fn, TupleExpr *TupleE) { ValueDecl *D = extractDecl(Fn); if (!D) return true; // continue. ArrayRef<Identifier> ArgNames = TupleE->getElementNames(); ArrayRef<SourceLoc> ArgLocs = TupleE->getElementNameLocs(); for (auto i : indices(ArgNames)) { Identifier Name = ArgNames[i]; if (Name.empty()) continue; SourceLoc Loc = ArgLocs[i]; if (Loc.isInvalid()) continue; CharSourceRange Range{ Loc, Name.getLength() }; bool Continue = SEWalker.visitCallArgName(Name, Range, D); if (!Continue) { Cancelled = true; return false; } } return true; }
static SourceLoc getDeclStartPosition(SourceFile &File) { SourceManager &SM = File.getASTContext().SourceMgr; SourceLoc Winner; auto tryUpdateStart = [&](SourceLoc Loc) -> bool { if (Loc.isInvalid()) return false; if (Winner.isInvalid()) { Winner = Loc; return true; } if (SM.isBeforeInBuffer(Loc, Winner)) { Winner = Loc; return true; } return false; }; for (auto D : File.Decls) { if (tryUpdateStart(D->getStartLoc())) { tryUpdateStart(D->getAttrs().getStartLoc()); auto RawComment = D->getRawComment(); if (!RawComment.isEmpty()) tryUpdateStart(RawComment.Comments.front().Range.getStart()); } } return Winner; }
void AccessScope::dump() const { llvm::errs() << getAccessLevelSpelling(accessLevelForDiagnostics()) << ": "; if (isPublic()) { llvm::errs() << "(null)\n"; return; } if (auto *file = dyn_cast<SourceFile>(getDeclContext())) { llvm::errs() << "file '" << file->getFilename() << "'\n"; return; } if (auto *decl = getDeclContext()->getAsDecl()) { llvm::errs() << Decl::getKindName(decl->getKind()) << " "; if (auto *ext = dyn_cast<ExtensionDecl>(decl)) llvm::errs() << ext->getExtendedNominal()->getName(); else if (auto *named = dyn_cast<ValueDecl>(decl)) llvm::errs() << named->getFullName(); else llvm::errs() << (const void *)decl; SourceLoc loc = decl->getLoc(); if (loc.isValid()) { llvm::errs() << " at "; loc.print(llvm::errs(), decl->getASTContext().SourceMgr); } llvm::errs() << "\n"; return; } // If all else fails, dump the DeclContext tree. getDeclContext()->printContext(llvm::errs()); }
SourceLoc ClangDiagnosticConsumer::resolveSourceLocation( const clang::SourceManager &clangSrcMgr, clang::SourceLocation clangLoc) { SourceManager &swiftSrcMgr = ImporterImpl.SwiftContext.SourceMgr; SourceLoc loc; clangLoc = clangSrcMgr.getFileLoc(clangLoc); auto decomposedLoc = clangSrcMgr.getDecomposedLoc(clangLoc); if (decomposedLoc.first.isInvalid()) return loc; auto buffer = clangSrcMgr.getBuffer(decomposedLoc.first); unsigned mirrorID; auto mirrorIter = mirroredBuffers.find(buffer); if (mirrorIter != mirroredBuffers.end()) { mirrorID = mirrorIter->second; } else { std::unique_ptr<llvm::MemoryBuffer> mirrorBuffer{ llvm::MemoryBuffer::getMemBuffer(buffer->getBuffer(), buffer->getBufferIdentifier(), /*nullTerminated=*/true) }; mirrorID = swiftSrcMgr.addNewSourceBuffer(std::move(mirrorBuffer)); mirroredBuffers[buffer] = mirrorID; } loc = swiftSrcMgr.getLocForOffset(mirrorID, decomposedLoc.second); auto presumedLoc = clangSrcMgr.getPresumedLoc(clangLoc); if (!presumedLoc.getFilename()) return loc; if (presumedLoc.getLine() == 0) return SourceLoc(); unsigned bufferLineNumber = clangSrcMgr.getLineNumber(decomposedLoc.first, decomposedLoc.second); StringRef presumedFile = presumedLoc.getFilename(); SourceLoc startOfLine = loc.getAdvancedLoc(-presumedLoc.getColumn() + 1); bool isNewVirtualFile = swiftSrcMgr.openVirtualFile(startOfLine, presumedFile, presumedLoc.getLine() - bufferLineNumber); if (isNewVirtualFile) { SourceLoc endOfLine = findEndOfLine(swiftSrcMgr, loc, mirrorID); swiftSrcMgr.closeVirtualFile(endOfLine); } using SourceManagerRef = llvm::IntrusiveRefCntPtr<const clang::SourceManager>; auto iter = std::lower_bound(sourceManagersWithDiagnostics.begin(), sourceManagersWithDiagnostics.end(), &clangSrcMgr, [](const SourceManagerRef &inArray, const clang::SourceManager *toInsert) { return std::less<const clang::SourceManager *>()(inArray.get(), toInsert); }); if (iter->get() != &clangSrcMgr) sourceManagersWithDiagnostics.insert(iter, &clangSrcMgr); return loc; }
/// \brief Tokenizes a string literal, taking into account string interpolation. static void getStringPartTokens(const Token &Tok, const LangOptions &LangOpts, const SourceManager &SM, int BufID, std::vector<Token> &Toks) { assert(Tok.is(tok::string_literal)); bool IsMultiline = Tok.IsMultilineString(); unsigned QuoteLen = IsMultiline ? 3 : 1; SmallVector<Lexer::StringSegment, 4> Segments; Lexer::getStringLiteralSegments(Tok, Segments, /*Diags=*/nullptr); for (unsigned i = 0, e = Segments.size(); i != e; ++i) { Lexer::StringSegment &Seg = Segments[i]; bool isFirst = i == 0; bool isLast = i == e-1; if (Seg.Kind == Lexer::StringSegment::Literal) { SourceLoc Loc = Seg.Loc; unsigned Len = Seg.Length; if (isFirst) { // Include the quote. Loc = Loc.getAdvancedLoc(-QuoteLen); Len += QuoteLen; } if (isLast) { // Include the quote. Len += QuoteLen; } StringRef Text = SM.extractText({ Loc, Len }); Token NewTok; NewTok.setToken(tok::string_literal, Text, IsMultiline); Toks.push_back(NewTok); } else { assert(Seg.Kind == Lexer::StringSegment::Expr && "new enumerator was introduced ?"); unsigned Offset = SM.getLocOffsetInBuffer(Seg.Loc, BufID); unsigned EndOffset = Offset + Seg.Length; if (isFirst) { // Add a token for the quote character. StringRef Text = SM.extractText({ Seg.Loc.getAdvancedLoc(-2), 1 }); Token NewTok; NewTok.setToken(tok::string_literal, Text); Toks.push_back(NewTok); } std::vector<Token> NewTokens = swift::tokenize(LangOpts, SM, BufID, Offset, EndOffset, /*KeepComments=*/true); Toks.insert(Toks.end(), NewTokens.begin(), NewTokens.end()); if (isLast) { // Add a token for the quote character. StringRef Text = SM.extractText({ Seg.Loc.getAdvancedLoc(Seg.Length), 1 }); Token NewTok; NewTok.setToken(tok::string_literal, Text); Toks.push_back(NewTok); } } } }
TupleTypeRepr::TupleTypeRepr(ArrayRef<TypeRepr *> Elements, SourceRange Parens, ArrayRef<Identifier> ElementNames, ArrayRef<SourceLoc> ElementNameLocs, ArrayRef<SourceLoc> underscoreLocs, SourceLoc Ellipsis, unsigned EllipsisIdx) : TypeRepr(TypeReprKind::Tuple), NumElements(Elements.size()), Parens(Parens) { TupleTypeReprBits.NameStatus = ElementNames.empty() ? NotNamed : underscoreLocs.empty() ? HasNames : HasLabels; TupleTypeReprBits.HasEllipsis = Ellipsis.isValid(); // Copy elements. std::uninitialized_copy(Elements.begin(), Elements.end(), getTrailingObjects<TypeRepr *>()); // Copy elements names. std::uninitialized_copy(ElementNames.begin(), ElementNames.end(), getTrailingObjects<Identifier>()); // Copy elements names locations. std::uninitialized_copy(ElementNameLocs.begin(), ElementNameLocs.end(), getTrailingObjects<SourceLoc>()); // Copy elements underscore locations. std::uninitialized_copy(underscoreLocs.begin(), underscoreLocs.end(), getTrailingObjects<SourceLoc>() + ElementNameLocs.size()); // Set ellipsis location and index. if (Ellipsis.isValid()) getTrailingObjects<SourceLocAndIdx>()[0] = {Ellipsis, EllipsisIdx}; }
void swift::printDeclDescription(llvm::raw_ostream &out, const Decl *D, ASTContext &Context) { SourceLoc loc = D->getStartLoc(); bool hasPrintedName = false; if (auto *named = dyn_cast<ValueDecl>(D)) { if (named->hasName()) { out << '\'' << named->getFullName() << '\''; hasPrintedName = true; } else if (auto *accessor = dyn_cast<AccessorDecl>(named)) { auto ASD = accessor->getStorage(); if (ASD->hasName()) { switch (accessor->getAccessorKind()) { case AccessorKind::Get: out << "getter"; break; case AccessorKind::Set: out << "setter"; break; case AccessorKind::WillSet: out << "willset"; break; case AccessorKind::DidSet: out << "didset"; break; case AccessorKind::MaterializeForSet: out << "materializeForSet"; break; case AccessorKind::Address: out << "addressor"; break; case AccessorKind::MutableAddress: out << "mutableAddressor"; break; } out << " for " << ASD->getFullName(); hasPrintedName = true; loc = ASD->getStartLoc(); } } } else if (auto *extension = dyn_cast<ExtensionDecl>(D)) { Type extendedTy = extension->getExtendedType(); if (extendedTy) { out << "extension of " << extendedTy; hasPrintedName = true; } } if (!hasPrintedName) out << "declaration " << (const void *)D; if (loc.isValid()) { out << " at "; loc.print(out, Context.SourceMgr); } else { out << " in module '" << D->getModuleContext()->getName() << '\''; } out << '\n'; }
CharSourceRange::CharSourceRange(const SourceManager &SM, SourceLoc Start, SourceLoc End) : Start(Start) { assert(Start.isValid() == End.isValid() && "Start and end should either both be valid or both be invalid!"); if (Start.isValid()) ByteLength = SM.getByteDistance(Start, End); }
static unsigned getLineNumber(DCType *DC) { SourceLoc loc = DC->getLoc(); if (loc.isInvalid()) return 0; const ASTContext &ctx = static_cast<const DeclContext *>(DC)->getASTContext(); return ctx.SourceMgr.getLineAndColumn(loc).first; }
void SerializedDiagnosticConsumer:: emitDiagnosticMessage(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind, StringRef Text, const DiagnosticInfo &Info) { // Emit the diagnostic to bitcode. llvm::BitstreamWriter &Stream = State->Stream; RecordData &Record = State->Record; AbbreviationMap &Abbrevs = State->Abbrevs; StringRef filename = ""; if (Loc.isValid()) filename = SM.getIdentifierForBuffer(SM.findBufferContainingLoc(Loc)); // Emit the RECORD_DIAG record. Record.clear(); Record.push_back(RECORD_DIAG); Record.push_back(getDiagnosticLevel(Kind)); addLocToRecord(Loc, SM, filename, Record); // FIXME: Swift diagnostics currently have no category. Record.push_back(0); // FIXME: Swift diagnostics currently have no flags. Record.push_back(0); // Emit the message. Record.push_back(Text.size()); Stream.EmitRecordWithBlob(Abbrevs.get(RECORD_DIAG), Record, Text); // If the location is invalid, do not emit source ranges or fixits. if (Loc.isInvalid()) return; // Emit source ranges. auto RangeAbbrev = State->Abbrevs.get(RECORD_SOURCE_RANGE); for (const auto &R : Info.Ranges) { if (R.isInvalid()) continue; State->Record.clear(); State->Record.push_back(RECORD_SOURCE_RANGE); addRangeToRecord(R, SM, filename, State->Record); State->Stream.EmitRecordWithAbbrev(RangeAbbrev, State->Record); } // Emit FixIts. auto FixItAbbrev = State->Abbrevs.get(RECORD_FIXIT); for (const auto &F : Info.FixIts) { if (F.getRange().isValid()) { State->Record.clear(); State->Record.push_back(RECORD_FIXIT); addRangeToRecord(F.getRange(), SM, filename, State->Record); State->Record.push_back(F.getText().size()); Stream.EmitRecordWithBlob(FixItAbbrev, Record, F.getText()); } } }
void handlePrimaryAST(ASTUnitRef AstUnit) override { auto &CompInst = AstUnit->getCompilerInstance(); auto &SrcFile = AstUnit->getPrimarySourceFile(); trace::TracedOperation TracedOp; SmallVector<std::pair<unsigned, unsigned>, 8> Ranges; auto Action = [&]() { if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; Invok->raw(SwiftArgs.Args.Args, SwiftArgs.Args.PrimaryFile); trace::initTraceFiles(SwiftArgs, CompInst); TracedOp.start(trace::OperationKind::RelatedIdents, SwiftArgs, {std::make_pair("Offset", std::to_string(Offset))}); } unsigned BufferID = SrcFile.getBufferID().getValue(); SourceLoc Loc = Lexer::getLocForStartOfToken(CompInst.getSourceMgr(), BufferID, Offset); if (Loc.isInvalid()) return; SemaLocResolver Resolver(SrcFile); SemaToken SemaTok = Resolver.resolve(Loc); if (SemaTok.isInvalid()) return; if (SemaTok.IsKeywordArgument) return; ValueDecl *VD = SemaTok.CtorTyRef ? SemaTok.CtorTyRef : SemaTok.ValueD; if (!VD) return; // This was a module reference. // Only accept pointing to an identifier. if (!SemaTok.IsRef && (isa<ConstructorDecl>(VD) || isa<DestructorDecl>(VD) || isa<SubscriptDecl>(VD))) return; if (VD->getName().isOperator()) return; RelatedIdScanner Scanner(SrcFile, BufferID, VD, Ranges); if (DeclContext *LocalDC = VD->getDeclContext()->getLocalContext()) { Scanner.walk(LocalDC); } else { Scanner.walk(SrcFile); } }; Action(); RelatedIdentsInfo Info; Info.Ranges = Ranges; Receiver(Info); }
void handlePrimaryAST(ASTUnitRef AstUnit) override { auto &CompIns = AstUnit->getCompilerInstance(); Module *MainModule = CompIns.getMainModule(); unsigned BufferID = AstUnit->getPrimarySourceFile().getBufferID().getValue(); SourceLoc Loc = Lexer::getLocForStartOfToken(CompIns.getSourceMgr(), BufferID, Offset); if (Loc.isInvalid()) { Receiver({}); return; } trace::TracedOperation TracedOp; if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; ASTInvok->raw(SwiftArgs.Args.Args, SwiftArgs.Args.PrimaryFile); trace::initTraceFiles(SwiftArgs, CompIns); TracedOp.start(trace::OperationKind::CursorInfoForSource, SwiftArgs, {std::make_pair("Offset", std::to_string(Offset))}); } SemaLocResolver Resolver(AstUnit->getPrimarySourceFile()); SemaToken SemaTok = Resolver.resolve(Loc); if (SemaTok.isInvalid()) { Receiver({}); return; } CompilerInvocation CompInvok; ASTInvok->applyTo(CompInvok); if (SemaTok.Mod) { passCursorInfoForModule(SemaTok.Mod, Lang.getIFaceGenContexts(), CompInvok, Receiver); } else { ValueDecl *VD = SemaTok.CtorTyRef ? SemaTok.CtorTyRef : SemaTok.ValueD; bool Failed = passCursorInfoForDecl(VD, MainModule, SemaTok.Ty, SemaTok.IsRef, BufferID, Lang, CompInvok, PreviousASTSnaps, Receiver); if (Failed) { if (!PreviousASTSnaps.empty()) { // Attempt again using the up-to-date AST. resolveCursor(Lang, InputFile, Offset, ASTInvok, /*TryExistingAST=*/false, Receiver); } else { Receiver({}); } } } }
unsigned SourceManager::getByteDistance(SourceLoc Start, SourceLoc End) const { assert(Start.isValid() && "start location should be valid"); assert(End.isValid() && "end location should be valid"); #ifndef NDEBUG unsigned BufferID = findBufferContainingLoc(Start); auto *Buffer = LLVMSourceMgr.getMemoryBuffer(BufferID); assert(End.Value.getPointer() >= Buffer->getBuffer().begin() && End.Value.getPointer() <= Buffer->getBuffer().end() && "End location is not from the same buffer"); #endif // When we have a rope buffer, could be implemented in terms of // getLocOffsetInBuffer(). return End.Value.getPointer() - Start.Value.getPointer(); }
ParserResult<TypeRepr> Parser::parseTypeCollection() { // Parse the leading '['. assert(Tok.is(tok::l_square)); Parser::StructureMarkerRAII parsingCollection(*this, Tok); SourceLoc lsquareLoc = consumeToken(); // Parse the element type. ParserResult<TypeRepr> firstTy = parseType(diag::expected_element_type); // If there is a ':', this is a dictionary type. SourceLoc colonLoc; ParserResult<TypeRepr> secondTy; if (Tok.is(tok::colon)) { colonLoc = consumeToken(); // Parse the second type. secondTy = parseType(diag::expected_dictionary_value_type); } // Parse the closing ']'. SourceLoc rsquareLoc; parseMatchingToken(tok::r_square, rsquareLoc, colonLoc.isValid() ? diag::expected_rbracket_dictionary_type : diag::expected_rbracket_array_type, lsquareLoc); if (firstTy.hasCodeCompletion() || secondTy.hasCodeCompletion()) return makeParserCodeCompletionStatus(); // If we couldn't parse anything for one of the types, propagate the error. if (firstTy.isNull() || (colonLoc.isValid() && secondTy.isNull())) return makeParserError(); // Form the dictionary type. SourceRange brackets(lsquareLoc, rsquareLoc); if (colonLoc.isValid()) return makeParserResult(ParserStatus(firstTy) | ParserStatus(secondTy), new (Context) DictionaryTypeRepr(firstTy.get(), secondTy.get(), colonLoc, brackets)); // Form the array type. return makeParserResult(firstTy, new (Context) ArrayTypeRepr(firstTy.get(), brackets)); }
void ConformanceLookupTable::inheritConformances(ClassDecl *classDecl, ClassDecl *superclassDecl, ExtensionDecl *superclassExt, LazyResolver *resolver) { // Local function to return the location of the superclass. This // takes a little digging, so compute on first use and cache it. SourceLoc superclassLoc; auto getSuperclassLoc = [&] { if (superclassLoc.isValid()) return superclassLoc; for (const auto &inherited : classDecl->getInherited()) { if (auto inheritedType = inherited.getType()) { if (inheritedType->getClassOrBoundGenericClass()) { superclassLoc = inherited.getSourceRange().Start; return superclassLoc; } } } superclassLoc = superclassDecl->getLoc(); return superclassLoc; }; llvm::SmallPtrSet<ProtocolDecl *, 4> protocols; auto addInheritedConformance = [&](ConformanceEntry *entry) { auto protocol = entry->getProtocol(); // Don't add redundant conformances here. This is merely an // optimization; resolveConformances() would zap the duplicates // anyway. if (!protocols.insert(protocol).second) return; // Add the inherited entry. (void)addProtocol(classDecl, protocol, getSuperclassLoc(), ConformanceSource::forInherited(classDecl)); }; // Add inherited conformances. DeclContext *superDC = superclassExt; if (!superclassExt) superDC = superclassDecl; for (auto entry : superclassDecl->ConformanceTable->AllConformances[superDC]){ addInheritedConformance(entry); } }
TupleTypeRepr::TupleTypeRepr(ArrayRef<TupleTypeReprElement> Elements, SourceRange Parens, SourceLoc Ellipsis, unsigned EllipsisIdx) : TypeRepr(TypeReprKind::Tuple), Parens(Parens) { Bits.TupleTypeRepr.HasEllipsis = Ellipsis.isValid(); Bits.TupleTypeRepr.NumElements = Elements.size(); // Copy elements. std::uninitialized_copy(Elements.begin(), Elements.end(), getTrailingObjects<TupleTypeReprElement>()); // Set ellipsis location and index. if (Ellipsis.isValid()) { getTrailingObjects<SourceLocAndIdx>()[0] = {Ellipsis, EllipsisIdx}; } }
SemaToken SemaLocResolver::resolve(SourceLoc Loc) { assert(Loc.isValid()); LocToResolve = Loc; SemaTok = SemaToken(); walk(SrcFile); return SemaTok; }
void swift::lookupVisibleDecls(VisibleDeclConsumer &Consumer, const DeclContext *DC, LazyResolver *TypeResolver, bool IncludeTopLevel, SourceLoc Loc) { if (Loc.isInvalid()) { lookupVisibleDeclsImpl(Consumer, DC, TypeResolver, IncludeTopLevel, Loc); return; } // Filtering out unusable values. class LocalConsumer : public VisibleDeclConsumer { const SourceManager &SM; SourceLoc Loc; VisibleDeclConsumer &Consumer; bool isUsableValue(ValueDecl *VD, DeclVisibilityKind Reason) { // Check "use within its own initial value" case. if (auto *varD = dyn_cast<VarDecl>(VD)) if (auto *PBD = varD->getParentPatternBinding()) if (!PBD->isImplicit() && SM.rangeContainsTokenLoc(PBD->getSourceRange(), Loc)) return false; switch (Reason) { case DeclVisibilityKind::LocalVariable: // Use of 'TypeDecl's before declaration is allowed. if (isa<TypeDecl>(VD)) return true; return SM.isBeforeInBuffer(VD->getLoc(), Loc); case DeclVisibilityKind::VisibleAtTopLevel: // TODO: Implement forward reference rule for script mode? Currently, // it's not needed because the rest of the file hasn't been parsed. // See: https://bugs.swift.org/browse/SR-284 for the rule. return true; default: // Other visibility kind are always usable. return true; } } public: LocalConsumer(const SourceManager &SM, SourceLoc Loc, VisibleDeclConsumer &Consumer) : SM(SM), Loc(Loc), Consumer(Consumer) {} void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason) { if (isUsableValue(VD, Reason)) Consumer.foundDecl(VD, Reason); } } LocalConsumer(DC->getASTContext().SourceMgr, Loc, Consumer); lookupVisibleDeclsImpl(LocalConsumer, DC, TypeResolver, IncludeTopLevel, Loc); }
SILLocation::DebugLoc SILLocation::decode(SourceLoc Loc, const SourceManager &SM) { DebugLoc DL; if (Loc.isValid()) { DL.Filename = SM.getBufferIdentifierForLoc(Loc); std::tie(DL.Line, DL.Column) = SM.getLineAndColumn(Loc); } return DL; }
unsigned SourceManager::getLocOffsetInBuffer(SourceLoc Loc, unsigned BufferID) const { assert(Loc.isValid() && "location should be valid"); auto *Buffer = LLVMSourceMgr.getMemoryBuffer(BufferID); assert(Loc.Value.getPointer() >= Buffer->getBuffer().begin() && Loc.Value.getPointer() <= Buffer->getBuffer().end() && "Location is not from the specified buffer"); return Loc.Value.getPointer() - Buffer->getBuffer().begin(); }
Optional<FileSpecificDiagnosticConsumer::Subconsumer *> FileSpecificDiagnosticConsumer::subconsumerForLocation(SourceManager &SM, SourceLoc loc) { // Diagnostics with invalid locations always go to every consumer. if (loc.isInvalid()) return None; // What if a there's a FileSpecificDiagnosticConsumer but there are no // subconsumers in it? (This situation occurs for the fix-its // FileSpecificDiagnosticConsumer.) In such a case, bail out now. if (Subconsumers.empty()) return None; // This map is generated on first use and cached, to allow the // FileSpecificDiagnosticConsumer to be set up before the source files are // actually loaded. if (ConsumersOrderedByRange.empty()) { // It's possible to get here while a bridging header PCH is being // attached-to, if there's some sort of AST-reader warning or error, which // happens before CompilerInstance::setUpInputs(), at which point _no_ // source buffers are loaded in yet. In that case we return None, rather // than trying to build a nonsensical map (and actually crashing since we // can't find buffers for the inputs). assert(!Subconsumers.empty()); if (!SM.getIDForBufferIdentifier(Subconsumers.begin()->getInputFileName()) .hasValue()) { assert(llvm::none_of(Subconsumers, [&](const Subconsumer &subconsumer) { return SM.getIDForBufferIdentifier(subconsumer.getInputFileName()) .hasValue(); })); return None; } auto *mutableThis = const_cast<FileSpecificDiagnosticConsumer*>(this); mutableThis->computeConsumersOrderedByRange(SM); } // This std::lower_bound call is doing a binary search for the first range // that /might/ contain 'loc'. Specifically, since the ranges are sorted // by end location, it's looking for the first range where the end location // is greater than or equal to 'loc'. const ConsumerAndRange *possiblyContainingRangeIter = std::lower_bound( ConsumersOrderedByRange.begin(), ConsumersOrderedByRange.end(), loc, [](const ConsumerAndRange &entry, SourceLoc loc) -> bool { return entry.endsAfter(loc); }); if (possiblyContainingRangeIter != ConsumersOrderedByRange.end() && possiblyContainingRangeIter->contains(loc)) { auto *consumerAndRangeForLocation = const_cast<ConsumerAndRange *>(possiblyContainingRangeIter); return &(*this)[*consumerAndRangeForLocation]; } return None; }
/// \brief Extract a character immediately before \p Loc. If \p Loc is the /// start of the buffer, return '\f'. static char extractCharBefore(SourceManager &SM, SourceLoc Loc) { // We have to be careful not to go off the front of the buffer. auto bufferID = SM.findBufferContainingLoc(Loc); auto bufferRange = SM.getRangeForBuffer(bufferID); if (bufferRange.getStart() == Loc) return '\f'; auto chars = SM.extractText({Loc.getAdvancedLoc(-1), 1}, bufferID); assert(!chars.empty() && "Couldn't extractText with valid range"); return chars[0]; }
static SourceLoc findEndOfLine(SourceManager &SM, SourceLoc loc, unsigned bufferID) { CharSourceRange entireBuffer = SM.getRangeForBuffer(bufferID); CharSourceRange rangeFromLoc{SM, loc, entireBuffer.getEnd()}; StringRef textFromLoc = SM.extractText(rangeFromLoc); size_t newlineOffset = textFromLoc.find_first_of({"\r\n\0", 3}); if (newlineOffset == StringRef::npos) return entireBuffer.getEnd(); return loc.getAdvancedLoc(newlineOffset); }
bool SemaAnnotator::passSubscriptReference(ValueDecl *D, SourceLoc Loc, bool IsOpenBracket) { CharSourceRange Range = Loc.isValid() ? CharSourceRange(Loc, 1) : CharSourceRange(); bool Continue = SEWalker.visitSubscriptReference(D, Range, IsOpenBracket); if (!Continue) Cancelled = true; return Continue; }
bool EditorAdapter::replaceText(SourceLoc Loc, StringRef Text, StringRef ReplacementText) { auto Range = Lexer::getCharSourceRangeFromSourceRange(SwiftSrcMgr, { Loc, Loc.getAdvancedLoc(Text.size())}); if (cacheReplacement(Range, Text)) { return true; } auto ClangLoc = translateSourceLoc(Loc); return Edits.replaceText(ClangLoc, Text, ReplacementText); }
SourceRange StmtConditionElement::getSourceRange() const { switch (getKind()) { case StmtConditionElement::CK_Boolean: return getBoolean()->getSourceRange(); case StmtConditionElement::CK_Availability: return getAvailability()->getSourceRange(); case StmtConditionElement::CK_PatternBinding: SourceLoc Start; if (IntroducerLoc.isValid()) Start = IntroducerLoc; else Start = getPattern()->getStartLoc(); SourceLoc End = getInitializer()->getEndLoc(); if (Start.isValid() && End.isValid()) { return SourceRange(Start, End); } else { return SourceRange(); } } }
bool SemaAnnotator::passReference(ValueDecl *D, Type Ty, SourceLoc Loc) { unsigned NameLen = D->getName().getLength(); TypeDecl *CtorTyRef = nullptr; if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { if (!CtorRefs.empty() && Loc.isValid()) { Expr *Fn = CtorRefs.back()->getFn(); if (Fn->getLoc() == Loc) { D = extractDecl(Fn); CtorTyRef = TD; } } } CharSourceRange Range = (Loc.isValid()) ? CharSourceRange(Loc, NameLen) : CharSourceRange(); bool Continue = SEWalker.visitDeclReference(D, Range, CtorTyRef, Ty); if (!Continue) Cancelled = true; return Continue; }
bool IndexSwiftASTWalker::startEntityDecl(ValueDecl *D) { if (!shouldIndex(D)) return false; SourceLoc Loc = D->getLoc(); if (Loc.isInvalid() && !IsModuleFile) return false; if (isa<FuncDecl>(D)) { FuncDeclEntityInfo Info; if (initFuncDeclEntityInfo(D, Info)) return false; return startEntity(D, Info); } else { EntityInfo Info; if (initEntityInfo(D, Loc, /*isRef=*/false, Info)) return false; return startEntity(D, Info); } }