Go to the documentation of this file.
22 #include "llvm/Support/Errc.h"
23 #include "llvm/Support/Error.h"
26 using namespace clang;
29 using llvm::StringError;
48 if (Err || !Tok.
is(Next))
55 if (
Range.isInvalid())
56 return llvm::make_error<StringError>(errc::invalid_argument,
59 if (
Range.getBegin().isMacroID() ||
Range.getEnd().isMacroID())
60 return llvm::make_error<StringError>(
61 errc::invalid_argument,
"Range starts or ends in a macro expansion");
63 if (
SM.isInSystemHeader(
Range.getBegin()) ||
64 SM.isInSystemHeader(
Range.getEnd()))
65 return llvm::make_error<StringError>(errc::invalid_argument,
66 "Range is in system header");
68 std::pair<FileID, unsigned> BeginInfo =
SM.getDecomposedLoc(
Range.getBegin());
69 std::pair<FileID, unsigned> EndInfo =
SM.getDecomposedLoc(
Range.getEnd());
70 if (BeginInfo.first != EndInfo.first)
71 return llvm::make_error<StringError>(
72 errc::invalid_argument,
"Range begins and ends in different files");
74 if (BeginInfo.second > EndInfo.second)
75 return llvm::make_error<StringError>(
76 errc::invalid_argument,
"Range's begin is past its end");
78 return llvm::Error::success();
108 static bool contains(
const std::set<tok::TokenKind> &Terminators,
110 return Terminators.count(Tok.
getKind()) > 0;
123 const std::set<tok::TokenKind> &Terminators,
125 assert(EntityLast.
isValid() &&
"Invalid end location found.");
135 std::unique_ptr<Lexer>
Lexer = [&]() {
136 bool Invalid =
false;
137 auto FileOffset =
SM.getDecomposedLoc(ExpansionRange.
getEnd());
138 llvm::StringRef
File =
SM.getBufferData(FileOffset.first, &Invalid);
139 assert(!Invalid &&
"Cannot get file/offset");
140 return std::make_unique<clang::Lexer>(
141 SM.getLocForStartOfFile(FileOffset.first), LangOpts,
File.begin(),
142 File.data() + FileOffset.second,
File.end());
155 bool Terminated =
false;
177 bool TerminatedByMacro =
false;
179 if (Terminators.empty() ||
contains(Terminators, Tok))
183 TerminatedByMacro =
true;
189 while (!Terminated) {
230 if (TerminatedByMacro &&
contains(Terminators, Tok)) {
233 TerminatedByMacro =
false;
252 if (llvm::isa<RecordDecl>(D) || llvm::isa<UsingDecl>(D))
255 if (llvm::isa<FunctionDecl>(D) || llvm::isa<LinkageSpecDecl>(D))
256 return {tok::r_brace, tok::semi};
258 if (llvm::isa<VarDecl>(D) || llvm::isa<FieldDecl>(D))
259 return {tok::comma, tok::semi};
270 const char *LocChars =
SM.getCharacterData(Loc);
289 bool Invalid =
false;
290 const char *LocChars =
293 "Loc must be a valid character and not the first of the source file.");
326 if (
const auto *Record = llvm::dyn_cast<CXXRecordDecl>(&
Decl)) {
327 if (
const auto *T = Record->getDescribedClassTemplate())
328 if (
SM.isBeforeInTranslationUnit(T->getBeginLoc(),
Range.getBegin()))
329 Range.setBegin(T->getBeginLoc());
330 }
else if (
const auto *F = llvm::dyn_cast<FunctionDecl>(&
Decl)) {
331 if (
const auto *T = F->getDescribedFunctionTemplate())
332 if (
SM.isBeforeInTranslationUnit(T->getBeginLoc(),
Range.getBegin()))
333 Range.setBegin(T->getBeginLoc());
340 Range.setTokenRange(
false);
353 if (
SM.isBeforeInTranslationUnit(Comment->getBeginLoc(),
359 const StringRef CommentText = Comment->getRawText(
SM);
360 if (!CommentText.contains(
"LINT.IfChange") &&
361 !CommentText.contains(
"LINT.ThenChange"))
362 Range.setBegin(Comment->getBeginLoc());
375 SM.getBufferData(
SM.getFileID(
Range.getBegin()), &Invalid);
378 llvm::StringRef BeforeAttr =
379 Source.substr(0,
SM.getFileOffset(
Range.getBegin()));
380 llvm::StringRef BeforeAttrStripped = BeforeAttr.rtrim();
382 for (llvm::StringRef Prefix : {
"[[",
"__attribute__(("}) {
384 if (BeforeAttrStripped.endswith(Prefix)) {
388 Range.setBegin(
Range.getBegin().getLocWithOffset(
static_cast<int>(
389 -BeforeAttr.size() + BeforeAttrStripped.size() - Prefix.size())));
static CharSourceRange makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Accepts a range and returns a character range with file locations.
ASTContext & getASTContext() const LLVM_READONLY
SourceLocation getEndLoc() const LLVM_READONLY
static SourceLocation getEntityEndLoc(const SourceManager &SM, SourceLocation EntityLast, const std::set< tok::TokenKind > &Terminators, const LangOptions &LangOpts)
static std::set< tok::TokenKind > getTerminators(const Decl &D)
static bool getRawToken(SourceLocation Loc, Token &Result, const SourceManager &SM, const LangOptions &LangOpts, bool IgnoreWhiteSpace=false)
Relex the token at the specified location.
RawComment * getRawCommentForDeclNoCache(const Decl *D) const
Return the documentation comment attached to a given declaration, without looking into cache.
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
SourceLocation getLocation() const
SourceLocation getEndLoc() const
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
static SourceLocation skipWhitespaceAndNewline(const SourceManager &SM, SourceLocation Loc, const LangOptions &LangOpts)
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
Token - This structure provides full information about a lexed token.
SourceManager & getSourceManager()
This class handles loading and caching of source files into memory.
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
tok::TokenKind getKind() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
static CharSourceRange getTokenRange(SourceRange R)
Decl - This represents one declaration (or definition), e.g.
Represents a character-granular source range.
SourceLocation getEnd() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
void SetKeepWhitespaceMode(bool Val)
SetKeepWhitespaceMode - This method lets clients enable or disable whitespace retention mode.
static bool contains(const std::set< tok::TokenKind > &Terminators, const Token &Tok)
LLVM_READONLY bool isVerticalWhitespace(unsigned char c)
Returns true if this character is vertical ASCII whitespace: '\n', '\r'.
bool isValid() const
Return true if this is a valid SourceLocation object.
Attr - This represents one attribute.
LLVM_READONLY bool isHorizontalWhitespace(unsigned char c)
Returns true if this character is horizontal ASCII whitespace: ' ', '\t', '\f', '\v'.
const LangOptions & getLangOpts() const
static bool startsWithNewline(const SourceManager &SM, const Token &Tok)
static CharSourceRange getAsCharRange(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Given a token range, produce a corresponding CharSourceRange that is not a token range.
static bool atOrBeforeSeparation(const SourceManager &SM, SourceLocation Loc, const LangOptions &LangOpts)