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");
97 const auto &Expansion =
SM.getSLocEntry(
SM.getFileID(Loc)).getExpansion();
98 if (Expansion.isMacroArgExpansion()) {
101 Loc = Expansion.getSpellingLoc();
102 ArgLocs.push_back(Expansion.getExpansionLocStart());
112 if (Range.getBegin().isMacroID() && Range.getEnd().isMacroID()) {
117 return B.empty() || B != E;
120 return Range.getBegin().isMacroID() || Range.getEnd().isMacroID();
126static std::optional<CharSourceRange>
131 auto &SLoc =
SM.getSLocEntry(
SM.getFileID(Loc), &
Invalid);
134 if (
auto &Expansion = SLoc.getExpansion();
135 !Expansion.isExpansionTokenRange()) {
139 return Expansion.getExpansionLocRange();
150 if (Range.isTokenRange()) {
155 BeginToken ? BeginToken->getBegin() : Range.getBegin();
160 }
else if (BeginToken) {
174 bool IncludeMacroExpansion) {
176 if (IncludeMacroExpansion) {
183 auto B =
SM.getSpellingLoc(AdjustedRange.getBegin());
184 auto E =
SM.getSpellingLoc(AdjustedRange.getEnd());
185 if (AdjustedRange.isTokenRange())
194 const LangOptions &LangOpts,
bool IncludeMacroExpansion) {
196 getRange(EditRange,
SM, LangOpts, IncludeMacroExpansion);
205 const LangOptions &LangOpts,
bool IncludeMacroExpansion) {
207 getRange(EditRange,
SM, LangOpts, IncludeMacroExpansion);
219static bool contains(
const std::set<tok::TokenKind> &Terminators,
221 return Terminators.count(
Tok.getKind()) > 0;
234 const std::set<tok::TokenKind> &Terminators,
236 assert(EntityLast.
isValid() &&
"Invalid end location found.");
246 std::unique_ptr<Lexer>
Lexer = [&]() {
248 auto FileOffset =
SM.getDecomposedLoc(ExpansionRange.
getEnd());
249 llvm::StringRef
File =
SM.getBufferData(FileOffset.first, &
Invalid);
250 assert(!
Invalid &&
"Cannot get file/offset");
251 return std::make_unique<clang::Lexer>(
252 SM.getLocForStartOfFile(FileOffset.first), LangOpts,
File.begin(),
253 File.data() + FileOffset.second,
File.end());
266 bool Terminated =
false;
288 bool TerminatedByMacro =
false;
290 if (Terminators.empty() ||
contains(Terminators,
Tok))
294 TerminatedByMacro =
true;
300 while (!Terminated) {
304 switch (
Tok.getKind()) {
315 End =
Tok.getEndLoc();
320 End =
Tok.getEndLoc();
329 switch (
Tok.getKind()) {
333 return Tok.getEndLoc();
337 End =
Tok.getEndLoc();
341 if (TerminatedByMacro &&
contains(Terminators,
Tok)) {
342 End =
Tok.getEndLoc();
344 TerminatedByMacro =
false;
363 if (llvm::isa<RecordDecl>(D) || llvm::isa<UsingDecl>(D))
366 if (llvm::isa<FunctionDecl>(D) || llvm::isa<LinkageSpecDecl>(D))
367 return {tok::r_brace, tok::semi};
369 if (llvm::isa<VarDecl>(D) || llvm::isa<FieldDecl>(D))
370 return {tok::comma, tok::semi};
381 const char *LocChars =
SM.getCharacterData(Loc);
401 const char *LocChars =
404 "Loc must be a valid character and not the first of the source file.");
419 switch (
Tok.getKind()) {
433 const LangOptions &LangOpts = Context.getLangOpts();
437 if (
const auto *
Record = llvm::dyn_cast<CXXRecordDecl>(&
Decl)) {
438 if (
const auto *
T =
Record->getDescribedClassTemplate())
439 if (
SM.isBeforeInTranslationUnit(
T->getBeginLoc(),
Range.getBegin()))
440 Range.setBegin(
T->getBeginLoc());
441 }
else if (
const auto *F = llvm::dyn_cast<FunctionDecl>(&
Decl)) {
442 if (
const auto *
T = F->getDescribedFunctionTemplate())
443 if (
SM.isBeforeInTranslationUnit(
T->getBeginLoc(),
Range.getBegin()))
444 Range.setBegin(
T->getBeginLoc());
451 Range.setTokenRange(
false);
464 if (
SM.isBeforeInTranslationUnit(Comment->getBeginLoc(),
470 const StringRef CommentText = Comment->getRawText(
SM);
471 if (!CommentText.contains(
"LINT.IfChange") &&
472 !CommentText.contains(
"LINT.ThenChange"))
473 Range.setBegin(Comment->getBeginLoc());
489 llvm::StringRef BeforeAttr =
490 Source.substr(0,
SM.getFileOffset(
Range.getBegin()));
491 llvm::StringRef BeforeAttrStripped = BeforeAttr.rtrim();
493 for (llvm::StringRef Prefix : {
"[[",
"__attribute__(("}) {
495 if (BeforeAttrStripped.ends_with(Prefix)) {
499 Range.setBegin(
Range.getBegin().getLocWithOffset(
static_cast<int>(
500 -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 llvm::SmallVector< SourceLocation, 2 > getMacroArgumentExpansionLocs(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',...