std::string rangeToString(SourceManager& sourceManager, const SourceLocation& start, const SourceLocation& end) { bool invalid; const char* b = sourceManager.getCharacterData(start, &invalid); if (invalid || !b) return "<invalid>"; const char* e = sourceManager.getCharacterData(end, &invalid); if (invalid || !e) return "<invalid>"; if (e < b + 30) return std::string(b, e); else return std::string(b, b+30) + "[...]"; }
std::string toString(SourceManager& sourceManager, const Decl* decl) { if (!decl) return "<invalid>"; SourceLocation start = sourceManager.getExpansionLoc(decl->getLocStart()); bool invalid; const char* b = sourceManager.getCharacterData(start, &invalid); if (invalid || !b) return "<invalid>"; SourceLocation end = sourceManager.getExpansionLoc(decl->getLocEnd()); const char* e = sourceManager.getCharacterData(end, &invalid); if (invalid || !e) return "<invalid>"; return std::string(b, std::min(b+30, e)); }
/// getSpelling() - Return the 'spelling' of this token. The spelling of a /// token are the characters used to represent the token in the source file /// after trigraph expansion and escaped-newline folding. In particular, this /// wants to get the true, uncanonicalized, spelling of things like digraphs /// UCNs, etc. std::string Preprocessor::getSpelling(const Token &Tok, const SourceManager &SourceMgr, const LangOptions &Features, bool *Invalid) { assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); // If this token contains nothing interesting, return it directly. bool CharDataInvalid = false; const char* TokStart = SourceMgr.getCharacterData(Tok.getLocation(), &CharDataInvalid); if (Invalid) *Invalid = CharDataInvalid; if (CharDataInvalid) return std::string(); if (!Tok.needsCleaning()) return std::string(TokStart, TokStart+Tok.getLength()); std::string Result; Result.reserve(Tok.getLength()); // Otherwise, hard case, relex the characters into the string. for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength(); Ptr != End; ) { unsigned CharSize; Result.push_back(Lexer::getCharAndSizeNoWarn(Ptr, CharSize, Features)); Ptr += CharSize; } assert(Result.size() != unsigned(Tok.getLength()) && "NeedsCleaning flag set on something that didn't need cleaning!"); return Result; }
static std::string getText(const SourceManager &SourceManager, const T &Node) { SourceLocation StartSpellingLocatino = SourceManager.getSpellingLoc(Node.getLocStart()); SourceLocation EndSpellingLocation = SourceManager.getSpellingLoc(Node.getLocEnd()); if (!StartSpellingLocatino.isValid() || !EndSpellingLocation.isValid()) { return std::string(); } bool Invalid = true; const char *Text = SourceManager.getCharacterData(StartSpellingLocatino, &Invalid); if (Invalid) { return std::string(); } std::pair<FileID, unsigned> Start = SourceManager.getDecomposedLoc(StartSpellingLocatino); std::pair<FileID, unsigned> End = SourceManager.getDecomposedLoc(Lexer::getLocForEndOfToken( EndSpellingLocation, 0, SourceManager, LangOptions())); if (Start.first != End.first) { // Start and end are in different files. return std::string(); } if (End.second < Start.second) { // Shuffling text with macros may cause this. return std::string(); } return std::string(Text, End.second - Start.second); }
static void PrintSourceForLocation(const SourceLocation &Loc, SourceManager &SM) { const char *LocData = SM.getCharacterData(Loc, /*Invalid=*/nullptr); unsigned LocColumn = SM.getSpellingColumnNumber(Loc, /*Invalid=*/nullptr) - 1; FileID FID = SM.getFileID(Loc); llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, Loc, /*Invalid=*/nullptr); assert(LocData >= Buffer->getBufferStart() && LocData < Buffer->getBufferEnd()); const char *LineBegin = LocData - LocColumn; assert(LineBegin >= Buffer->getBufferStart()); const char *LineEnd = nullptr; for (LineEnd = LineBegin; *LineEnd != '\n' && *LineEnd != '\r' && LineEnd < Buffer->getBufferEnd(); ++LineEnd) ; llvm::StringRef LineString(LineBegin, LineEnd - LineBegin); llvm::errs() << LineString << '\n'; std::string Space(LocColumn, ' '); llvm::errs() << Space.c_str() << '\n'; }
int runFD(const FunctionDecl *md, SourceManager &sm) { if (!md->hasBody()) return 0; if (!md->isThisDeclarationADefinition()) return 0; DeclarationNameInfo info = md->getNameInfo(); FullSourceLoc b(md->getLocStart(), sm), _e(md->getLocEnd(), sm); FullSourceLoc e(clang::Lexer::getLocForEndOfToken(_e, 0, sm, *this->lopt), sm); SourceRange nameRange = SourceRange(info.getLoc()); FullSourceLoc d(nameRange.getBegin(), sm), _f(nameRange.getEnd(), sm); FullSourceLoc f(clang::Lexer::getLocForEndOfToken(_f, 0, sm, *this->lopt), sm); string start(sm.getCharacterData(b), sm.getCharacterData(d)-sm.getCharacterData(b)); string name(sm.getCharacterData(d), sm.getCharacterData(f)-sm.getCharacterData(d)); string end(sm.getCharacterData(f), sm.getCharacterData(e)-sm.getCharacterData(f)); if (this->methods.find(name) != this->methods.end()) { message("Redefinition of method " + name); return 1; } METHOD* m = new METHOD(); m->pre = start; m->name = name; m->post = end; getAbsoluteLocation(FullSourceLoc(md->getLocStart(), sm), FullSourceLoc(md->getLocEnd(), sm), &m->location.begin, &m->location.end, *this->lopt); m->sm = &sm; m->range = CharSourceRange:: getTokenRange(SourceRange(info.getLoc())); this->methods[name] = m; // For debugging purposes // cout << start << "|" << name << "|" << end << endl; return 0; }
static bool LineIsMarkedWithNOLINT(SourceManager &SM, SourceLocation Loc) { bool Invalid; const char *CharacterData = SM.getCharacterData(Loc, &Invalid); if (!Invalid) { const char *P = CharacterData; while (*P != '\0' && *P != '\r' && *P != '\n') ++P; StringRef RestOfLine(CharacterData, P - CharacterData + 1); // FIXME: Handle /\bNOLINT\b(\([^)]*\))?/ as cpplint.py does. if (RestOfLine.find("NOLINT") != StringRef::npos) { return true; } } return false; }
// Checks if 'typedef' keyword can be removed - we do it only if // it is the only declaration in a declaration chain. static bool CheckRemoval(SourceManager &SM, const SourceLocation &LocStart, const SourceLocation &LocEnd, ASTContext &Context, SourceRange &ResultRange) { FileID FID = SM.getFileID(LocEnd); llvm::MemoryBuffer *Buffer = SM.getBuffer(FID, LocEnd); Lexer DeclLexer(SM.getLocForStartOfFile(FID), Context.getLangOpts(), Buffer->getBufferStart(), SM.getCharacterData(LocStart), Buffer->getBufferEnd()); Token DeclToken; bool result = false; int parenthesisLevel = 0; while (!DeclLexer.LexFromRawLexer(DeclToken)) { if (DeclToken.getKind() == tok::TokenKind::l_paren) parenthesisLevel++; if (DeclToken.getKind() == tok::TokenKind::r_paren) parenthesisLevel--; if (DeclToken.getKind() == tok::TokenKind::semi) break; // if there is comma and we are not between open parenthesis then it is // two or more declatarions in this chain if (parenthesisLevel == 0 && DeclToken.getKind() == tok::TokenKind::comma) return false; if (DeclToken.isOneOf(tok::TokenKind::identifier, tok::TokenKind::raw_identifier)) { auto TokenStr = DeclToken.getRawIdentifier().str(); if (TokenStr == "typedef") { ResultRange = SourceRange(DeclToken.getLocation(), DeclToken.getEndLoc()); result = true; } } } // assert if there was keyword 'typedef' in declaration assert(result && "No typedef found"); return result; }
// Looks for the token matching the predicate and returns the range of the found // token including trailing whitespace. static SourceRange FindToken(const SourceManager &Sources, LangOptions LangOpts, SourceLocation StartLoc, SourceLocation EndLoc, bool (*Pred)(const Token &)) { if (StartLoc.isMacroID() || EndLoc.isMacroID()) return SourceRange(); FileID File = Sources.getFileID(Sources.getSpellingLoc(StartLoc)); StringRef Buf = Sources.getBufferData(File); const char *StartChar = Sources.getCharacterData(StartLoc); Lexer Lex(StartLoc, LangOpts, StartChar, StartChar, Buf.end()); Lex.SetCommentRetentionState(true); Token Tok; do { Lex.LexFromRawLexer(Tok); if (Pred(Tok)) { Token NextTok; Lex.LexFromRawLexer(NextTok); return SourceRange(Tok.getLocation(), NextTok.getLocation()); } } while (Tok.isNot(tok::eof) && Tok.getLocation() < EndLoc); return SourceRange(); }
static StringRef GetText(const Token &Tok, const SourceManager &Sources) { return StringRef(Sources.getCharacterData(Tok.getLocation()), Tok.getLength()); }