22#include "llvm/Support/Errc.h"
23#include "llvm/Support/Error.h"
29using llvm::StringError;
34 Context.getLangOpts());
41 Context.getLangOpts());
47 Context.getLangOpts(),
true);
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");
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();
94 assert(Loc.
isMacroID() &&
"Location must be in a macro");
96 const auto &Expansion =
SM.getSLocEntry(
SM.getFileID(Loc)).getExpansion();
97 if (Expansion.isMacroArgExpansion()) {
100 Loc = Expansion.getSpellingLoc();
110 if (Range.getBegin().isMacroID() && Range.getEnd().isMacroID()) {
114 return B.isInvalid() || B != E;
117 if (Range.getBegin().isMacroID())
119 if (Range.getEnd().isMacroID())
128static std::optional<CharSourceRange>
133 auto &SLoc =
SM.getSLocEntry(
SM.getFileID(Loc), &
Invalid);
136 if (
auto &Expansion = SLoc.getExpansion();
137 !Expansion.isExpansionTokenRange()) {
141 return Expansion.getExpansionLocRange();
152 if (Range.isTokenRange()) {
157 BeginToken ? BeginToken->getBegin() : Range.getBegin();
162 }
else if (BeginToken) {
176 bool IncludeMacroExpansion) {
178 if (IncludeMacroExpansion) {
185 auto B =
SM.getSpellingLoc(AdjustedRange.getBegin());
186 auto E =
SM.getSpellingLoc(AdjustedRange.getEnd());
187 if (AdjustedRange.isTokenRange())
196 const LangOptions &LangOpts,
bool IncludeMacroExpansion) {
198 getRange(EditRange,
SM, LangOpts, IncludeMacroExpansion);
207 const LangOptions &LangOpts,
bool IncludeMacroExpansion) {
209 getRange(EditRange,
SM, LangOpts, IncludeMacroExpansion);
221static bool contains(
const std::set<tok::TokenKind> &Terminators,
223 return Terminators.count(
Tok.getKind()) > 0;
236 const std::set<tok::TokenKind> &Terminators,
238 assert(EntityLast.
isValid() &&
"Invalid end location found.");
248 std::unique_ptr<Lexer>
Lexer = [&]() {
250 auto FileOffset =
SM.getDecomposedLoc(ExpansionRange.
getEnd());
251 llvm::StringRef
File =
SM.getBufferData(FileOffset.first, &
Invalid);
252 assert(!
Invalid &&
"Cannot get file/offset");
253 return std::make_unique<clang::Lexer>(
254 SM.getLocForStartOfFile(FileOffset.first), LangOpts,
File.begin(),
255 File.data() + FileOffset.second,
File.end());
268 bool Terminated =
false;
290 bool TerminatedByMacro =
false;
292 if (Terminators.empty() ||
contains(Terminators,
Tok))
296 TerminatedByMacro =
true;
302 while (!Terminated) {
306 switch (
Tok.getKind()) {
317 End =
Tok.getEndLoc();
322 End =
Tok.getEndLoc();
331 switch (
Tok.getKind()) {
335 return Tok.getEndLoc();
339 End =
Tok.getEndLoc();
343 if (TerminatedByMacro &&
contains(Terminators,
Tok)) {
344 End =
Tok.getEndLoc();
346 TerminatedByMacro =
false;
365 if (llvm::isa<RecordDecl>(D) || llvm::isa<UsingDecl>(D))
368 if (llvm::isa<FunctionDecl>(D) || llvm::isa<LinkageSpecDecl>(D))
369 return {tok::r_brace, tok::semi};
371 if (llvm::isa<VarDecl>(D) || llvm::isa<FieldDecl>(D))
372 return {tok::comma, tok::semi};
383 const char *LocChars =
SM.getCharacterData(Loc);
403 const char *LocChars =
406 "Loc must be a valid character and not the first of the source file.");
421 switch (
Tok.getKind()) {
435 const LangOptions &LangOpts = Context.getLangOpts();
439 if (
const auto *
Record = llvm::dyn_cast<CXXRecordDecl>(&
Decl)) {
440 if (
const auto *
T =
Record->getDescribedClassTemplate())
441 if (
SM.isBeforeInTranslationUnit(
T->getBeginLoc(),
Range.getBegin()))
442 Range.setBegin(
T->getBeginLoc());
443 }
else if (
const auto *F = llvm::dyn_cast<FunctionDecl>(&
Decl)) {
444 if (
const auto *
T = F->getDescribedFunctionTemplate())
445 if (
SM.isBeforeInTranslationUnit(
T->getBeginLoc(),
Range.getBegin()))
446 Range.setBegin(
T->getBeginLoc());
453 Range.setTokenRange(
false);
466 if (
SM.isBeforeInTranslationUnit(Comment->getBeginLoc(),
472 const StringRef CommentText = Comment->getRawText(
SM);
473 if (!CommentText.contains(
"LINT.IfChange") &&
474 !CommentText.contains(
"LINT.ThenChange"))
475 Range.setBegin(Comment->getBeginLoc());
491 llvm::StringRef BeforeAttr =
492 Source.substr(0,
SM.getFileOffset(
Range.getBegin()));
493 llvm::StringRef BeforeAttrStripped = BeforeAttr.rtrim();
495 for (llvm::StringRef Prefix : {
"[[",
"__attribute__(("}) {
497 if (BeforeAttrStripped.ends_with(Prefix)) {
501 Range.setBegin(
Range.getBegin().getLocWithOffset(
static_cast<int>(
502 -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 SourceLocation getMacroArgumentSpellingLoc(SourceLocation Loc, const SourceManager &SM)
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 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 bool spelledInMacroDefinition(CharSourceRange Range, const SourceManager &SM)
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 ...
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.
Token - This structure provides full information about a lexed token.
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'.
std::pair< FileID, unsigned > FileIDAndOffset
LLVM_READONLY bool isHorizontalWhitespace(unsigned char c)
Returns true if this character is horizontal ASCII whitespace: ' ', '\t', '\f', '\v'.
const FunctionProtoType * T
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...