// Finds the location of the qualifying `const` token in the `FunctionDecl`'s // return type. Returns `None` when the return type is not `const`-qualified or // `const` does not appear in `Def`'s source like when the type is an alias or a // macro. static llvm::Optional<Token> findConstToRemove(const FunctionDecl *Def, const MatchFinder::MatchResult &Result) { if (!Def->getReturnType().isLocalConstQualified()) return None; // Get the begin location for the function name, including any qualifiers // written in the source (for out-of-line declarations). A FunctionDecl's // "location" is the start of its name, so, when the name is unqualified, we // use `getLocation()`. SourceLocation NameBeginLoc = Def->getQualifier() ? Def->getQualifierLoc().getBeginLoc() : Def->getLocation(); // Since either of the locs can be in a macro, use `makeFileCharRange` to be // sure that we have a consistent `CharSourceRange`, located entirely in the // source file. CharSourceRange FileRange = Lexer::makeFileCharRange( CharSourceRange::getCharRange(Def->getBeginLoc(), NameBeginLoc), *Result.SourceManager, Result.Context->getLangOpts()); if (FileRange.isInvalid()) return None; return utils::lexer::getConstQualifyingToken(FileRange, *Result.Context, *Result.SourceManager); }
static RawComment toRawComment(ASTContext &Context, CharSourceRange Range) { if (Range.isInvalid()) return RawComment(); auto &SourceMgr = Context.SourceMgr; unsigned BufferID = SourceMgr.findBufferContainingLoc(Range.getStart()); unsigned Offset = SourceMgr.getLocOffsetInBuffer(Range.getStart(), BufferID); unsigned EndOffset = SourceMgr.getLocOffsetInBuffer(Range.getEnd(), BufferID); LangOptions FakeLangOpts; Lexer L(FakeLangOpts, SourceMgr, BufferID, nullptr, LexerMode::Swift, HashbangMode::Disallowed, CommentRetentionMode::ReturnAsTokens, TriviaRetentionMode::WithoutTrivia, Offset, EndOffset); SmallVector<SingleRawComment, 16> Comments; Token Tok; while (true) { L.lex(Tok); if (Tok.is(tok::eof)) break; assert(Tok.is(tok::comment)); addCommentToList(Comments, SingleRawComment(Tok.getRange(), SourceMgr)); } RawComment Result; Result.Comments = Context.AllocateCopy(Comments); return Result; }
bool SourceManager::openVirtualFile(SourceLoc loc, StringRef name, int lineOffset) { CharSourceRange fullRange = getRangeForBuffer(findBufferContainingLoc(loc)); SourceLoc end; auto nextRangeIter = VirtualFiles.upper_bound(loc.Value.getPointer()); if (nextRangeIter != VirtualFiles.end() && fullRange.contains(nextRangeIter->second.Range.getStart())) { const VirtualFile &existingFile = nextRangeIter->second; if (existingFile.Range.getStart() == loc) { assert(existingFile.Name == name); assert(existingFile.LineOffset == lineOffset); return false; } assert(!existingFile.Range.contains(loc) && "must close current open file first"); end = nextRangeIter->second.Range.getStart(); } else { end = fullRange.getEnd(); } CharSourceRange range = CharSourceRange(*this, loc, end); VirtualFiles[end.Value.getPointer()] = { range, name, lineOffset }; CachedVFile = {nullptr, nullptr}; return true; }
// Re-lex the tokens to get precise locations to insert 'override' and remove // 'virtual'. static SmallVector<Token, 16> ParseTokens(CharSourceRange Range, const MatchFinder::MatchResult &Result) { const SourceManager &Sources = *Result.SourceManager; std::pair<FileID, unsigned> LocInfo = Sources.getDecomposedLoc(Range.getBegin()); StringRef File = Sources.getBufferData(LocInfo.first); const char *TokenBegin = File.data() + LocInfo.second; Lexer RawLexer(Sources.getLocForStartOfFile(LocInfo.first), Result.Context->getLangOpts(), File.begin(), TokenBegin, File.end()); SmallVector<Token, 16> Tokens; Token Tok; while (!RawLexer.LexFromRawLexer(Tok)) { if (Tok.is(tok::semi) || Tok.is(tok::l_brace)) break; if (Sources.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation())) break; if (Tok.is(tok::raw_identifier)) { IdentifierInfo &Info = Result.Context->Idents.get(StringRef( Sources.getCharacterData(Tok.getLocation()), Tok.getLength())); Tok.setIdentifierInfo(&Info); Tok.setKind(Info.getTokenID()); } Tokens.push_back(Tok); } return Tokens; }
bool Commit::replaceWithInner(CharSourceRange range, CharSourceRange replacementRange) { FileOffset OuterBegin; unsigned OuterLen; if (!canRemoveRange(range, OuterBegin, OuterLen)) { IsCommitable = false; return false; } FileOffset InnerBegin; unsigned InnerLen; if (!canRemoveRange(replacementRange, InnerBegin, InnerLen)) { IsCommitable = false; return false; } FileOffset OuterEnd = OuterBegin.getWithOffset(OuterLen); FileOffset InnerEnd = InnerBegin.getWithOffset(InnerLen); if (OuterBegin.getFID() != InnerBegin.getFID() || InnerBegin < OuterBegin || InnerBegin > OuterEnd || InnerEnd > OuterEnd) { IsCommitable = false; return false; } addRemove(range.getBegin(), OuterBegin, InnerBegin.getOffset() - OuterBegin.getOffset()); addRemove(replacementRange.getEnd(), InnerEnd, OuterEnd.getOffset() - InnerEnd.getOffset()); return true; }
static std::pair<unsigned, unsigned> makeStandaloneRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts) { CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts); unsigned Offset = SM.getFileOffset(FileRange.getBegin()); unsigned EndOffset = SM.getFileOffset(FileRange.getEnd()); return std::make_pair(Offset, EndOffset); }
void SerializedDiagnosticConsumer::addRangeToRecord(CharSourceRange Range, SourceManager &SM, StringRef Filename, RecordDataImpl &Record) { assert(Range.isValid()); addLocToRecord(Range.getStart(), SM, Filename, Record); addLocToRecord(Range.getEnd(), SM, Filename, Record); }
static void EmitRange(raw_ostream& o, const SourceManager &SM, const LangOptions &LangOpts, CharSourceRange R, const FIDMap &FM, unsigned indent) { Indent(o, indent) << "<array>\n"; EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1); EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, R.isTokenRange()); Indent(o, indent) << "</array>\n"; }
SingleRawComment::SingleRawComment(CharSourceRange Range, const SourceManager &SourceMgr) : Range(Range), RawText(SourceMgr.extractText(Range)), Kind(static_cast<unsigned>(getCommentKind(RawText))) { auto StartLineAndColumn = SourceMgr.getLineAndColumn(Range.getStart()); StartLine = StartLineAndColumn.first; StartColumn = StartLineAndColumn.second; EndLine = SourceMgr.getLineNumber(Range.getEnd()); }
void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) { const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move"); const auto *ReceivingExpr = Result.Nodes.getNodeAs<Expr>("receiving-expr"); const Expr *Arg = CallMove->getArg(0); SourceManager &SM = Result.Context->getSourceManager(); CharSourceRange MoveRange = CharSourceRange::getCharRange(CallMove->getSourceRange()); CharSourceRange FileMoveRange = Lexer::makeFileCharRange(MoveRange, SM, getLangOpts()); if (!FileMoveRange.isValid()) return; bool IsConstArg = Arg->getType().isConstQualified(); bool IsTriviallyCopyable = Arg->getType().isTriviallyCopyableType(*Result.Context); if (IsConstArg || IsTriviallyCopyable) { if (const CXXRecordDecl *R = Arg->getType()->getAsCXXRecordDecl()) { // According to [expr.prim.lambda]p3, "whether the closure type is // trivially copyable" property can be changed by the implementation of // the language, so we shouldn't rely on it when issuing diagnostics. if (R->isLambda()) return; // Don't warn when the type is not copyable. for (const auto *Ctor : R->ctors()) { if (Ctor->isCopyConstructor() && Ctor->isDeleted()) return; } } if (!IsConstArg && IsTriviallyCopyable && !CheckTriviallyCopyableMove) return; bool IsVariable = isa<DeclRefExpr>(Arg); const auto *Var = IsVariable ? dyn_cast<DeclRefExpr>(Arg)->getDecl() : nullptr; auto Diag = diag(FileMoveRange.getBegin(), "std::move of the %select{|const }0" "%select{expression|variable %4}1 " "%select{|of the trivially-copyable type %5 }2" "has no effect; remove std::move()" "%select{| or make the variable non-const}3") << IsConstArg << IsVariable << IsTriviallyCopyable << (IsConstArg && IsVariable && !IsTriviallyCopyable) << Var << Arg->getType(); ReplaceCallWithArg(CallMove, Diag, SM, getLangOpts()); } else if (ReceivingExpr) { auto Diag = diag(FileMoveRange.getBegin(), "passing result of std::move() as a const reference " "argument; no move will actually happen"); ReplaceCallWithArg(CallMove, Diag, SM, getLangOpts()); } }
void RedundantVoidArgCheck::removeVoidArgumentTokens( const ast_matchers::MatchFinder::MatchResult &Result, SourceRange Range, StringRef GrammarLocation) { CharSourceRange CharRange = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Range), *Result.SourceManager, getLangOpts()); std::string DeclText = Lexer::getSourceText(CharRange, *Result.SourceManager, getLangOpts()) .str(); Lexer PrototypeLexer(CharRange.getBegin(), getLangOpts(), DeclText.data(), DeclText.data(), DeclText.data() + DeclText.size()); enum TokenState { NothingYet, SawLeftParen, SawVoid, }; TokenState State = NothingYet; Token VoidToken; Token ProtoToken; std::string Diagnostic = ("redundant void argument list in " + GrammarLocation).str(); while (!PrototypeLexer.LexFromRawLexer(ProtoToken)) { switch (State) { case NothingYet: if (ProtoToken.is(tok::TokenKind::l_paren)) { State = SawLeftParen; } break; case SawLeftParen: if (ProtoToken.is(tok::TokenKind::raw_identifier) && ProtoToken.getRawIdentifier() == "void") { State = SawVoid; VoidToken = ProtoToken; } else if (ProtoToken.is(tok::TokenKind::l_paren)) { State = SawLeftParen; } else { State = NothingYet; } break; case SawVoid: State = NothingYet; if (ProtoToken.is(tok::TokenKind::r_paren)) { removeVoidToken(VoidToken, Diagnostic); } else if (ProtoToken.is(tok::TokenKind::l_paren)) { State = SawLeftParen; } break; } } if (State == SawVoid && ProtoToken.is(tok::TokenKind::r_paren)) { removeVoidToken(VoidToken, Diagnostic); } }
StringRef SourceManager::extractText(CharSourceRange Range, Optional<unsigned> BufferID) const { assert(Range.isValid() && "range should be valid"); if (!BufferID) BufferID = findBufferContainingLoc(Range.getStart()); StringRef Buffer = LLVMSourceMgr.getMemoryBuffer(*BufferID)->getBuffer(); return Buffer.substr(getLocOffsetInBuffer(Range.getStart(), *BufferID), Range.getByteLength()); }
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 FileInstrumentation::redirectInclude(FileID includedFileID, llvm::StringRef newFilePath) { CharSourceRange includeDirectiveRange = utils::getIncludeDirectiveSourceRange(includedFileID, m_sourceFile.getSourceManager(), m_astContext.getLangOpts()); if(includeDirectiveRange.isValid()) { m_rewriter.replace(includeDirectiveRange.getAsRange()) << "\"" << newFilePath << "\""; return true; } return false; }
// FIXME: This should go into the Lexer, but we need to figure out how // to handle ranges for refactoring in general first - there is no obvious // good way how to integrate this into the Lexer yet. static int getRangeSize(SourceManager &Sources, const CharSourceRange &Range) { SourceLocation SpellingBegin = Sources.getSpellingLoc(Range.getBegin()); SourceLocation SpellingEnd = Sources.getSpellingLoc(Range.getEnd()); std::pair<FileID, unsigned> Start = Sources.getDecomposedLoc(SpellingBegin); std::pair<FileID, unsigned> End = Sources.getDecomposedLoc(SpellingEnd); if (Start.first != End.first) return -1; if (Range.isTokenRange()) End.second += Lexer::MeasureTokenLength(SpellingEnd, Sources, LangOptions()); return End.second - Start.second; }
bool AffectedRangeManager::affectsCharSourceRange( const CharSourceRange &Range) { for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) && !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin())) return true; } return false; }
void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range, RecordDataImpl &Record, const SourceManager &SM) { AddLocToRecord(Range.getBegin(), Record, &SM); unsigned TokSize = 0; if (Range.isTokenRange()) TokSize = Lexer::MeasureTokenLength(Range.getEnd(), SM, *LangOpts); AddLocToRecord(Range.getEnd(), Record, &SM, TokSize); }
bool Commit::insertWrap(StringRef before, CharSourceRange range, StringRef after) { bool commitableBefore = insert(range.getBegin(), before, /*afterToken=*/false, /*beforePreviousInsertions=*/true); bool commitableAfter; if (range.isTokenRange()) commitableAfter = insertAfterToken(range.getEnd(), after); else commitableAfter = insert(range.getEnd(), after); return commitableBefore && commitableAfter; }
/// Check if all the locations in the range have the same macro argument /// expansion, and that that expansion starts with ArgumentLoc. static bool checkRangeForMacroArgExpansion(CharSourceRange Range, const SourceManager &SM, SourceLocation ArgumentLoc) { SourceLocation BegLoc = Range.getBegin(), EndLoc = Range.getEnd(); while (BegLoc != EndLoc) { if (!checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc)) return false; BegLoc.getLocWithOffset(1); } return checkLocForMacroArgExpansion(BegLoc, SM, ArgumentLoc); }
void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) { SourceManager &SM = *Result.SourceManager; if (const auto *E = Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId)) { CharSourceRange Range = Lexer::makeFileCharRange( CharSourceRange::getTokenRange(E->getSourceRange()), SM, LangOptions()); if (Range.isInvalid()) return; auto Diag = diag(Range.getBegin(), "use std::move to transfer ownership") << FixItHint::CreateInsertion(Range.getBegin(), "std::move(") << FixItHint::CreateInsertion(Range.getEnd(), ")"); if (auto Fix = Inserter->CreateIncludeInsertion(SM.getMainFileID(), "utility", /*IsAngled=*/true)) Diag << *Fix; return; } SourceLocation AutoPtrLoc; if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) { // std::auto_ptr<int> i; // ^ if (auto Loc = TL->getAs<TemplateSpecializationTypeLoc>()) AutoPtrLoc = Loc.getTemplateNameLoc(); } else if (const auto *D = Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId)) { // using std::auto_ptr; // ^ AutoPtrLoc = D->getNameInfo().getBeginLoc(); } else { llvm_unreachable("Bad Callback. No node provided."); } if (AutoPtrLoc.isMacroID()) AutoPtrLoc = SM.getSpellingLoc(AutoPtrLoc); // Ensure that only the 'auto_ptr' token is replaced and not the template // aliases. if (StringRef(SM.getCharacterData(AutoPtrLoc), strlen("auto_ptr")) != "auto_ptr") return; SourceLocation EndLoc = AutoPtrLoc.getLocWithOffset(strlen("auto_ptr") - 1); diag(AutoPtrLoc, "auto_ptr is deprecated, use unique_ptr instead") << FixItHint::CreateReplacement(SourceRange(AutoPtrLoc, EndLoc), "unique_ptr"); }
/// Find the suitable set of lines to show to include a set of ranges. static llvm::Optional<std::pair<unsigned, unsigned>> findLinesForRange(const CharSourceRange &R, FileID FID, const SourceManager &SM) { if (!R.isValid()) return None; SourceLocation Begin = R.getBegin(); SourceLocation End = R.getEnd(); if (SM.getFileID(Begin) != FID || SM.getFileID(End) != FID) return None; return std::make_pair(SM.getExpansionLineNumber(Begin), SM.getExpansionLineNumber(End)); }
void PreprocessingRecord::InclusionDirective( SourceLocation HashLoc, const clang::Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, const Module *Imported) { InclusionDirective::InclusionKind Kind = InclusionDirective::Include; switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { case tok::pp_include: Kind = InclusionDirective::Include; break; case tok::pp_import: Kind = InclusionDirective::Import; break; case tok::pp_using: Kind = InclusionDirective::Using; break; case tok::pp_include_next: Kind = InclusionDirective::IncludeNext; break; case tok::pp___include_macros: Kind = InclusionDirective::IncludeMacros; break; default: llvm_unreachable("Unknown include directive kind"); } SourceLocation EndLoc; if (!IsAngled) { EndLoc = FilenameRange.getBegin(); } else { EndLoc = FilenameRange.getEnd(); if (FilenameRange.isCharRange()) EndLoc = EndLoc.getLocWithOffset(-1); // the InclusionDirective expects // a token range. } clang::InclusionDirective *ID = new (*this) clang::InclusionDirective(*this, Kind, FileName, !IsAngled, File, SourceRange(HashLoc, EndLoc)); addPreprocessedEntity(ID); }
void Parser::diagnoseWhereClauseInGenericParamList(const GenericParamList * GenericParams) { if (GenericParams == nullptr || GenericParams->getWhereLoc().isInvalid()) return; auto WhereRangeInsideBrackets = GenericParams->getWhereClauseSourceRange(); // Move everything immediately following the last generic parameter // as written all the way to the right angle bracket (">") auto LastGenericParam = GenericParams->getParams().back(); auto EndOfLastGenericParam = Lexer::getLocForEndOfToken(SourceMgr, LastGenericParam->getEndLoc()); CharSourceRange RemoveWhereRange { SourceMgr, EndOfLastGenericParam, GenericParams->getRAngleLoc() }; auto WhereCharRange = Lexer::getCharSourceRangeFromSourceRange(SourceMgr, GenericParams->getWhereClauseSourceRange()); SmallString<64> Buffer; llvm::raw_svector_ostream WhereClauseText(Buffer); WhereClauseText << SourceMgr.extractText(Tok.is(tok::kw_where) ? WhereCharRange : RemoveWhereRange); // If, for some reason, there was a where clause in both locations, we're // adding to the list of requirements, so tack on a comma here before // inserting it at the head of the later where clause. if (Tok.is(tok::kw_where)) WhereClauseText << ','; auto Diag = diagnose(WhereRangeInsideBrackets.Start, diag::where_inside_brackets); Diag.fixItRemoveChars(RemoveWhereRange.getStart(), RemoveWhereRange.getEnd()); if (Tok.is(tok::kw_where)) { Diag.fixItReplace(Tok.getLoc(), WhereClauseText.str()); } else { Diag.fixItInsert(Lexer::getLocForEndOfToken(SourceMgr, PreviousLoc), WhereClauseText.str()); } }
bool Commit::canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len) { const SourceManager &SM = SourceMgr; range = Lexer::makeFileCharRange(range, SM, LangOpts); if (range.isInvalid()) return false; if (range.getBegin().isMacroID() || range.getEnd().isMacroID()) return false; if (SM.isInSystemHeader(range.getBegin()) || SM.isInSystemHeader(range.getEnd())) return false; if (PPRec && PPRec->rangeIntersectsConditionalDirective(range.getAsRange())) return false; std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(range.getBegin()); std::pair<FileID, unsigned> endInfo = SM.getDecomposedLoc(range.getEnd()); if (beginInfo.first != endInfo.first || beginInfo.second > endInfo.second) return false; Offs = FileOffset(beginInfo.first, beginInfo.second); Len = endInfo.second - beginInfo.second; return true; }
bool EditorAdapter::cacheReplacement(CharSourceRange Range, StringRef Text) const { if (!CacheEnabled) return false; unsigned SwiftBufferID, Offset; std::tie(SwiftBufferID, Offset) = getLocInfo(Range.getStart()); Replacement R { Offset, Range.getByteLength(), Text }; if (Replacements.count(R)) { return true; } else { Replacements.insert(R); } return false; }
bool Commit::replace(CharSourceRange range, StringRef text) { if (text.empty()) return remove(range); FileOffset Offs; unsigned Len; if (!canInsert(range.getBegin(), Offs) || !canRemoveRange(range, Offs, Len)) { IsCommitable = false; return false; } addRemove(range.getBegin(), Offs, Len); addInsert(range.getBegin(), Offs, text, false); return true; }
static void printUntilFirstDeclStarts(SourceFile &File, ASTPrinter &Printer) { if (!File.getBufferID().hasValue()) return; auto BufferID = *File.getBufferID(); auto &SM = File.getASTContext().SourceMgr; CharSourceRange TextRange = SM.getRangeForBuffer(BufferID); auto DeclStartLoc = getDeclStartPosition(File); if (DeclStartLoc.isValid()) { TextRange = CharSourceRange(SM, TextRange.getStart(), DeclStartLoc); } Printer << SM.extractText(TextRange, BufferID); }
bool Commit::insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken, bool beforePreviousInsertions) { FileOffset RangeOffs; unsigned RangeLen; if (!canRemoveRange(range, RangeOffs, RangeLen)) { IsCommitable = false; return false; } FileOffset Offs; if ((!afterToken && !canInsert(loc, Offs)) || ( afterToken && !canInsertAfterToken(loc, Offs, loc))) { IsCommitable = false; return false; } if (PPRec && PPRec->areInDifferentConditionalDirectiveRegion(loc, range.getBegin())) { IsCommitable = false; return false; } addInsertFromRange(loc, Offs, RangeOffs, RangeLen, beforePreviousInsertions); return true; }
void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) { SourceManager &SM = *Result.SourceManager; if (const auto *E = Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId)) { CharSourceRange Range = Lexer::makeFileCharRange( CharSourceRange::getTokenRange(E->getSourceRange()), SM, LangOptions()); if (Range.isInvalid()) return; auto Diag = diag(Range.getBegin(), "use std::move to transfer ownership") << FixItHint::CreateInsertion(Range.getBegin(), "std::move(") << FixItHint::CreateInsertion(Range.getEnd(), ")"); auto Insertion = Inserter->CreateIncludeInsertion(SM.getMainFileID(), "utility", /*IsAngled=*/true); if (Insertion.hasValue()) Diag << Insertion.getValue(); return; } SourceLocation IdentifierLoc; if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) { IdentifierLoc = locateFromTypeLoc(TL, SM); } else if (const auto *D = Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId)) { IdentifierLoc = locateFromUsingDecl(D, SM); } else { llvm_unreachable("Bad Callback. No node provided."); } if (IdentifierLoc.isMacroID()) IdentifierLoc = SM.getSpellingLoc(IdentifierLoc); // Ensure that only the 'auto_ptr' token is replaced and not the template // aliases. if (!checkTokenIsAutoPtr(IdentifierLoc, SM, LangOptions())) return; SourceLocation EndLoc = IdentifierLoc.getLocWithOffset(strlen("auto_ptr") - 1); diag(IdentifierLoc, "auto_ptr is deprecated, use unique_ptr instead") << FixItHint::CreateReplacement(SourceRange(IdentifierLoc, EndLoc), "unique_ptr"); }
bool SemaLocResolver::visitModuleReference(ModuleEntity Mod, CharSourceRange Range) { if (isDone()) return false; if (Mod.isBuiltinModule()) return true; // Ignore. return !tryResolve(Mod, Range.getStart()); }