10#include "llvm/Support/Debug.h"
13#define DEBUG_TYPE "macro-expansion-context"
23 MacroExpansionContext::ExpansionRangeMap &ExpansionRanges;
28 MacroExpansionContext::ExpansionRangeMap &ExpansionRanges)
29 : PP(PP),
SM(
SM), ExpansionRanges(ExpansionRanges) {}
43 return SM.getExpansionLoc(
47 return SM.getExpansionLoc(
Range.
getEnd()).getLocWithOffset(1);
51 LLVM_DEBUG(llvm::dbgs() <<
"MacroExpands event: '";
54 <<
"' with length " << MacroName.
getLength() <<
" at ";
55 MacroNameBegin.
print(llvm::dbgs(),
SM);
56 llvm::dbgs() <<
", expansion end at ";
57 ExpansionEnd.
print(llvm::dbgs(),
SM); llvm::dbgs() <<
'\n';);
61 MacroExpansionContext::ExpansionRangeMap::iterator It;
63 std::tie(It, Inserted) =
64 ExpansionRanges.try_emplace(MacroNameBegin, ExpansionEnd);
66 LLVM_DEBUG(llvm::dbgs() <<
"maps ";
67 It->getFirst().
print(llvm::dbgs(),
SM); llvm::dbgs() <<
" to ";
68 It->getSecond().print(llvm::dbgs(),
SM);
69 llvm::dbgs() <<
'\n';);
71 if (
SM.isBeforeInTranslationUnit(It->getSecond(), ExpansionEnd)) {
72 It->getSecond() = ExpansionEnd;
74 llvm::dbgs() <<
"remaps "; It->getFirst().
print(llvm::dbgs(),
SM);
75 llvm::dbgs() <<
" to "; It->getSecond().print(llvm::dbgs(),
SM);
76 llvm::dbgs() <<
'\n';);
87 : LangOpts(LangOpts) {}
94 PP->
addPPCallbacks(std::make_unique<detail::MacroExpansionRangeRecorder>(
95 *PP, *SM, ExpansionRanges));
100std::optional<StringRef>
106 if (ExpansionRanges.find_as(MacroExpansionLoc) == ExpansionRanges.end())
110 const auto It = ExpandedTokens.find_as(MacroExpansionLoc);
111 if (It == ExpandedTokens.end())
112 return StringRef{
""};
115 return It->getSecond().str();
118std::optional<StringRef>
123 const auto It = ExpansionRanges.find_as(MacroExpansionLoc);
124 if (It == ExpansionRanges.end())
127 assert(It->getFirst() != It->getSecond() &&
128 "Every macro expansion must cover a non-empty range.");
143 std::vector<std::pair<SourceLocation, SourceLocation>> LocalExpansionRanges;
144 LocalExpansionRanges.reserve(ExpansionRanges.size());
145 for (
const auto &
Record : ExpansionRanges)
146 LocalExpansionRanges.emplace_back(
148 llvm::sort(LocalExpansionRanges);
150 OS <<
"\n=============== ExpansionRanges ===============\n";
151 for (
const auto &
Record : LocalExpansionRanges) {
153 Record.first.print(OS, *SM);
155 Record.second.print(OS, *SM);
161 std::vector<std::pair<SourceLocation, MacroExpansionText>>
163 LocalExpandedTokens.reserve(ExpandedTokens.size());
164 for (
const auto &
Record : ExpandedTokens)
165 LocalExpandedTokens.emplace_back(
167 llvm::sort(LocalExpandedTokens);
169 OS <<
"\n=============== ExpandedTokens ===============\n";
170 for (
const auto &
Record : LocalExpandedTokens) {
172 Record.first.print(OS, *SM);
173 OS <<
" -> '" <<
Record.second <<
"'\n";
178 assert(Tok.
isNot(tok::raw_identifier));
189 OS << II->getName() <<
' ';
195 const char *TokPtr = Tmp;
198 OS.write(TokPtr, Len);
200 OS <<
"<too long token>";
205void MacroExpansionContext::onTokenLexed(
const Token &Tok) {
210 LLVM_DEBUG(llvm::dbgs() <<
"lexed macro expansion token '";
211 dumpTokenInto(*PP, llvm::dbgs(), Tok); llvm::dbgs() <<
"' at ";
212 SLoc.
print(llvm::dbgs(), *SM); llvm::dbgs() <<
'\n';);
217 MacroExpansionText TokenAsString;
218 llvm::raw_svector_ostream OS(TokenAsString);
225 ExpansionMap::iterator It;
227 std::tie(It, Inserted) =
228 ExpandedTokens.try_emplace(CurrExpansionLoc, std::move(TokenAsString));
230 It->getSecond().append(TokenAsString);
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
llvm::MachO::Record Record
static void dumpTokenInto(const clang::Preprocessor &PP, llvm::raw_ostream &OS, clang::Token Tok)
static CharSourceRange getCharRange(SourceRange R)
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid=nullptr)
Returns a string for the source that the range encompasses.
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
A description of the current definition of a macro.
void registerForPreprocessor(Preprocessor &PP)
Register the necessary callbacks to the Preprocessor to record the expansion events and the generated...
LLVM_DUMP_METHOD void dumpExpandedTextsToStream(raw_ostream &OS) const
LLVM_DUMP_METHOD void dumpExpandedTexts() const
LLVM_DUMP_METHOD void dumpExpansionRanges() const
MacroExpansionContext(const LangOptions &LangOpts)
Creates a MacroExpansionContext.
LLVM_DUMP_METHOD void dumpExpansionRangesToStream(raw_ostream &OS) const
std::optional< StringRef > getExpandedText(SourceLocation MacroExpansionLoc) const
std::optional< StringRef > getOriginalText(SourceLocation MacroExpansionLoc) const
This interface provides a way to observe the actions of the preprocessor as it does its thing.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
SourceManager & getSourceManager() const
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
void setTokenWatcher(llvm::unique_function< void(const clang::Token &)> F)
Register a function that would be called on each token in the final expanded token stream.
Encodes a location in the source.
void print(raw_ostream &OS, const SourceManager &SM) const
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 getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
unsigned getLength() const
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
bool needsCleaning() const
Return true if this token has trigraphs or escaped newlines in it.
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
void MacroExpands(const Token &MacroName, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) override
Called by Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is found.
MacroExpansionRangeRecorder(const Preprocessor &PP, SourceManager &SM, MacroExpansionContext::ExpansionRangeMap &ExpansionRanges)
The JSON file list parser is used to communicate input to InstallAPI.