1*0b57cec5SDimitry Andric //===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This code simply runs the preprocessor on the input file and prints out the 10*0b57cec5SDimitry Andric // result. This is the traditional behavior of the -E option. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "clang/Frontend/Utils.h" 15*0b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 16*0b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 17*0b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 18*0b57cec5SDimitry Andric #include "clang/Frontend/PreprocessorOutputOptions.h" 19*0b57cec5SDimitry Andric #include "clang/Lex/MacroInfo.h" 20*0b57cec5SDimitry Andric #include "clang/Lex/PPCallbacks.h" 21*0b57cec5SDimitry Andric #include "clang/Lex/Pragma.h" 22*0b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 23*0b57cec5SDimitry Andric #include "clang/Lex/TokenConcatenation.h" 24*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 25*0b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 26*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 27*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 28*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 29*0b57cec5SDimitry Andric #include <cstdio> 30*0b57cec5SDimitry Andric using namespace clang; 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric /// PrintMacroDefinition - Print a macro definition in a form that will be 33*0b57cec5SDimitry Andric /// properly accepted back as a definition. 34*0b57cec5SDimitry Andric static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, 35*0b57cec5SDimitry Andric Preprocessor &PP, raw_ostream &OS) { 36*0b57cec5SDimitry Andric OS << "#define " << II.getName(); 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric if (MI.isFunctionLike()) { 39*0b57cec5SDimitry Andric OS << '('; 40*0b57cec5SDimitry Andric if (!MI.param_empty()) { 41*0b57cec5SDimitry Andric MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end(); 42*0b57cec5SDimitry Andric for (; AI+1 != E; ++AI) { 43*0b57cec5SDimitry Andric OS << (*AI)->getName(); 44*0b57cec5SDimitry Andric OS << ','; 45*0b57cec5SDimitry Andric } 46*0b57cec5SDimitry Andric 47*0b57cec5SDimitry Andric // Last argument. 48*0b57cec5SDimitry Andric if ((*AI)->getName() == "__VA_ARGS__") 49*0b57cec5SDimitry Andric OS << "..."; 50*0b57cec5SDimitry Andric else 51*0b57cec5SDimitry Andric OS << (*AI)->getName(); 52*0b57cec5SDimitry Andric } 53*0b57cec5SDimitry Andric 54*0b57cec5SDimitry Andric if (MI.isGNUVarargs()) 55*0b57cec5SDimitry Andric OS << "..."; // #define foo(x...) 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric OS << ')'; 58*0b57cec5SDimitry Andric } 59*0b57cec5SDimitry Andric 60*0b57cec5SDimitry Andric // GCC always emits a space, even if the macro body is empty. However, do not 61*0b57cec5SDimitry Andric // want to emit two spaces if the first token has a leading space. 62*0b57cec5SDimitry Andric if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace()) 63*0b57cec5SDimitry Andric OS << ' '; 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric SmallString<128> SpellingBuffer; 66*0b57cec5SDimitry Andric for (const auto &T : MI.tokens()) { 67*0b57cec5SDimitry Andric if (T.hasLeadingSpace()) 68*0b57cec5SDimitry Andric OS << ' '; 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric OS << PP.getSpelling(T, SpellingBuffer); 71*0b57cec5SDimitry Andric } 72*0b57cec5SDimitry Andric } 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 75*0b57cec5SDimitry Andric // Preprocessed token printer 76*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric namespace { 79*0b57cec5SDimitry Andric class PrintPPOutputPPCallbacks : public PPCallbacks { 80*0b57cec5SDimitry Andric Preprocessor &PP; 81*0b57cec5SDimitry Andric SourceManager &SM; 82*0b57cec5SDimitry Andric TokenConcatenation ConcatInfo; 83*0b57cec5SDimitry Andric public: 84*0b57cec5SDimitry Andric raw_ostream &OS; 85*0b57cec5SDimitry Andric private: 86*0b57cec5SDimitry Andric unsigned CurLine; 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric bool EmittedTokensOnThisLine; 89*0b57cec5SDimitry Andric bool EmittedDirectiveOnThisLine; 90*0b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType; 91*0b57cec5SDimitry Andric SmallString<512> CurFilename; 92*0b57cec5SDimitry Andric bool Initialized; 93*0b57cec5SDimitry Andric bool DisableLineMarkers; 94*0b57cec5SDimitry Andric bool DumpDefines; 95*0b57cec5SDimitry Andric bool DumpIncludeDirectives; 96*0b57cec5SDimitry Andric bool UseLineDirectives; 97*0b57cec5SDimitry Andric bool IsFirstFileEntered; 98*0b57cec5SDimitry Andric public: 99*0b57cec5SDimitry Andric PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers, 100*0b57cec5SDimitry Andric bool defines, bool DumpIncludeDirectives, 101*0b57cec5SDimitry Andric bool UseLineDirectives) 102*0b57cec5SDimitry Andric : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os), 103*0b57cec5SDimitry Andric DisableLineMarkers(lineMarkers), DumpDefines(defines), 104*0b57cec5SDimitry Andric DumpIncludeDirectives(DumpIncludeDirectives), 105*0b57cec5SDimitry Andric UseLineDirectives(UseLineDirectives) { 106*0b57cec5SDimitry Andric CurLine = 0; 107*0b57cec5SDimitry Andric CurFilename += "<uninit>"; 108*0b57cec5SDimitry Andric EmittedTokensOnThisLine = false; 109*0b57cec5SDimitry Andric EmittedDirectiveOnThisLine = false; 110*0b57cec5SDimitry Andric FileType = SrcMgr::C_User; 111*0b57cec5SDimitry Andric Initialized = false; 112*0b57cec5SDimitry Andric IsFirstFileEntered = false; 113*0b57cec5SDimitry Andric } 114*0b57cec5SDimitry Andric 115*0b57cec5SDimitry Andric void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } 116*0b57cec5SDimitry Andric bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; } 119*0b57cec5SDimitry Andric bool hasEmittedDirectiveOnThisLine() const { 120*0b57cec5SDimitry Andric return EmittedDirectiveOnThisLine; 121*0b57cec5SDimitry Andric } 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric bool startNewLineIfNeeded(bool ShouldUpdateCurrentLine = true); 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric void FileChanged(SourceLocation Loc, FileChangeReason Reason, 126*0b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType, 127*0b57cec5SDimitry Andric FileID PrevFID) override; 128*0b57cec5SDimitry Andric void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, 129*0b57cec5SDimitry Andric StringRef FileName, bool IsAngled, 130*0b57cec5SDimitry Andric CharSourceRange FilenameRange, const FileEntry *File, 131*0b57cec5SDimitry Andric StringRef SearchPath, StringRef RelativePath, 132*0b57cec5SDimitry Andric const Module *Imported, 133*0b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType) override; 134*0b57cec5SDimitry Andric void Ident(SourceLocation Loc, StringRef str) override; 135*0b57cec5SDimitry Andric void PragmaMessage(SourceLocation Loc, StringRef Namespace, 136*0b57cec5SDimitry Andric PragmaMessageKind Kind, StringRef Str) override; 137*0b57cec5SDimitry Andric void PragmaDebug(SourceLocation Loc, StringRef DebugType) override; 138*0b57cec5SDimitry Andric void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override; 139*0b57cec5SDimitry Andric void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override; 140*0b57cec5SDimitry Andric void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 141*0b57cec5SDimitry Andric diag::Severity Map, StringRef Str) override; 142*0b57cec5SDimitry Andric void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, 143*0b57cec5SDimitry Andric ArrayRef<int> Ids) override; 144*0b57cec5SDimitry Andric void PragmaWarningPush(SourceLocation Loc, int Level) override; 145*0b57cec5SDimitry Andric void PragmaWarningPop(SourceLocation Loc) override; 146*0b57cec5SDimitry Andric void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override; 147*0b57cec5SDimitry Andric void PragmaExecCharsetPop(SourceLocation Loc) override; 148*0b57cec5SDimitry Andric void PragmaAssumeNonNullBegin(SourceLocation Loc) override; 149*0b57cec5SDimitry Andric void PragmaAssumeNonNullEnd(SourceLocation Loc) override; 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric bool HandleFirstTokOnLine(Token &Tok); 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric /// Move to the line of the provided source location. This will 154*0b57cec5SDimitry Andric /// return true if the output stream required adjustment or if 155*0b57cec5SDimitry Andric /// the requested location is on the first line. 156*0b57cec5SDimitry Andric bool MoveToLine(SourceLocation Loc) { 157*0b57cec5SDimitry Andric PresumedLoc PLoc = SM.getPresumedLoc(Loc); 158*0b57cec5SDimitry Andric if (PLoc.isInvalid()) 159*0b57cec5SDimitry Andric return false; 160*0b57cec5SDimitry Andric return MoveToLine(PLoc.getLine()) || (PLoc.getLine() == 1); 161*0b57cec5SDimitry Andric } 162*0b57cec5SDimitry Andric bool MoveToLine(unsigned LineNo); 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, 165*0b57cec5SDimitry Andric const Token &Tok) { 166*0b57cec5SDimitry Andric return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok); 167*0b57cec5SDimitry Andric } 168*0b57cec5SDimitry Andric void WriteLineInfo(unsigned LineNo, const char *Extra=nullptr, 169*0b57cec5SDimitry Andric unsigned ExtraLen=0); 170*0b57cec5SDimitry Andric bool LineMarkersAreDisabled() const { return DisableLineMarkers; } 171*0b57cec5SDimitry Andric void HandleNewlinesInToken(const char *TokStr, unsigned Len); 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric /// MacroDefined - This hook is called whenever a macro definition is seen. 174*0b57cec5SDimitry Andric void MacroDefined(const Token &MacroNameTok, 175*0b57cec5SDimitry Andric const MacroDirective *MD) override; 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric /// MacroUndefined - This hook is called whenever a macro #undef is seen. 178*0b57cec5SDimitry Andric void MacroUndefined(const Token &MacroNameTok, 179*0b57cec5SDimitry Andric const MacroDefinition &MD, 180*0b57cec5SDimitry Andric const MacroDirective *Undef) override; 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric void BeginModule(const Module *M); 183*0b57cec5SDimitry Andric void EndModule(const Module *M); 184*0b57cec5SDimitry Andric }; 185*0b57cec5SDimitry Andric } // end anonymous namespace 186*0b57cec5SDimitry Andric 187*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, 188*0b57cec5SDimitry Andric const char *Extra, 189*0b57cec5SDimitry Andric unsigned ExtraLen) { 190*0b57cec5SDimitry Andric startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 191*0b57cec5SDimitry Andric 192*0b57cec5SDimitry Andric // Emit #line directives or GNU line markers depending on what mode we're in. 193*0b57cec5SDimitry Andric if (UseLineDirectives) { 194*0b57cec5SDimitry Andric OS << "#line" << ' ' << LineNo << ' ' << '"'; 195*0b57cec5SDimitry Andric OS.write_escaped(CurFilename); 196*0b57cec5SDimitry Andric OS << '"'; 197*0b57cec5SDimitry Andric } else { 198*0b57cec5SDimitry Andric OS << '#' << ' ' << LineNo << ' ' << '"'; 199*0b57cec5SDimitry Andric OS.write_escaped(CurFilename); 200*0b57cec5SDimitry Andric OS << '"'; 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric if (ExtraLen) 203*0b57cec5SDimitry Andric OS.write(Extra, ExtraLen); 204*0b57cec5SDimitry Andric 205*0b57cec5SDimitry Andric if (FileType == SrcMgr::C_System) 206*0b57cec5SDimitry Andric OS.write(" 3", 2); 207*0b57cec5SDimitry Andric else if (FileType == SrcMgr::C_ExternCSystem) 208*0b57cec5SDimitry Andric OS.write(" 3 4", 4); 209*0b57cec5SDimitry Andric } 210*0b57cec5SDimitry Andric OS << '\n'; 211*0b57cec5SDimitry Andric } 212*0b57cec5SDimitry Andric 213*0b57cec5SDimitry Andric /// MoveToLine - Move the output to the source line specified by the location 214*0b57cec5SDimitry Andric /// object. We can do this by emitting some number of \n's, or be emitting a 215*0b57cec5SDimitry Andric /// #line directive. This returns false if already at the specified line, true 216*0b57cec5SDimitry Andric /// if some newlines were emitted. 217*0b57cec5SDimitry Andric bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) { 218*0b57cec5SDimitry Andric // If this line is "close enough" to the original line, just print newlines, 219*0b57cec5SDimitry Andric // otherwise print a #line directive. 220*0b57cec5SDimitry Andric if (LineNo-CurLine <= 8) { 221*0b57cec5SDimitry Andric if (LineNo-CurLine == 1) 222*0b57cec5SDimitry Andric OS << '\n'; 223*0b57cec5SDimitry Andric else if (LineNo == CurLine) 224*0b57cec5SDimitry Andric return false; // Spelling line moved, but expansion line didn't. 225*0b57cec5SDimitry Andric else { 226*0b57cec5SDimitry Andric const char *NewLines = "\n\n\n\n\n\n\n\n"; 227*0b57cec5SDimitry Andric OS.write(NewLines, LineNo-CurLine); 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric } else if (!DisableLineMarkers) { 230*0b57cec5SDimitry Andric // Emit a #line or line marker. 231*0b57cec5SDimitry Andric WriteLineInfo(LineNo, nullptr, 0); 232*0b57cec5SDimitry Andric } else { 233*0b57cec5SDimitry Andric // Okay, we're in -P mode, which turns off line markers. However, we still 234*0b57cec5SDimitry Andric // need to emit a newline between tokens on different lines. 235*0b57cec5SDimitry Andric startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 236*0b57cec5SDimitry Andric } 237*0b57cec5SDimitry Andric 238*0b57cec5SDimitry Andric CurLine = LineNo; 239*0b57cec5SDimitry Andric return true; 240*0b57cec5SDimitry Andric } 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric bool 243*0b57cec5SDimitry Andric PrintPPOutputPPCallbacks::startNewLineIfNeeded(bool ShouldUpdateCurrentLine) { 244*0b57cec5SDimitry Andric if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) { 245*0b57cec5SDimitry Andric OS << '\n'; 246*0b57cec5SDimitry Andric EmittedTokensOnThisLine = false; 247*0b57cec5SDimitry Andric EmittedDirectiveOnThisLine = false; 248*0b57cec5SDimitry Andric if (ShouldUpdateCurrentLine) 249*0b57cec5SDimitry Andric ++CurLine; 250*0b57cec5SDimitry Andric return true; 251*0b57cec5SDimitry Andric } 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric return false; 254*0b57cec5SDimitry Andric } 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric /// FileChanged - Whenever the preprocessor enters or exits a #include file 257*0b57cec5SDimitry Andric /// it invokes this handler. Update our conception of the current source 258*0b57cec5SDimitry Andric /// position. 259*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, 260*0b57cec5SDimitry Andric FileChangeReason Reason, 261*0b57cec5SDimitry Andric SrcMgr::CharacteristicKind NewFileType, 262*0b57cec5SDimitry Andric FileID PrevFID) { 263*0b57cec5SDimitry Andric // Unless we are exiting a #include, make sure to skip ahead to the line the 264*0b57cec5SDimitry Andric // #include directive was at. 265*0b57cec5SDimitry Andric SourceManager &SourceMgr = SM; 266*0b57cec5SDimitry Andric 267*0b57cec5SDimitry Andric PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); 268*0b57cec5SDimitry Andric if (UserLoc.isInvalid()) 269*0b57cec5SDimitry Andric return; 270*0b57cec5SDimitry Andric 271*0b57cec5SDimitry Andric unsigned NewLine = UserLoc.getLine(); 272*0b57cec5SDimitry Andric 273*0b57cec5SDimitry Andric if (Reason == PPCallbacks::EnterFile) { 274*0b57cec5SDimitry Andric SourceLocation IncludeLoc = UserLoc.getIncludeLoc(); 275*0b57cec5SDimitry Andric if (IncludeLoc.isValid()) 276*0b57cec5SDimitry Andric MoveToLine(IncludeLoc); 277*0b57cec5SDimitry Andric } else if (Reason == PPCallbacks::SystemHeaderPragma) { 278*0b57cec5SDimitry Andric // GCC emits the # directive for this directive on the line AFTER the 279*0b57cec5SDimitry Andric // directive and emits a bunch of spaces that aren't needed. This is because 280*0b57cec5SDimitry Andric // otherwise we will emit a line marker for THIS line, which requires an 281*0b57cec5SDimitry Andric // extra blank line after the directive to avoid making all following lines 282*0b57cec5SDimitry Andric // off by one. We can do better by simply incrementing NewLine here. 283*0b57cec5SDimitry Andric NewLine += 1; 284*0b57cec5SDimitry Andric } 285*0b57cec5SDimitry Andric 286*0b57cec5SDimitry Andric CurLine = NewLine; 287*0b57cec5SDimitry Andric 288*0b57cec5SDimitry Andric CurFilename.clear(); 289*0b57cec5SDimitry Andric CurFilename += UserLoc.getFilename(); 290*0b57cec5SDimitry Andric FileType = NewFileType; 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric if (DisableLineMarkers) { 293*0b57cec5SDimitry Andric startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 294*0b57cec5SDimitry Andric return; 295*0b57cec5SDimitry Andric } 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric if (!Initialized) { 298*0b57cec5SDimitry Andric WriteLineInfo(CurLine); 299*0b57cec5SDimitry Andric Initialized = true; 300*0b57cec5SDimitry Andric } 301*0b57cec5SDimitry Andric 302*0b57cec5SDimitry Andric // Do not emit an enter marker for the main file (which we expect is the first 303*0b57cec5SDimitry Andric // entered file). This matches gcc, and improves compatibility with some tools 304*0b57cec5SDimitry Andric // which track the # line markers as a way to determine when the preprocessed 305*0b57cec5SDimitry Andric // output is in the context of the main file. 306*0b57cec5SDimitry Andric if (Reason == PPCallbacks::EnterFile && !IsFirstFileEntered) { 307*0b57cec5SDimitry Andric IsFirstFileEntered = true; 308*0b57cec5SDimitry Andric return; 309*0b57cec5SDimitry Andric } 310*0b57cec5SDimitry Andric 311*0b57cec5SDimitry Andric switch (Reason) { 312*0b57cec5SDimitry Andric case PPCallbacks::EnterFile: 313*0b57cec5SDimitry Andric WriteLineInfo(CurLine, " 1", 2); 314*0b57cec5SDimitry Andric break; 315*0b57cec5SDimitry Andric case PPCallbacks::ExitFile: 316*0b57cec5SDimitry Andric WriteLineInfo(CurLine, " 2", 2); 317*0b57cec5SDimitry Andric break; 318*0b57cec5SDimitry Andric case PPCallbacks::SystemHeaderPragma: 319*0b57cec5SDimitry Andric case PPCallbacks::RenameFile: 320*0b57cec5SDimitry Andric WriteLineInfo(CurLine); 321*0b57cec5SDimitry Andric break; 322*0b57cec5SDimitry Andric } 323*0b57cec5SDimitry Andric } 324*0b57cec5SDimitry Andric 325*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::InclusionDirective( 326*0b57cec5SDimitry Andric SourceLocation HashLoc, 327*0b57cec5SDimitry Andric const Token &IncludeTok, 328*0b57cec5SDimitry Andric StringRef FileName, 329*0b57cec5SDimitry Andric bool IsAngled, 330*0b57cec5SDimitry Andric CharSourceRange FilenameRange, 331*0b57cec5SDimitry Andric const FileEntry *File, 332*0b57cec5SDimitry Andric StringRef SearchPath, 333*0b57cec5SDimitry Andric StringRef RelativePath, 334*0b57cec5SDimitry Andric const Module *Imported, 335*0b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType) { 336*0b57cec5SDimitry Andric // In -dI mode, dump #include directives prior to dumping their content or 337*0b57cec5SDimitry Andric // interpretation. 338*0b57cec5SDimitry Andric if (DumpIncludeDirectives) { 339*0b57cec5SDimitry Andric startNewLineIfNeeded(); 340*0b57cec5SDimitry Andric MoveToLine(HashLoc); 341*0b57cec5SDimitry Andric const std::string TokenText = PP.getSpelling(IncludeTok); 342*0b57cec5SDimitry Andric assert(!TokenText.empty()); 343*0b57cec5SDimitry Andric OS << "#" << TokenText << " " 344*0b57cec5SDimitry Andric << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') 345*0b57cec5SDimitry Andric << " /* clang -E -dI */"; 346*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 347*0b57cec5SDimitry Andric startNewLineIfNeeded(); 348*0b57cec5SDimitry Andric } 349*0b57cec5SDimitry Andric 350*0b57cec5SDimitry Andric // When preprocessing, turn implicit imports into module import pragmas. 351*0b57cec5SDimitry Andric if (Imported) { 352*0b57cec5SDimitry Andric switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { 353*0b57cec5SDimitry Andric case tok::pp_include: 354*0b57cec5SDimitry Andric case tok::pp_import: 355*0b57cec5SDimitry Andric case tok::pp_include_next: 356*0b57cec5SDimitry Andric startNewLineIfNeeded(); 357*0b57cec5SDimitry Andric MoveToLine(HashLoc); 358*0b57cec5SDimitry Andric OS << "#pragma clang module import " << Imported->getFullModuleName(true) 359*0b57cec5SDimitry Andric << " /* clang -E: implicit import for " 360*0b57cec5SDimitry Andric << "#" << PP.getSpelling(IncludeTok) << " " 361*0b57cec5SDimitry Andric << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') 362*0b57cec5SDimitry Andric << " */"; 363*0b57cec5SDimitry Andric // Since we want a newline after the pragma, but not a #<line>, start a 364*0b57cec5SDimitry Andric // new line immediately. 365*0b57cec5SDimitry Andric EmittedTokensOnThisLine = true; 366*0b57cec5SDimitry Andric startNewLineIfNeeded(); 367*0b57cec5SDimitry Andric break; 368*0b57cec5SDimitry Andric 369*0b57cec5SDimitry Andric case tok::pp___include_macros: 370*0b57cec5SDimitry Andric // #__include_macros has no effect on a user of a preprocessed source 371*0b57cec5SDimitry Andric // file; the only effect is on preprocessing. 372*0b57cec5SDimitry Andric // 373*0b57cec5SDimitry Andric // FIXME: That's not *quite* true: it causes the module in question to 374*0b57cec5SDimitry Andric // be loaded, which can affect downstream diagnostics. 375*0b57cec5SDimitry Andric break; 376*0b57cec5SDimitry Andric 377*0b57cec5SDimitry Andric default: 378*0b57cec5SDimitry Andric llvm_unreachable("unknown include directive kind"); 379*0b57cec5SDimitry Andric break; 380*0b57cec5SDimitry Andric } 381*0b57cec5SDimitry Andric } 382*0b57cec5SDimitry Andric } 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric /// Handle entering the scope of a module during a module compilation. 385*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::BeginModule(const Module *M) { 386*0b57cec5SDimitry Andric startNewLineIfNeeded(); 387*0b57cec5SDimitry Andric OS << "#pragma clang module begin " << M->getFullModuleName(true); 388*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 389*0b57cec5SDimitry Andric } 390*0b57cec5SDimitry Andric 391*0b57cec5SDimitry Andric /// Handle leaving the scope of a module during a module compilation. 392*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::EndModule(const Module *M) { 393*0b57cec5SDimitry Andric startNewLineIfNeeded(); 394*0b57cec5SDimitry Andric OS << "#pragma clang module end /*" << M->getFullModuleName(true) << "*/"; 395*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 396*0b57cec5SDimitry Andric } 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric /// Ident - Handle #ident directives when read by the preprocessor. 399*0b57cec5SDimitry Andric /// 400*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) { 401*0b57cec5SDimitry Andric MoveToLine(Loc); 402*0b57cec5SDimitry Andric 403*0b57cec5SDimitry Andric OS.write("#ident ", strlen("#ident ")); 404*0b57cec5SDimitry Andric OS.write(S.begin(), S.size()); 405*0b57cec5SDimitry Andric EmittedTokensOnThisLine = true; 406*0b57cec5SDimitry Andric } 407*0b57cec5SDimitry Andric 408*0b57cec5SDimitry Andric /// MacroDefined - This hook is called whenever a macro definition is seen. 409*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, 410*0b57cec5SDimitry Andric const MacroDirective *MD) { 411*0b57cec5SDimitry Andric const MacroInfo *MI = MD->getMacroInfo(); 412*0b57cec5SDimitry Andric // Only print out macro definitions in -dD mode. 413*0b57cec5SDimitry Andric if (!DumpDefines || 414*0b57cec5SDimitry Andric // Ignore __FILE__ etc. 415*0b57cec5SDimitry Andric MI->isBuiltinMacro()) return; 416*0b57cec5SDimitry Andric 417*0b57cec5SDimitry Andric MoveToLine(MI->getDefinitionLoc()); 418*0b57cec5SDimitry Andric PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS); 419*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 420*0b57cec5SDimitry Andric } 421*0b57cec5SDimitry Andric 422*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, 423*0b57cec5SDimitry Andric const MacroDefinition &MD, 424*0b57cec5SDimitry Andric const MacroDirective *Undef) { 425*0b57cec5SDimitry Andric // Only print out macro definitions in -dD mode. 426*0b57cec5SDimitry Andric if (!DumpDefines) return; 427*0b57cec5SDimitry Andric 428*0b57cec5SDimitry Andric MoveToLine(MacroNameTok.getLocation()); 429*0b57cec5SDimitry Andric OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName(); 430*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 431*0b57cec5SDimitry Andric } 432*0b57cec5SDimitry Andric 433*0b57cec5SDimitry Andric static void outputPrintable(raw_ostream &OS, StringRef Str) { 434*0b57cec5SDimitry Andric for (unsigned char Char : Str) { 435*0b57cec5SDimitry Andric if (isPrintable(Char) && Char != '\\' && Char != '"') 436*0b57cec5SDimitry Andric OS << (char)Char; 437*0b57cec5SDimitry Andric else // Output anything hard as an octal escape. 438*0b57cec5SDimitry Andric OS << '\\' 439*0b57cec5SDimitry Andric << (char)('0' + ((Char >> 6) & 7)) 440*0b57cec5SDimitry Andric << (char)('0' + ((Char >> 3) & 7)) 441*0b57cec5SDimitry Andric << (char)('0' + ((Char >> 0) & 7)); 442*0b57cec5SDimitry Andric } 443*0b57cec5SDimitry Andric } 444*0b57cec5SDimitry Andric 445*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, 446*0b57cec5SDimitry Andric StringRef Namespace, 447*0b57cec5SDimitry Andric PragmaMessageKind Kind, 448*0b57cec5SDimitry Andric StringRef Str) { 449*0b57cec5SDimitry Andric startNewLineIfNeeded(); 450*0b57cec5SDimitry Andric MoveToLine(Loc); 451*0b57cec5SDimitry Andric OS << "#pragma "; 452*0b57cec5SDimitry Andric if (!Namespace.empty()) 453*0b57cec5SDimitry Andric OS << Namespace << ' '; 454*0b57cec5SDimitry Andric switch (Kind) { 455*0b57cec5SDimitry Andric case PMK_Message: 456*0b57cec5SDimitry Andric OS << "message(\""; 457*0b57cec5SDimitry Andric break; 458*0b57cec5SDimitry Andric case PMK_Warning: 459*0b57cec5SDimitry Andric OS << "warning \""; 460*0b57cec5SDimitry Andric break; 461*0b57cec5SDimitry Andric case PMK_Error: 462*0b57cec5SDimitry Andric OS << "error \""; 463*0b57cec5SDimitry Andric break; 464*0b57cec5SDimitry Andric } 465*0b57cec5SDimitry Andric 466*0b57cec5SDimitry Andric outputPrintable(OS, Str); 467*0b57cec5SDimitry Andric OS << '"'; 468*0b57cec5SDimitry Andric if (Kind == PMK_Message) 469*0b57cec5SDimitry Andric OS << ')'; 470*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 471*0b57cec5SDimitry Andric } 472*0b57cec5SDimitry Andric 473*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc, 474*0b57cec5SDimitry Andric StringRef DebugType) { 475*0b57cec5SDimitry Andric startNewLineIfNeeded(); 476*0b57cec5SDimitry Andric MoveToLine(Loc); 477*0b57cec5SDimitry Andric 478*0b57cec5SDimitry Andric OS << "#pragma clang __debug "; 479*0b57cec5SDimitry Andric OS << DebugType; 480*0b57cec5SDimitry Andric 481*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 482*0b57cec5SDimitry Andric } 483*0b57cec5SDimitry Andric 484*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 485*0b57cec5SDimitry Andric PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { 486*0b57cec5SDimitry Andric startNewLineIfNeeded(); 487*0b57cec5SDimitry Andric MoveToLine(Loc); 488*0b57cec5SDimitry Andric OS << "#pragma " << Namespace << " diagnostic push"; 489*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 490*0b57cec5SDimitry Andric } 491*0b57cec5SDimitry Andric 492*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 493*0b57cec5SDimitry Andric PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { 494*0b57cec5SDimitry Andric startNewLineIfNeeded(); 495*0b57cec5SDimitry Andric MoveToLine(Loc); 496*0b57cec5SDimitry Andric OS << "#pragma " << Namespace << " diagnostic pop"; 497*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 498*0b57cec5SDimitry Andric } 499*0b57cec5SDimitry Andric 500*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc, 501*0b57cec5SDimitry Andric StringRef Namespace, 502*0b57cec5SDimitry Andric diag::Severity Map, 503*0b57cec5SDimitry Andric StringRef Str) { 504*0b57cec5SDimitry Andric startNewLineIfNeeded(); 505*0b57cec5SDimitry Andric MoveToLine(Loc); 506*0b57cec5SDimitry Andric OS << "#pragma " << Namespace << " diagnostic "; 507*0b57cec5SDimitry Andric switch (Map) { 508*0b57cec5SDimitry Andric case diag::Severity::Remark: 509*0b57cec5SDimitry Andric OS << "remark"; 510*0b57cec5SDimitry Andric break; 511*0b57cec5SDimitry Andric case diag::Severity::Warning: 512*0b57cec5SDimitry Andric OS << "warning"; 513*0b57cec5SDimitry Andric break; 514*0b57cec5SDimitry Andric case diag::Severity::Error: 515*0b57cec5SDimitry Andric OS << "error"; 516*0b57cec5SDimitry Andric break; 517*0b57cec5SDimitry Andric case diag::Severity::Ignored: 518*0b57cec5SDimitry Andric OS << "ignored"; 519*0b57cec5SDimitry Andric break; 520*0b57cec5SDimitry Andric case diag::Severity::Fatal: 521*0b57cec5SDimitry Andric OS << "fatal"; 522*0b57cec5SDimitry Andric break; 523*0b57cec5SDimitry Andric } 524*0b57cec5SDimitry Andric OS << " \"" << Str << '"'; 525*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 526*0b57cec5SDimitry Andric } 527*0b57cec5SDimitry Andric 528*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc, 529*0b57cec5SDimitry Andric StringRef WarningSpec, 530*0b57cec5SDimitry Andric ArrayRef<int> Ids) { 531*0b57cec5SDimitry Andric startNewLineIfNeeded(); 532*0b57cec5SDimitry Andric MoveToLine(Loc); 533*0b57cec5SDimitry Andric OS << "#pragma warning(" << WarningSpec << ':'; 534*0b57cec5SDimitry Andric for (ArrayRef<int>::iterator I = Ids.begin(), E = Ids.end(); I != E; ++I) 535*0b57cec5SDimitry Andric OS << ' ' << *I; 536*0b57cec5SDimitry Andric OS << ')'; 537*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 538*0b57cec5SDimitry Andric } 539*0b57cec5SDimitry Andric 540*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc, 541*0b57cec5SDimitry Andric int Level) { 542*0b57cec5SDimitry Andric startNewLineIfNeeded(); 543*0b57cec5SDimitry Andric MoveToLine(Loc); 544*0b57cec5SDimitry Andric OS << "#pragma warning(push"; 545*0b57cec5SDimitry Andric if (Level >= 0) 546*0b57cec5SDimitry Andric OS << ", " << Level; 547*0b57cec5SDimitry Andric OS << ')'; 548*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 549*0b57cec5SDimitry Andric } 550*0b57cec5SDimitry Andric 551*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { 552*0b57cec5SDimitry Andric startNewLineIfNeeded(); 553*0b57cec5SDimitry Andric MoveToLine(Loc); 554*0b57cec5SDimitry Andric OS << "#pragma warning(pop)"; 555*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 556*0b57cec5SDimitry Andric } 557*0b57cec5SDimitry Andric 558*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc, 559*0b57cec5SDimitry Andric StringRef Str) { 560*0b57cec5SDimitry Andric startNewLineIfNeeded(); 561*0b57cec5SDimitry Andric MoveToLine(Loc); 562*0b57cec5SDimitry Andric OS << "#pragma character_execution_set(push"; 563*0b57cec5SDimitry Andric if (!Str.empty()) 564*0b57cec5SDimitry Andric OS << ", " << Str; 565*0b57cec5SDimitry Andric OS << ')'; 566*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 567*0b57cec5SDimitry Andric } 568*0b57cec5SDimitry Andric 569*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaExecCharsetPop(SourceLocation Loc) { 570*0b57cec5SDimitry Andric startNewLineIfNeeded(); 571*0b57cec5SDimitry Andric MoveToLine(Loc); 572*0b57cec5SDimitry Andric OS << "#pragma character_execution_set(pop)"; 573*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 574*0b57cec5SDimitry Andric } 575*0b57cec5SDimitry Andric 576*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 577*0b57cec5SDimitry Andric PragmaAssumeNonNullBegin(SourceLocation Loc) { 578*0b57cec5SDimitry Andric startNewLineIfNeeded(); 579*0b57cec5SDimitry Andric MoveToLine(Loc); 580*0b57cec5SDimitry Andric OS << "#pragma clang assume_nonnull begin"; 581*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 582*0b57cec5SDimitry Andric } 583*0b57cec5SDimitry Andric 584*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 585*0b57cec5SDimitry Andric PragmaAssumeNonNullEnd(SourceLocation Loc) { 586*0b57cec5SDimitry Andric startNewLineIfNeeded(); 587*0b57cec5SDimitry Andric MoveToLine(Loc); 588*0b57cec5SDimitry Andric OS << "#pragma clang assume_nonnull end"; 589*0b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 590*0b57cec5SDimitry Andric } 591*0b57cec5SDimitry Andric 592*0b57cec5SDimitry Andric /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this 593*0b57cec5SDimitry Andric /// is called for the first token on each new line. If this really is the start 594*0b57cec5SDimitry Andric /// of a new logical line, handle it and return true, otherwise return false. 595*0b57cec5SDimitry Andric /// This may not be the start of a logical line because the "start of line" 596*0b57cec5SDimitry Andric /// marker is set for spelling lines, not expansion ones. 597*0b57cec5SDimitry Andric bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { 598*0b57cec5SDimitry Andric // Figure out what line we went to and insert the appropriate number of 599*0b57cec5SDimitry Andric // newline characters. 600*0b57cec5SDimitry Andric if (!MoveToLine(Tok.getLocation())) 601*0b57cec5SDimitry Andric return false; 602*0b57cec5SDimitry Andric 603*0b57cec5SDimitry Andric // Print out space characters so that the first token on a line is 604*0b57cec5SDimitry Andric // indented for easy reading. 605*0b57cec5SDimitry Andric unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation()); 606*0b57cec5SDimitry Andric 607*0b57cec5SDimitry Andric // The first token on a line can have a column number of 1, yet still expect 608*0b57cec5SDimitry Andric // leading white space, if a macro expansion in column 1 starts with an empty 609*0b57cec5SDimitry Andric // macro argument, or an empty nested macro expansion. In this case, move the 610*0b57cec5SDimitry Andric // token to column 2. 611*0b57cec5SDimitry Andric if (ColNo == 1 && Tok.hasLeadingSpace()) 612*0b57cec5SDimitry Andric ColNo = 2; 613*0b57cec5SDimitry Andric 614*0b57cec5SDimitry Andric // This hack prevents stuff like: 615*0b57cec5SDimitry Andric // #define HASH # 616*0b57cec5SDimitry Andric // HASH define foo bar 617*0b57cec5SDimitry Andric // From having the # character end up at column 1, which makes it so it 618*0b57cec5SDimitry Andric // is not handled as a #define next time through the preprocessor if in 619*0b57cec5SDimitry Andric // -fpreprocessed mode. 620*0b57cec5SDimitry Andric if (ColNo <= 1 && Tok.is(tok::hash)) 621*0b57cec5SDimitry Andric OS << ' '; 622*0b57cec5SDimitry Andric 623*0b57cec5SDimitry Andric // Otherwise, indent the appropriate number of spaces. 624*0b57cec5SDimitry Andric for (; ColNo > 1; --ColNo) 625*0b57cec5SDimitry Andric OS << ' '; 626*0b57cec5SDimitry Andric 627*0b57cec5SDimitry Andric return true; 628*0b57cec5SDimitry Andric } 629*0b57cec5SDimitry Andric 630*0b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr, 631*0b57cec5SDimitry Andric unsigned Len) { 632*0b57cec5SDimitry Andric unsigned NumNewlines = 0; 633*0b57cec5SDimitry Andric for (; Len; --Len, ++TokStr) { 634*0b57cec5SDimitry Andric if (*TokStr != '\n' && 635*0b57cec5SDimitry Andric *TokStr != '\r') 636*0b57cec5SDimitry Andric continue; 637*0b57cec5SDimitry Andric 638*0b57cec5SDimitry Andric ++NumNewlines; 639*0b57cec5SDimitry Andric 640*0b57cec5SDimitry Andric // If we have \n\r or \r\n, skip both and count as one line. 641*0b57cec5SDimitry Andric if (Len != 1 && 642*0b57cec5SDimitry Andric (TokStr[1] == '\n' || TokStr[1] == '\r') && 643*0b57cec5SDimitry Andric TokStr[0] != TokStr[1]) { 644*0b57cec5SDimitry Andric ++TokStr; 645*0b57cec5SDimitry Andric --Len; 646*0b57cec5SDimitry Andric } 647*0b57cec5SDimitry Andric } 648*0b57cec5SDimitry Andric 649*0b57cec5SDimitry Andric if (NumNewlines == 0) return; 650*0b57cec5SDimitry Andric 651*0b57cec5SDimitry Andric CurLine += NumNewlines; 652*0b57cec5SDimitry Andric } 653*0b57cec5SDimitry Andric 654*0b57cec5SDimitry Andric 655*0b57cec5SDimitry Andric namespace { 656*0b57cec5SDimitry Andric struct UnknownPragmaHandler : public PragmaHandler { 657*0b57cec5SDimitry Andric const char *Prefix; 658*0b57cec5SDimitry Andric PrintPPOutputPPCallbacks *Callbacks; 659*0b57cec5SDimitry Andric 660*0b57cec5SDimitry Andric // Set to true if tokens should be expanded 661*0b57cec5SDimitry Andric bool ShouldExpandTokens; 662*0b57cec5SDimitry Andric 663*0b57cec5SDimitry Andric UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks, 664*0b57cec5SDimitry Andric bool RequireTokenExpansion) 665*0b57cec5SDimitry Andric : Prefix(prefix), Callbacks(callbacks), 666*0b57cec5SDimitry Andric ShouldExpandTokens(RequireTokenExpansion) {} 667*0b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 668*0b57cec5SDimitry Andric Token &PragmaTok) override { 669*0b57cec5SDimitry Andric // Figure out what line we went to and insert the appropriate number of 670*0b57cec5SDimitry Andric // newline characters. 671*0b57cec5SDimitry Andric Callbacks->startNewLineIfNeeded(); 672*0b57cec5SDimitry Andric Callbacks->MoveToLine(PragmaTok.getLocation()); 673*0b57cec5SDimitry Andric Callbacks->OS.write(Prefix, strlen(Prefix)); 674*0b57cec5SDimitry Andric 675*0b57cec5SDimitry Andric if (ShouldExpandTokens) { 676*0b57cec5SDimitry Andric // The first token does not have expanded macros. Expand them, if 677*0b57cec5SDimitry Andric // required. 678*0b57cec5SDimitry Andric auto Toks = llvm::make_unique<Token[]>(1); 679*0b57cec5SDimitry Andric Toks[0] = PragmaTok; 680*0b57cec5SDimitry Andric PP.EnterTokenStream(std::move(Toks), /*NumToks=*/1, 681*0b57cec5SDimitry Andric /*DisableMacroExpansion=*/false, 682*0b57cec5SDimitry Andric /*IsReinject=*/false); 683*0b57cec5SDimitry Andric PP.Lex(PragmaTok); 684*0b57cec5SDimitry Andric } 685*0b57cec5SDimitry Andric Token PrevToken; 686*0b57cec5SDimitry Andric Token PrevPrevToken; 687*0b57cec5SDimitry Andric PrevToken.startToken(); 688*0b57cec5SDimitry Andric PrevPrevToken.startToken(); 689*0b57cec5SDimitry Andric 690*0b57cec5SDimitry Andric // Read and print all of the pragma tokens. 691*0b57cec5SDimitry Andric while (PragmaTok.isNot(tok::eod)) { 692*0b57cec5SDimitry Andric if (PragmaTok.hasLeadingSpace() || 693*0b57cec5SDimitry Andric Callbacks->AvoidConcat(PrevPrevToken, PrevToken, PragmaTok)) 694*0b57cec5SDimitry Andric Callbacks->OS << ' '; 695*0b57cec5SDimitry Andric std::string TokSpell = PP.getSpelling(PragmaTok); 696*0b57cec5SDimitry Andric Callbacks->OS.write(&TokSpell[0], TokSpell.size()); 697*0b57cec5SDimitry Andric 698*0b57cec5SDimitry Andric PrevPrevToken = PrevToken; 699*0b57cec5SDimitry Andric PrevToken = PragmaTok; 700*0b57cec5SDimitry Andric 701*0b57cec5SDimitry Andric if (ShouldExpandTokens) 702*0b57cec5SDimitry Andric PP.Lex(PragmaTok); 703*0b57cec5SDimitry Andric else 704*0b57cec5SDimitry Andric PP.LexUnexpandedToken(PragmaTok); 705*0b57cec5SDimitry Andric } 706*0b57cec5SDimitry Andric Callbacks->setEmittedDirectiveOnThisLine(); 707*0b57cec5SDimitry Andric } 708*0b57cec5SDimitry Andric }; 709*0b57cec5SDimitry Andric } // end anonymous namespace 710*0b57cec5SDimitry Andric 711*0b57cec5SDimitry Andric 712*0b57cec5SDimitry Andric static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, 713*0b57cec5SDimitry Andric PrintPPOutputPPCallbacks *Callbacks, 714*0b57cec5SDimitry Andric raw_ostream &OS) { 715*0b57cec5SDimitry Andric bool DropComments = PP.getLangOpts().TraditionalCPP && 716*0b57cec5SDimitry Andric !PP.getCommentRetentionState(); 717*0b57cec5SDimitry Andric 718*0b57cec5SDimitry Andric char Buffer[256]; 719*0b57cec5SDimitry Andric Token PrevPrevTok, PrevTok; 720*0b57cec5SDimitry Andric PrevPrevTok.startToken(); 721*0b57cec5SDimitry Andric PrevTok.startToken(); 722*0b57cec5SDimitry Andric while (1) { 723*0b57cec5SDimitry Andric if (Callbacks->hasEmittedDirectiveOnThisLine()) { 724*0b57cec5SDimitry Andric Callbacks->startNewLineIfNeeded(); 725*0b57cec5SDimitry Andric Callbacks->MoveToLine(Tok.getLocation()); 726*0b57cec5SDimitry Andric } 727*0b57cec5SDimitry Andric 728*0b57cec5SDimitry Andric // If this token is at the start of a line, emit newlines if needed. 729*0b57cec5SDimitry Andric if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) { 730*0b57cec5SDimitry Andric // done. 731*0b57cec5SDimitry Andric } else if (Tok.hasLeadingSpace() || 732*0b57cec5SDimitry Andric // If we haven't emitted a token on this line yet, PrevTok isn't 733*0b57cec5SDimitry Andric // useful to look at and no concatenation could happen anyway. 734*0b57cec5SDimitry Andric (Callbacks->hasEmittedTokensOnThisLine() && 735*0b57cec5SDimitry Andric // Don't print "-" next to "-", it would form "--". 736*0b57cec5SDimitry Andric Callbacks->AvoidConcat(PrevPrevTok, PrevTok, Tok))) { 737*0b57cec5SDimitry Andric OS << ' '; 738*0b57cec5SDimitry Andric } 739*0b57cec5SDimitry Andric 740*0b57cec5SDimitry Andric if (DropComments && Tok.is(tok::comment)) { 741*0b57cec5SDimitry Andric // Skip comments. Normally the preprocessor does not generate 742*0b57cec5SDimitry Andric // tok::comment nodes at all when not keeping comments, but under 743*0b57cec5SDimitry Andric // -traditional-cpp the lexer keeps /all/ whitespace, including comments. 744*0b57cec5SDimitry Andric SourceLocation StartLoc = Tok.getLocation(); 745*0b57cec5SDimitry Andric Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength())); 746*0b57cec5SDimitry Andric } else if (Tok.is(tok::eod)) { 747*0b57cec5SDimitry Andric // Don't print end of directive tokens, since they are typically newlines 748*0b57cec5SDimitry Andric // that mess up our line tracking. These come from unknown pre-processor 749*0b57cec5SDimitry Andric // directives or hash-prefixed comments in standalone assembly files. 750*0b57cec5SDimitry Andric PP.Lex(Tok); 751*0b57cec5SDimitry Andric continue; 752*0b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_include)) { 753*0b57cec5SDimitry Andric // PrintPPOutputPPCallbacks::InclusionDirective handles producing 754*0b57cec5SDimitry Andric // appropriate output here. Ignore this token entirely. 755*0b57cec5SDimitry Andric PP.Lex(Tok); 756*0b57cec5SDimitry Andric continue; 757*0b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_begin)) { 758*0b57cec5SDimitry Andric // FIXME: We retrieve this token after the FileChanged callback, and 759*0b57cec5SDimitry Andric // retrieve the module_end token before the FileChanged callback, so 760*0b57cec5SDimitry Andric // we render this within the file and render the module end outside the 761*0b57cec5SDimitry Andric // file, but this is backwards from the token locations: the module_begin 762*0b57cec5SDimitry Andric // token is at the include location (outside the file) and the module_end 763*0b57cec5SDimitry Andric // token is at the EOF location (within the file). 764*0b57cec5SDimitry Andric Callbacks->BeginModule( 765*0b57cec5SDimitry Andric reinterpret_cast<Module *>(Tok.getAnnotationValue())); 766*0b57cec5SDimitry Andric PP.Lex(Tok); 767*0b57cec5SDimitry Andric continue; 768*0b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_end)) { 769*0b57cec5SDimitry Andric Callbacks->EndModule( 770*0b57cec5SDimitry Andric reinterpret_cast<Module *>(Tok.getAnnotationValue())); 771*0b57cec5SDimitry Andric PP.Lex(Tok); 772*0b57cec5SDimitry Andric continue; 773*0b57cec5SDimitry Andric } else if (Tok.is(tok::annot_header_unit)) { 774*0b57cec5SDimitry Andric // This is a header-name that has been (effectively) converted into a 775*0b57cec5SDimitry Andric // module-name. 776*0b57cec5SDimitry Andric // FIXME: The module name could contain non-identifier module name 777*0b57cec5SDimitry Andric // components. We don't have a good way to round-trip those. 778*0b57cec5SDimitry Andric Module *M = reinterpret_cast<Module *>(Tok.getAnnotationValue()); 779*0b57cec5SDimitry Andric std::string Name = M->getFullModuleName(); 780*0b57cec5SDimitry Andric OS.write(Name.data(), Name.size()); 781*0b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(Name.data(), Name.size()); 782*0b57cec5SDimitry Andric } else if (Tok.isAnnotation()) { 783*0b57cec5SDimitry Andric // Ignore annotation tokens created by pragmas - the pragmas themselves 784*0b57cec5SDimitry Andric // will be reproduced in the preprocessed output. 785*0b57cec5SDimitry Andric PP.Lex(Tok); 786*0b57cec5SDimitry Andric continue; 787*0b57cec5SDimitry Andric } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { 788*0b57cec5SDimitry Andric OS << II->getName(); 789*0b57cec5SDimitry Andric } else if (Tok.isLiteral() && !Tok.needsCleaning() && 790*0b57cec5SDimitry Andric Tok.getLiteralData()) { 791*0b57cec5SDimitry Andric OS.write(Tok.getLiteralData(), Tok.getLength()); 792*0b57cec5SDimitry Andric } else if (Tok.getLength() < llvm::array_lengthof(Buffer)) { 793*0b57cec5SDimitry Andric const char *TokPtr = Buffer; 794*0b57cec5SDimitry Andric unsigned Len = PP.getSpelling(Tok, TokPtr); 795*0b57cec5SDimitry Andric OS.write(TokPtr, Len); 796*0b57cec5SDimitry Andric 797*0b57cec5SDimitry Andric // Tokens that can contain embedded newlines need to adjust our current 798*0b57cec5SDimitry Andric // line number. 799*0b57cec5SDimitry Andric if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) 800*0b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(TokPtr, Len); 801*0b57cec5SDimitry Andric } else { 802*0b57cec5SDimitry Andric std::string S = PP.getSpelling(Tok); 803*0b57cec5SDimitry Andric OS.write(S.data(), S.size()); 804*0b57cec5SDimitry Andric 805*0b57cec5SDimitry Andric // Tokens that can contain embedded newlines need to adjust our current 806*0b57cec5SDimitry Andric // line number. 807*0b57cec5SDimitry Andric if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) 808*0b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(S.data(), S.size()); 809*0b57cec5SDimitry Andric } 810*0b57cec5SDimitry Andric Callbacks->setEmittedTokensOnThisLine(); 811*0b57cec5SDimitry Andric 812*0b57cec5SDimitry Andric if (Tok.is(tok::eof)) break; 813*0b57cec5SDimitry Andric 814*0b57cec5SDimitry Andric PrevPrevTok = PrevTok; 815*0b57cec5SDimitry Andric PrevTok = Tok; 816*0b57cec5SDimitry Andric PP.Lex(Tok); 817*0b57cec5SDimitry Andric } 818*0b57cec5SDimitry Andric } 819*0b57cec5SDimitry Andric 820*0b57cec5SDimitry Andric typedef std::pair<const IdentifierInfo *, MacroInfo *> id_macro_pair; 821*0b57cec5SDimitry Andric static int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS) { 822*0b57cec5SDimitry Andric return LHS->first->getName().compare(RHS->first->getName()); 823*0b57cec5SDimitry Andric } 824*0b57cec5SDimitry Andric 825*0b57cec5SDimitry Andric static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) { 826*0b57cec5SDimitry Andric // Ignore unknown pragmas. 827*0b57cec5SDimitry Andric PP.IgnorePragmas(); 828*0b57cec5SDimitry Andric 829*0b57cec5SDimitry Andric // -dM mode just scans and ignores all tokens in the files, then dumps out 830*0b57cec5SDimitry Andric // the macro table at the end. 831*0b57cec5SDimitry Andric PP.EnterMainSourceFile(); 832*0b57cec5SDimitry Andric 833*0b57cec5SDimitry Andric Token Tok; 834*0b57cec5SDimitry Andric do PP.Lex(Tok); 835*0b57cec5SDimitry Andric while (Tok.isNot(tok::eof)); 836*0b57cec5SDimitry Andric 837*0b57cec5SDimitry Andric SmallVector<id_macro_pair, 128> MacrosByID; 838*0b57cec5SDimitry Andric for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); 839*0b57cec5SDimitry Andric I != E; ++I) { 840*0b57cec5SDimitry Andric auto *MD = I->second.getLatest(); 841*0b57cec5SDimitry Andric if (MD && MD->isDefined()) 842*0b57cec5SDimitry Andric MacrosByID.push_back(id_macro_pair(I->first, MD->getMacroInfo())); 843*0b57cec5SDimitry Andric } 844*0b57cec5SDimitry Andric llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare); 845*0b57cec5SDimitry Andric 846*0b57cec5SDimitry Andric for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) { 847*0b57cec5SDimitry Andric MacroInfo &MI = *MacrosByID[i].second; 848*0b57cec5SDimitry Andric // Ignore computed macros like __LINE__ and friends. 849*0b57cec5SDimitry Andric if (MI.isBuiltinMacro()) continue; 850*0b57cec5SDimitry Andric 851*0b57cec5SDimitry Andric PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS); 852*0b57cec5SDimitry Andric *OS << '\n'; 853*0b57cec5SDimitry Andric } 854*0b57cec5SDimitry Andric } 855*0b57cec5SDimitry Andric 856*0b57cec5SDimitry Andric /// DoPrintPreprocessedInput - This implements -E mode. 857*0b57cec5SDimitry Andric /// 858*0b57cec5SDimitry Andric void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, 859*0b57cec5SDimitry Andric const PreprocessorOutputOptions &Opts) { 860*0b57cec5SDimitry Andric // Show macros with no output is handled specially. 861*0b57cec5SDimitry Andric if (!Opts.ShowCPP) { 862*0b57cec5SDimitry Andric assert(Opts.ShowMacros && "Not yet implemented!"); 863*0b57cec5SDimitry Andric DoPrintMacros(PP, OS); 864*0b57cec5SDimitry Andric return; 865*0b57cec5SDimitry Andric } 866*0b57cec5SDimitry Andric 867*0b57cec5SDimitry Andric // Inform the preprocessor whether we want it to retain comments or not, due 868*0b57cec5SDimitry Andric // to -C or -CC. 869*0b57cec5SDimitry Andric PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments); 870*0b57cec5SDimitry Andric 871*0b57cec5SDimitry Andric PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks( 872*0b57cec5SDimitry Andric PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, 873*0b57cec5SDimitry Andric Opts.ShowIncludeDirectives, Opts.UseLineDirectives); 874*0b57cec5SDimitry Andric 875*0b57cec5SDimitry Andric // Expand macros in pragmas with -fms-extensions. The assumption is that 876*0b57cec5SDimitry Andric // the majority of pragmas in such a file will be Microsoft pragmas. 877*0b57cec5SDimitry Andric // Remember the handlers we will add so that we can remove them later. 878*0b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> MicrosoftExtHandler( 879*0b57cec5SDimitry Andric new UnknownPragmaHandler( 880*0b57cec5SDimitry Andric "#pragma", Callbacks, 881*0b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 882*0b57cec5SDimitry Andric 883*0b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> GCCHandler(new UnknownPragmaHandler( 884*0b57cec5SDimitry Andric "#pragma GCC", Callbacks, 885*0b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 886*0b57cec5SDimitry Andric 887*0b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> ClangHandler(new UnknownPragmaHandler( 888*0b57cec5SDimitry Andric "#pragma clang", Callbacks, 889*0b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 890*0b57cec5SDimitry Andric 891*0b57cec5SDimitry Andric PP.AddPragmaHandler(MicrosoftExtHandler.get()); 892*0b57cec5SDimitry Andric PP.AddPragmaHandler("GCC", GCCHandler.get()); 893*0b57cec5SDimitry Andric PP.AddPragmaHandler("clang", ClangHandler.get()); 894*0b57cec5SDimitry Andric 895*0b57cec5SDimitry Andric // The tokens after pragma omp need to be expanded. 896*0b57cec5SDimitry Andric // 897*0b57cec5SDimitry Andric // OpenMP [2.1, Directive format] 898*0b57cec5SDimitry Andric // Preprocessing tokens following the #pragma omp are subject to macro 899*0b57cec5SDimitry Andric // replacement. 900*0b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> OpenMPHandler( 901*0b57cec5SDimitry Andric new UnknownPragmaHandler("#pragma omp", Callbacks, 902*0b57cec5SDimitry Andric /*RequireTokenExpansion=*/true)); 903*0b57cec5SDimitry Andric PP.AddPragmaHandler("omp", OpenMPHandler.get()); 904*0b57cec5SDimitry Andric 905*0b57cec5SDimitry Andric PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks)); 906*0b57cec5SDimitry Andric 907*0b57cec5SDimitry Andric // After we have configured the preprocessor, enter the main file. 908*0b57cec5SDimitry Andric PP.EnterMainSourceFile(); 909*0b57cec5SDimitry Andric 910*0b57cec5SDimitry Andric // Consume all of the tokens that come from the predefines buffer. Those 911*0b57cec5SDimitry Andric // should not be emitted into the output and are guaranteed to be at the 912*0b57cec5SDimitry Andric // start. 913*0b57cec5SDimitry Andric const SourceManager &SourceMgr = PP.getSourceManager(); 914*0b57cec5SDimitry Andric Token Tok; 915*0b57cec5SDimitry Andric do { 916*0b57cec5SDimitry Andric PP.Lex(Tok); 917*0b57cec5SDimitry Andric if (Tok.is(tok::eof) || !Tok.getLocation().isFileID()) 918*0b57cec5SDimitry Andric break; 919*0b57cec5SDimitry Andric 920*0b57cec5SDimitry Andric PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); 921*0b57cec5SDimitry Andric if (PLoc.isInvalid()) 922*0b57cec5SDimitry Andric break; 923*0b57cec5SDimitry Andric 924*0b57cec5SDimitry Andric if (strcmp(PLoc.getFilename(), "<built-in>")) 925*0b57cec5SDimitry Andric break; 926*0b57cec5SDimitry Andric } while (true); 927*0b57cec5SDimitry Andric 928*0b57cec5SDimitry Andric // Read all the preprocessed tokens, printing them out to the stream. 929*0b57cec5SDimitry Andric PrintPreprocessedTokens(PP, Tok, Callbacks, *OS); 930*0b57cec5SDimitry Andric *OS << '\n'; 931*0b57cec5SDimitry Andric 932*0b57cec5SDimitry Andric // Remove the handlers we just added to leave the preprocessor in a sane state 933*0b57cec5SDimitry Andric // so that it can be reused (for example by a clang::Parser instance). 934*0b57cec5SDimitry Andric PP.RemovePragmaHandler(MicrosoftExtHandler.get()); 935*0b57cec5SDimitry Andric PP.RemovePragmaHandler("GCC", GCCHandler.get()); 936*0b57cec5SDimitry Andric PP.RemovePragmaHandler("clang", ClangHandler.get()); 937*0b57cec5SDimitry Andric PP.RemovePragmaHandler("omp", OpenMPHandler.get()); 938*0b57cec5SDimitry Andric } 939