22#include "llvm/Support/Errc.h"
23#include "llvm/Support/Error.h"
29using llvm::StringError;
48 if (Err || !Tok.
is(Next))
55 bool AllowSystemHeaders) {
56 if (
Range.isInvalid())
57 return llvm::make_error<StringError>(errc::invalid_argument,
60 if (
Range.getBegin().isMacroID() ||
Range.getEnd().isMacroID())
61 return llvm::make_error<StringError>(
62 errc::invalid_argument,
"Range starts or ends in a macro expansion");
64 if (!AllowSystemHeaders) {
65 if (
SM.isInSystemHeader(
Range.getBegin()) ||
66 SM.isInSystemHeader(
Range.getEnd()))
67 return llvm::make_error<StringError>(errc::invalid_argument,
68 "Range is in system header");
71 std::pair<FileID, unsigned> BeginInfo =
SM.getDecomposedLoc(
Range.getBegin());
72 std::pair<FileID, unsigned> EndInfo =
SM.getDecomposedLoc(
Range.getEnd());
73 if (BeginInfo.first != EndInfo.first)
74 return llvm::make_error<StringError>(
75 errc::invalid_argument,
"Range begins and ends in different files");
77 if (BeginInfo.second > EndInfo.second)
78 return llvm::make_error<StringError>(errc::invalid_argument,
79 "Range's begin is past its end");
81 return llvm::Error::success();
92 const auto &Expansion =
SM.getSLocEntry(
SM.getFileID(Loc)).getExpansion();
93 if (Expansion.isMacroArgExpansion()) {
96 Loc = Expansion.getSpellingLoc();
107 bool IncludeMacroExpansion) {
109 if (IncludeMacroExpansion) {
116 auto B =
SM.getSpellingLoc(EditRange.
getBegin());
117 auto E =
SM.getSpellingLoc(EditRange.
getEnd());
127 const LangOptions &LangOpts,
bool IncludeMacroExpansion) {
129 getRange(EditRange,
SM, LangOpts, IncludeMacroExpansion);
138 const LangOptions &LangOpts,
bool IncludeMacroExpansion) {
140 getRange(EditRange,
SM, LangOpts, IncludeMacroExpansion);
152static bool contains(
const std::set<tok::TokenKind> &Terminators,
154 return Terminators.count(Tok.
getKind()) > 0;
167 const std::set<tok::TokenKind> &Terminators,
169 assert(EntityLast.
isValid() &&
"Invalid end location found.");
179 std::unique_ptr<Lexer>
Lexer = [&]() {
181 auto FileOffset =
SM.getDecomposedLoc(ExpansionRange.
getEnd());
182 llvm::StringRef
File =
SM.getBufferData(FileOffset.first, &
Invalid);
183 assert(!
Invalid &&
"Cannot get file/offset");
184 return std::make_unique<clang::Lexer>(
185 SM.getLocForStartOfFile(FileOffset.first), LangOpts,
File.begin(),
186 File.data() + FileOffset.second,
File.end());
199 bool Terminated =
false;
221 bool TerminatedByMacro =
false;
223 if (Terminators.empty() ||
contains(Terminators, Tok))
227 TerminatedByMacro =
true;
233 while (!Terminated) {
274 if (TerminatedByMacro &&
contains(Terminators, Tok)) {
277 TerminatedByMacro =
false;
296 if (llvm::isa<RecordDecl>(D) || llvm::isa<UsingDecl>(D))
299 if (llvm::isa<FunctionDecl>(D) || llvm::isa<LinkageSpecDecl>(D))
300 return {tok::r_brace, tok::semi};
302 if (llvm::isa<VarDecl>(D) || llvm::isa<FieldDecl>(D))
303 return {tok::comma, tok::semi};
314 const char *LocChars =
SM.getCharacterData(Loc);
334 const char *LocChars =
337 "Loc must be a valid character and not the first of the source file.");
370 if (
const auto *Record = llvm::dyn_cast<CXXRecordDecl>(&
Decl)) {
371 if (
const auto *T = Record->getDescribedClassTemplate())
372 if (
SM.isBeforeInTranslationUnit(T->getBeginLoc(),
Range.getBegin()))
373 Range.setBegin(T->getBeginLoc());
374 }
else if (
const auto *F = llvm::dyn_cast<FunctionDecl>(&
Decl)) {
375 if (
const auto *T = F->getDescribedFunctionTemplate())
376 if (
SM.isBeforeInTranslationUnit(T->getBeginLoc(),
Range.getBegin()))
377 Range.setBegin(T->getBeginLoc());
384 Range.setTokenRange(
false);
397 if (
SM.isBeforeInTranslationUnit(Comment->getBeginLoc(),
403 const StringRef CommentText = Comment->getRawText(
SM);
404 if (!CommentText.contains(
"LINT.IfChange") &&
405 !CommentText.contains(
"LINT.ThenChange"))
406 Range.setBegin(Comment->getBeginLoc());
422 llvm::StringRef BeforeAttr =
423 Source.substr(0,
SM.getFileOffset(
Range.getBegin()));
424 llvm::StringRef BeforeAttrStripped = BeforeAttr.rtrim();
426 for (llvm::StringRef Prefix : {
"[[",
"__attribute__(("}) {
428 if (BeforeAttrStripped.endswith(Prefix)) {
432 Range.setBegin(
Range.getBegin().getLocWithOffset(
static_cast<int>(
433 -BeforeAttr.size() + BeforeAttrStripped.size() - Prefix.size())));
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
static bool contains(const std::set< tok::TokenKind > &Terminators, const Token &Tok)
static bool atOrBeforeSeparation(const SourceManager &SM, SourceLocation Loc, const LangOptions &LangOpts)
static bool startsWithNewline(const SourceManager &SM, const Token &Tok)
static SourceLocation getEntityEndLoc(const SourceManager &SM, SourceLocation EntityLast, const std::set< tok::TokenKind > &Terminators, const LangOptions &LangOpts)
static bool spelledInMacroDefinition(SourceLocation Loc, const SourceManager &SM)
static SourceLocation skipWhitespaceAndNewline(const SourceManager &SM, SourceLocation Loc, const LangOptions &LangOpts)
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
static std::set< tok::TokenKind > getTerminators(const Decl &D)
Defines the SourceManager interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const LangOptions & getLangOpts() const
RawComment * getRawCommentForDeclNoCache(const Decl *D) const
Return the documentation comment attached to a given declaration, without looking into cache.
Attr - This represents one attribute.
SourceLocation getLocation() const
Represents a character-granular source range.
bool isTokenRange() const
Return true if the end of this range specifies the start of the last token.
static CharSourceRange getCharRange(SourceRange R)
static CharSourceRange getTokenRange(SourceRange R)
SourceLocation getEnd() const
SourceLocation getBegin() const
Decl - This represents one declaration (or definition), e.g.
SourceLocation getEndLoc() const LLVM_READONLY
ASTContext & getASTContext() const LLVM_READONLY
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
void SetKeepWhitespaceMode(bool Val)
SetKeepWhitespaceMode - This method lets clients enable or disable whitespace retention mode.
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
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 CharSourceRange makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Accepts a range and returns a character range with file locations.
static bool getRawToken(SourceLocation Loc, Token &Result, const SourceManager &SM, const LangOptions &LangOpts, bool IgnoreWhiteSpace=false)
Relex the token at the specified location.
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
Token - This structure provides full information about a lexed token.
SourceLocation getEndLoc() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
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)) {....
tok::TokenKind getKind() const
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
LLVM_READONLY bool isVerticalWhitespace(unsigned char c)
Returns true if this character is vertical ASCII whitespace: '\n', '\r'.
LLVM_READONLY bool isHorizontalWhitespace(unsigned char c)
Returns true if this character is horizontal ASCII whitespace: ' ', '\t', '\f', '\v'.
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...