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();
107static std::optional<CharSourceRange>
115 if (
auto &Expansion = SLoc.getExpansion();
116 !Expansion.isExpansionTokenRange()) {
120 return Expansion.getExpansionLocRange();
131 if (
Range.isTokenRange()) {
141 }
else if (BeginToken) {
155 bool IncludeMacroExpansion) {
157 if (IncludeMacroExpansion) {
165 auto B =
SM.getSpellingLoc(AdjustedRange.getBegin());
166 auto E =
SM.getSpellingLoc(AdjustedRange.getEnd());
167 if (AdjustedRange.isTokenRange())
176 const LangOptions &LangOpts,
bool IncludeMacroExpansion) {
178 getRange(EditRange,
SM, LangOpts, IncludeMacroExpansion);
187 const LangOptions &LangOpts,
bool IncludeMacroExpansion) {
189 getRange(EditRange,
SM, LangOpts, IncludeMacroExpansion);
201static bool contains(
const std::set<tok::TokenKind> &Terminators,
203 return Terminators.count(Tok.
getKind()) > 0;
216 const std::set<tok::TokenKind> &Terminators,
218 assert(EntityLast.
isValid() &&
"Invalid end location found.");
228 std::unique_ptr<Lexer>
Lexer = [&]() {
230 auto FileOffset =
SM.getDecomposedLoc(ExpansionRange.
getEnd());
231 llvm::StringRef
File =
SM.getBufferData(FileOffset.first, &
Invalid);
232 assert(!
Invalid &&
"Cannot get file/offset");
233 return std::make_unique<clang::Lexer>(
234 SM.getLocForStartOfFile(FileOffset.first), LangOpts,
File.begin(),
235 File.data() + FileOffset.second,
File.end());
248 bool Terminated =
false;
270 bool TerminatedByMacro =
false;
272 if (Terminators.empty() ||
contains(Terminators, Tok))
276 TerminatedByMacro =
true;
282 while (!Terminated) {
323 if (TerminatedByMacro &&
contains(Terminators, Tok)) {
326 TerminatedByMacro =
false;
345 if (llvm::isa<RecordDecl>(
D) || llvm::isa<UsingDecl>(
D))
348 if (llvm::isa<FunctionDecl>(
D) || llvm::isa<LinkageSpecDecl>(
D))
349 return {tok::r_brace, tok::semi};
351 if (llvm::isa<VarDecl>(
D) || llvm::isa<FieldDecl>(
D))
352 return {tok::comma, tok::semi};
363 const char *LocChars =
SM.getCharacterData(
Loc);
383 const char *LocChars =
386 "Loc must be a valid character and not the first of the source file.");
419 if (
const auto *
Record = llvm::dyn_cast<CXXRecordDecl>(&
Decl)) {
420 if (
const auto *
T =
Record->getDescribedClassTemplate())
421 if (
SM.isBeforeInTranslationUnit(
T->getBeginLoc(),
Range.getBegin()))
422 Range.setBegin(
T->getBeginLoc());
423 }
else if (
const auto *F = llvm::dyn_cast<FunctionDecl>(&
Decl)) {
424 if (
const auto *
T = F->getDescribedFunctionTemplate())
425 if (
SM.isBeforeInTranslationUnit(
T->getBeginLoc(),
Range.getBegin()))
426 Range.setBegin(
T->getBeginLoc());
433 Range.setTokenRange(
false);
446 if (
SM.isBeforeInTranslationUnit(Comment->getBeginLoc(),
452 const StringRef CommentText = Comment->getRawText(
SM);
453 if (!CommentText.contains(
"LINT.IfChange") &&
454 !CommentText.contains(
"LINT.ThenChange"))
455 Range.setBegin(Comment->getBeginLoc());
471 llvm::StringRef BeforeAttr =
472 Source.substr(0,
SM.getFileOffset(
Range.getBegin()));
473 llvm::StringRef BeforeAttrStripped = BeforeAttr.rtrim();
475 for (llvm::StringRef Prefix : {
"[[",
"__attribute__(("}) {
477 if (BeforeAttrStripped.ends_with(Prefix)) {
481 Range.setBegin(
Range.getBegin().getLocWithOffset(
static_cast<int>(
482 -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.
llvm::MachO::Record Record
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 CharSourceRange getRangeForSplitTokens(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
static SourceLocation skipWhitespaceAndNewline(const SourceManager &SM, SourceLocation Loc, const LangOptions &LangOpts)
static std::optional< CharSourceRange > getExpansionForSplitToken(SourceLocation Loc, const SourceManager &SM, 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.
static CharSourceRange getCharRange(SourceRange R)
static CharSourceRange getTokenRange(SourceRange R)
SourceLocation getEnd() 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.
SourceLocation getEnd() const
SourceLocation getBegin() const
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.
The JSON file list parser is used to communicate input to InstallAPI.
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',...
const FunctionProtoType * T