25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/ADT/SmallString.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include "llvm/Support/raw_ostream.h"
31 using namespace clang;
37 OS <<
"#define " << II.
getName();
43 for (; AI+1 !=
E; ++AI) {
44 OS << (*AI)->getName();
49 if ((*AI)->getName() ==
"__VA_ARGS__")
52 OS << (*AI)->getName();
67 for (
const auto &T : MI.
tokens()) {
68 if (T.hasLeadingSpace())
80 class PrintPPOutputPPCallbacks :
public PPCallbacks {
89 bool EmittedTokensOnThisLine;
90 bool EmittedDirectiveOnThisLine;
94 bool DisableLineMarkers;
96 bool UseLineDirectives;
97 bool IsFirstFileEntered;
99 PrintPPOutputPPCallbacks(
Preprocessor &pp, raw_ostream &os,
bool lineMarkers,
100 bool defines,
bool UseLineDirectives)
101 : PP(pp),
SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
102 DisableLineMarkers(lineMarkers), DumpDefines(defines),
103 UseLineDirectives(UseLineDirectives) {
105 CurFilename +=
"<uninit>";
106 EmittedTokensOnThisLine =
false;
107 EmittedDirectiveOnThisLine =
false;
110 IsFirstFileEntered =
false;
113 void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine =
true; }
114 bool hasEmittedTokensOnThisLine()
const {
return EmittedTokensOnThisLine; }
116 void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine =
true; }
117 bool hasEmittedDirectiveOnThisLine()
const {
118 return EmittedDirectiveOnThisLine;
121 bool startNewLineIfNeeded(
bool ShouldUpdateCurrentLine =
true);
129 StringRef SearchPath, StringRef RelativePath,
130 const Module *Imported)
override;
133 PragmaMessageKind
Kind, StringRef Str)
override;
134 void PragmaDebug(
SourceLocation Loc, StringRef DebugType)
override;
135 void PragmaDiagnosticPush(
SourceLocation Loc, StringRef Namespace)
override;
136 void PragmaDiagnosticPop(
SourceLocation Loc, StringRef Namespace)
override;
144 bool HandleFirstTokOnLine(
Token &Tok);
155 bool MoveToLine(
unsigned LineNo);
157 bool AvoidConcat(
const Token &PrevPrevTok,
const Token &PrevTok,
159 return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok);
161 void WriteLineInfo(
unsigned LineNo,
const char *Extra=
nullptr,
162 unsigned ExtraLen=0);
163 bool LineMarkersAreDisabled()
const {
return DisableLineMarkers; }
164 void HandleNewlinesInToken(
const char *TokStr,
unsigned Len);
167 void MacroDefined(
const Token &MacroNameTok,
171 void MacroUndefined(
const Token &MacroNameTok,
176 void PrintPPOutputPPCallbacks::WriteLineInfo(
unsigned LineNo,
179 startNewLineIfNeeded(
false);
182 if (UseLineDirectives) {
183 OS <<
"#line" <<
' ' << LineNo <<
' ' <<
'"';
184 OS.write_escaped(CurFilename);
187 OS <<
'#' <<
' ' << LineNo <<
' ' <<
'"';
188 OS.write_escaped(CurFilename);
192 OS.write(Extra, ExtraLen);
206 bool PrintPPOutputPPCallbacks::MoveToLine(
unsigned LineNo) {
209 if (LineNo-CurLine <= 8) {
210 if (LineNo-CurLine == 1)
212 else if (LineNo == CurLine)
215 const char *NewLines =
"\n\n\n\n\n\n\n\n";
216 OS.write(NewLines, LineNo-CurLine);
218 }
else if (!DisableLineMarkers) {
220 WriteLineInfo(LineNo,
nullptr, 0);
224 startNewLineIfNeeded(
false);
232 PrintPPOutputPPCallbacks::startNewLineIfNeeded(
bool ShouldUpdateCurrentLine) {
233 if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) {
235 EmittedTokensOnThisLine =
false;
236 EmittedDirectiveOnThisLine =
false;
237 if (ShouldUpdateCurrentLine)
249 FileChangeReason Reason,
265 MoveToLine(IncludeLoc);
279 FileType = NewFileType;
281 if (DisableLineMarkers) {
282 startNewLineIfNeeded(
false);
287 WriteLineInfo(CurLine);
296 IsFirstFileEntered =
true;
302 WriteLineInfo(CurLine,
" 1", 2);
305 WriteLineInfo(CurLine,
" 2", 2);
309 WriteLineInfo(CurLine);
314 void PrintPPOutputPPCallbacks::InclusionDirective(
SourceLocation HashLoc,
315 const Token &IncludeTok,
320 StringRef SearchPath,
321 StringRef RelativePath,
327 startNewLineIfNeeded();
329 if (PP.getLangOpts().ObjC2) {
331 <<
" /* clang -E: implicit import for \"" << File->
getName()
337 << (IsAngled ?
'<' :
'"')
339 << (IsAngled ?
'>' :
'"')
340 <<
" /* clang -E: implicit import for module "
345 EmittedTokensOnThisLine =
true;
346 startNewLineIfNeeded();
352 void PrintPPOutputPPCallbacks::Ident(
SourceLocation Loc, StringRef
S) {
355 OS.write(
"#ident ", strlen(
"#ident "));
356 OS.write(S.begin(), S.size());
357 EmittedTokensOnThisLine =
true;
361 void PrintPPOutputPPCallbacks::MacroDefined(
const Token &MacroNameTok,
371 setEmittedDirectiveOnThisLine();
374 void PrintPPOutputPPCallbacks::MacroUndefined(
const Token &MacroNameTok,
377 if (!DumpDefines)
return;
381 setEmittedDirectiveOnThisLine();
385 for (
unsigned char Char : Str) {
386 if (
isPrintable(Char) && Char !=
'\\' && Char !=
'"')
390 << (char)(
'0' + ((Char >> 6) & 7))
391 << (char)(
'0' + ((Char >> 3) & 7))
392 << (char)(
'0' + ((Char >> 0) & 7));
398 PragmaMessageKind
Kind,
400 startNewLineIfNeeded();
403 if (!Namespace.empty())
404 OS << Namespace <<
' ';
419 if (Kind == PMK_Message)
421 setEmittedDirectiveOnThisLine();
425 StringRef DebugType) {
426 startNewLineIfNeeded();
429 OS <<
"#pragma clang __debug ";
432 setEmittedDirectiveOnThisLine();
435 void PrintPPOutputPPCallbacks::
437 startNewLineIfNeeded();
439 OS <<
"#pragma " << Namespace <<
" diagnostic push";
440 setEmittedDirectiveOnThisLine();
443 void PrintPPOutputPPCallbacks::
445 startNewLineIfNeeded();
447 OS <<
"#pragma " << Namespace <<
" diagnostic pop";
448 setEmittedDirectiveOnThisLine();
451 void PrintPPOutputPPCallbacks::PragmaDiagnostic(
SourceLocation Loc,
455 startNewLineIfNeeded();
457 OS <<
"#pragma " << Namespace <<
" diagnostic ";
475 OS <<
" \"" << Str <<
'"';
476 setEmittedDirectiveOnThisLine();
480 StringRef WarningSpec,
482 startNewLineIfNeeded();
484 OS <<
"#pragma warning(" << WarningSpec <<
':';
488 setEmittedDirectiveOnThisLine();
491 void PrintPPOutputPPCallbacks::PragmaWarningPush(
SourceLocation Loc,
493 startNewLineIfNeeded();
495 OS <<
"#pragma warning(push";
499 setEmittedDirectiveOnThisLine();
502 void PrintPPOutputPPCallbacks::PragmaWarningPop(
SourceLocation Loc) {
503 startNewLineIfNeeded();
505 OS <<
"#pragma warning(pop)";
506 setEmittedDirectiveOnThisLine();
514 bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(
Token &Tok) {
537 if (ColNo <= 1 && Tok.
is(tok::hash))
541 for (; ColNo > 1; --ColNo)
547 void PrintPPOutputPPCallbacks::HandleNewlinesInToken(
const char *TokStr,
549 unsigned NumNewlines = 0;
550 for (; Len; --Len, ++TokStr) {
551 if (*TokStr !=
'\n' &&
559 (TokStr[1] ==
'\n' || TokStr[1] ==
'\r') &&
560 TokStr[0] != TokStr[1]) {
566 if (NumNewlines == 0)
return;
568 CurLine += NumNewlines;
575 PrintPPOutputPPCallbacks *Callbacks;
578 bool ShouldExpandTokens;
580 UnknownPragmaHandler(
const char *prefix, PrintPPOutputPPCallbacks *callbacks,
581 bool RequireTokenExpansion)
582 : Prefix(prefix), Callbacks(callbacks),
583 ShouldExpandTokens(RequireTokenExpansion) {}
585 Token &PragmaTok)
override {
588 Callbacks->startNewLineIfNeeded();
590 Callbacks->OS.write(Prefix, strlen(Prefix));
592 if (ShouldExpandTokens) {
595 auto Toks = llvm::make_unique<Token[]>(1);
597 PP.EnterTokenStream(std::move(Toks), 1,
607 while (PragmaTok.
isNot(tok::eod)) {
609 Callbacks->AvoidConcat(PrevPrevToken, PrevToken, PragmaTok))
610 Callbacks->OS <<
' ';
612 Callbacks->OS.write(&TokSpell[0], TokSpell.size());
614 PrevPrevToken = PrevToken;
615 PrevToken = PragmaTok;
617 if (ShouldExpandTokens)
622 Callbacks->setEmittedDirectiveOnThisLine();
629 PrintPPOutputPPCallbacks *Callbacks,
631 bool DropComments = PP.
getLangOpts().TraditionalCPP &&
635 Token PrevPrevTok, PrevTok;
639 if (Callbacks->hasEmittedDirectiveOnThisLine()) {
640 Callbacks->startNewLineIfNeeded();
650 (Callbacks->hasEmittedTokensOnThisLine() &&
652 Callbacks->AvoidConcat(PrevPrevTok, PrevTok, Tok))) {
656 if (DropComments && Tok.
is(tok::comment)) {
662 }
else if (Tok.
is(tok::annot_module_include) ||
663 Tok.
is(tok::annot_module_begin) ||
664 Tok.
is(tok::annot_module_end)) {
675 const char *TokPtr =
Buffer;
677 OS.write(TokPtr, Len);
681 if (Tok.
getKind() == tok::comment || Tok.
getKind() == tok::unknown)
682 Callbacks->HandleNewlinesInToken(TokPtr, Len);
685 OS.write(&S[0], S.size());
689 if (Tok.
getKind() == tok::comment || Tok.
getKind() == tok::unknown)
690 Callbacks->HandleNewlinesInToken(&S[0], S.size());
692 Callbacks->setEmittedTokensOnThisLine();
696 PrevPrevTok = PrevTok;
704 return LHS->first->getName().compare(RHS->first->getName());
722 auto *MD =
I->second.getLatest();
723 if (MD && MD->isDefined())
726 llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(),
MacroIDCompare);
728 for (
unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
744 assert(Opts.
ShowMacros &&
"Not yet implemented!");
753 PrintPPOutputPPCallbacks *Callbacks =
new PrintPPOutputPPCallbacks(
759 "#pragma", Callbacks,
762 "GCC",
new UnknownPragmaHandler(
763 "#pragma GCC", Callbacks,
766 "clang",
new UnknownPragmaHandler(
767 "#pragma clang", Callbacks,
776 new UnknownPragmaHandler(
"#pragma omp", Callbacks,
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
SourceManager & getSourceManager() const
static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, Preprocessor &PP, raw_ostream &OS)
PrintMacroDefinition - Print a macro definition in a form that will be properly accepted back as a de...
std::pair< const IdentifierInfo *, MacroInfo * > id_macro_pair
void AddPragmaHandler(StringRef Namespace, PragmaHandler *Handler)
Add the specified pragma handler to this preprocessor.
bool isInvalid() const
Return true if this object is invalid or uninitialized.
Defines the SourceManager interface.
TokenConcatenation class, which answers the question of "Is it safe to emit two tokens without a whit...
Defines the clang::MacroInfo and clang::MacroDirective classes.
bool hasLeadingSpace() const
Return true if this token has whitespace before it.
A description of the current definition of a macro.
std::unique_ptr< llvm::MemoryBuffer > Buffer
macro_iterator macro_begin(bool IncludeExternalMacros=true) const
bool needsCleaning() const
Return true if this token has trigraphs or escaped newlines in it.
MacroMap::const_iterator macro_iterator
void IgnorePragmas()
Install empty handlers for all pragmas (making them ignored).
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing)...
SourceLocation getDefinitionLoc() const
Return the location that the macro was defined at.
CharacteristicKind
Indicates whether a file or directory holds normal user code, system code, or system code which is im...
This interface provides a way to observe the actions of the preprocessor as it does its thing...
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 ...
std::string getFullModuleName() const
Retrieve the full name of this module, including the path from its top-level module.
One of these records is kept for each identifier that is lexed.
const LangOptions & getLangOpts() const
Token - This structure provides full information about a lexed token.
void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments)
Control whether the preprocessor retains comments in output.
bool tokens_empty() const
Describes a module or submodule.
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
unsigned getExpansionColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
bool getCommentRetentionState() const
tokens_iterator tokens_begin() const
Present this diagnostic as an error.
tok::TokenKind getKind() const
unsigned getLine() const
Return the presumed line number of this location.
detail::InMemoryDirectory::const_iterator I
PragmaIntroducerKind
Describes how the pragma was introduced, e.g., with #pragma, _Pragma, or __pragma.
SourceLocation getIncludeLoc() const
Return the presumed include location of this location.
ArrayRef< Token > tokens() const
void LexUnexpandedToken(Token &Result)
Just like Lex, but disables macro expansion of identifier tokens.
PreprocessorOutputOptions - Options for controlling the C preprocessor output (e.g., -E).
void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts)
DoPrintPreprocessedInput - Implement -E mode.
IdentifierInfo *const * arg_iterator
Arguments - The list of arguments for a function-like macro.
static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS)
StringRef getName() const
Return the actual identifier string.
Represents a character-granular source range.
static void outputPrintable(raw_ostream &OS, StringRef Str)
void EnterMainSourceFile()
Enter the specified FileID as the main source file, which implicitly adds the builtin defines etc...
Defines the clang::Preprocessor interface.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
bool isNot(tok::TokenKind K) const
unsigned ShowMacros
Print macro definitions.
Record the location of an inclusion directive, such as an #include or #import statement.
Represents an unpacked "presumed" location which can be presented to the user.
arg_iterator arg_end() const
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
static int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS)
const char * getFilename() const
Return the presumed filename of this location.
const char * getName() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
macro_iterator macro_end(bool IncludeExternalMacros=true) const
Cached information about one file (either on disk or in the virtual file system). ...
void Lex(Token &Result)
Lex the next token for this preprocessor.
unsigned UseLineDirectives
Use #line instead of GCC-style # N.
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)) {...
unsigned ShowComments
Show comments.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
static LLVM_READONLY bool isPrintable(unsigned char c)
Return true if this character is an ASCII printable character; that is, a character that should take ...
Present this diagnostic as a remark.
bool isGNUVarargs() const
PragmaHandler - Instances of this interface defined to handle the various pragmas that the language f...
const MacroInfo * getMacroInfo() const
detail::InMemoryDirectory::const_iterator E
unsigned Map[Count]
The type of a lookup table which maps from language-specific address spaces to target-specific ones...
Defines the Diagnostic-related interfaces.
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
bool isFunctionLike() const
Encapsulates the data about a macro definition (e.g.
bool isBuiltinMacro() const
Return true if this macro requires processing before expansion.
Defines the PPCallbacks interface.
unsigned ShowMacroComments
Show comments, even in macros.
Do not present this diagnostic, ignore it.
unsigned ShowLineMarkers
Show #line markers.
unsigned ShowCPP
Print normal preprocessed output.
unsigned getLength() const
Present this diagnostic as a fatal error.
arg_iterator arg_begin() const
Present this diagnostic as a warning.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
This class handles loading and caching of source files into memory.
void startToken()
Reset all flags to cleared.
static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, PrintPPOutputPPCallbacks *Callbacks, raw_ostream &OS)
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
IdentifierInfo * getIdentifierInfo() const
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.