10b57cec5SDimitry Andric //===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This code simply runs the preprocessor on the input file and prints out the 100b57cec5SDimitry Andric // result. This is the traditional behavior of the -E option. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "clang/Frontend/Utils.h" 150b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 160b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 170b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 180b57cec5SDimitry Andric #include "clang/Frontend/PreprocessorOutputOptions.h" 190b57cec5SDimitry Andric #include "clang/Lex/MacroInfo.h" 200b57cec5SDimitry Andric #include "clang/Lex/PPCallbacks.h" 210b57cec5SDimitry Andric #include "clang/Lex/Pragma.h" 220b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 230b57cec5SDimitry Andric #include "clang/Lex/TokenConcatenation.h" 240b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 250b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 260b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 270b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 290b57cec5SDimitry Andric #include <cstdio> 300b57cec5SDimitry Andric using namespace clang; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric /// PrintMacroDefinition - Print a macro definition in a form that will be 330b57cec5SDimitry Andric /// properly accepted back as a definition. 340b57cec5SDimitry Andric static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, 350b57cec5SDimitry Andric Preprocessor &PP, raw_ostream &OS) { 360b57cec5SDimitry Andric OS << "#define " << II.getName(); 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric if (MI.isFunctionLike()) { 390b57cec5SDimitry Andric OS << '('; 400b57cec5SDimitry Andric if (!MI.param_empty()) { 410b57cec5SDimitry Andric MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end(); 420b57cec5SDimitry Andric for (; AI+1 != E; ++AI) { 430b57cec5SDimitry Andric OS << (*AI)->getName(); 440b57cec5SDimitry Andric OS << ','; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric // Last argument. 480b57cec5SDimitry Andric if ((*AI)->getName() == "__VA_ARGS__") 490b57cec5SDimitry Andric OS << "..."; 500b57cec5SDimitry Andric else 510b57cec5SDimitry Andric OS << (*AI)->getName(); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric if (MI.isGNUVarargs()) 550b57cec5SDimitry Andric OS << "..."; // #define foo(x...) 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric OS << ')'; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // GCC always emits a space, even if the macro body is empty. However, do not 610b57cec5SDimitry Andric // want to emit two spaces if the first token has a leading space. 620b57cec5SDimitry Andric if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace()) 630b57cec5SDimitry Andric OS << ' '; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric SmallString<128> SpellingBuffer; 660b57cec5SDimitry Andric for (const auto &T : MI.tokens()) { 670b57cec5SDimitry Andric if (T.hasLeadingSpace()) 680b57cec5SDimitry Andric OS << ' '; 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric OS << PP.getSpelling(T, SpellingBuffer); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 750b57cec5SDimitry Andric // Preprocessed token printer 760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric namespace { 790b57cec5SDimitry Andric class PrintPPOutputPPCallbacks : public PPCallbacks { 800b57cec5SDimitry Andric Preprocessor &PP; 810b57cec5SDimitry Andric SourceManager &SM; 820b57cec5SDimitry Andric TokenConcatenation ConcatInfo; 830b57cec5SDimitry Andric public: 840b57cec5SDimitry Andric raw_ostream &OS; 850b57cec5SDimitry Andric private: 860b57cec5SDimitry Andric unsigned CurLine; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric bool EmittedTokensOnThisLine; 890b57cec5SDimitry Andric bool EmittedDirectiveOnThisLine; 900b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType; 910b57cec5SDimitry Andric SmallString<512> CurFilename; 920b57cec5SDimitry Andric bool Initialized; 930b57cec5SDimitry Andric bool DisableLineMarkers; 940b57cec5SDimitry Andric bool DumpDefines; 950b57cec5SDimitry Andric bool DumpIncludeDirectives; 960b57cec5SDimitry Andric bool UseLineDirectives; 970b57cec5SDimitry Andric bool IsFirstFileEntered; 980b57cec5SDimitry Andric public: 990b57cec5SDimitry Andric PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers, 1000b57cec5SDimitry Andric bool defines, bool DumpIncludeDirectives, 1010b57cec5SDimitry Andric bool UseLineDirectives) 1020b57cec5SDimitry Andric : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os), 1030b57cec5SDimitry Andric DisableLineMarkers(lineMarkers), DumpDefines(defines), 1040b57cec5SDimitry Andric DumpIncludeDirectives(DumpIncludeDirectives), 1050b57cec5SDimitry Andric UseLineDirectives(UseLineDirectives) { 1060b57cec5SDimitry Andric CurLine = 0; 1070b57cec5SDimitry Andric CurFilename += "<uninit>"; 1080b57cec5SDimitry Andric EmittedTokensOnThisLine = false; 1090b57cec5SDimitry Andric EmittedDirectiveOnThisLine = false; 1100b57cec5SDimitry Andric FileType = SrcMgr::C_User; 1110b57cec5SDimitry Andric Initialized = false; 1120b57cec5SDimitry Andric IsFirstFileEntered = false; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } 1160b57cec5SDimitry Andric bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; } 1190b57cec5SDimitry Andric bool hasEmittedDirectiveOnThisLine() const { 1200b57cec5SDimitry Andric return EmittedDirectiveOnThisLine; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric bool startNewLineIfNeeded(bool ShouldUpdateCurrentLine = true); 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric void FileChanged(SourceLocation Loc, FileChangeReason Reason, 1260b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType, 1270b57cec5SDimitry Andric FileID PrevFID) override; 1280b57cec5SDimitry Andric void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, 1290b57cec5SDimitry Andric StringRef FileName, bool IsAngled, 1300b57cec5SDimitry Andric CharSourceRange FilenameRange, const FileEntry *File, 1310b57cec5SDimitry Andric StringRef SearchPath, StringRef RelativePath, 1320b57cec5SDimitry Andric const Module *Imported, 1330b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType) override; 1340b57cec5SDimitry Andric void Ident(SourceLocation Loc, StringRef str) override; 1350b57cec5SDimitry Andric void PragmaMessage(SourceLocation Loc, StringRef Namespace, 1360b57cec5SDimitry Andric PragmaMessageKind Kind, StringRef Str) override; 1370b57cec5SDimitry Andric void PragmaDebug(SourceLocation Loc, StringRef DebugType) override; 1380b57cec5SDimitry Andric void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override; 1390b57cec5SDimitry Andric void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override; 1400b57cec5SDimitry Andric void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 1410b57cec5SDimitry Andric diag::Severity Map, StringRef Str) override; 1420b57cec5SDimitry Andric void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, 1430b57cec5SDimitry Andric ArrayRef<int> Ids) override; 1440b57cec5SDimitry Andric void PragmaWarningPush(SourceLocation Loc, int Level) override; 1450b57cec5SDimitry Andric void PragmaWarningPop(SourceLocation Loc) override; 1460b57cec5SDimitry Andric void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override; 1470b57cec5SDimitry Andric void PragmaExecCharsetPop(SourceLocation Loc) override; 1480b57cec5SDimitry Andric void PragmaAssumeNonNullBegin(SourceLocation Loc) override; 1490b57cec5SDimitry Andric void PragmaAssumeNonNullEnd(SourceLocation Loc) override; 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric bool HandleFirstTokOnLine(Token &Tok); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric /// Move to the line of the provided source location. This will 1540b57cec5SDimitry Andric /// return true if the output stream required adjustment or if 1550b57cec5SDimitry Andric /// the requested location is on the first line. 1560b57cec5SDimitry Andric bool MoveToLine(SourceLocation Loc) { 1570b57cec5SDimitry Andric PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1580b57cec5SDimitry Andric if (PLoc.isInvalid()) 1590b57cec5SDimitry Andric return false; 1600b57cec5SDimitry Andric return MoveToLine(PLoc.getLine()) || (PLoc.getLine() == 1); 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric bool MoveToLine(unsigned LineNo); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, 1650b57cec5SDimitry Andric const Token &Tok) { 1660b57cec5SDimitry Andric return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok); 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric void WriteLineInfo(unsigned LineNo, const char *Extra=nullptr, 1690b57cec5SDimitry Andric unsigned ExtraLen=0); 1700b57cec5SDimitry Andric bool LineMarkersAreDisabled() const { return DisableLineMarkers; } 1710b57cec5SDimitry Andric void HandleNewlinesInToken(const char *TokStr, unsigned Len); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric /// MacroDefined - This hook is called whenever a macro definition is seen. 1740b57cec5SDimitry Andric void MacroDefined(const Token &MacroNameTok, 1750b57cec5SDimitry Andric const MacroDirective *MD) override; 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric /// MacroUndefined - This hook is called whenever a macro #undef is seen. 1780b57cec5SDimitry Andric void MacroUndefined(const Token &MacroNameTok, 1790b57cec5SDimitry Andric const MacroDefinition &MD, 1800b57cec5SDimitry Andric const MacroDirective *Undef) override; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric void BeginModule(const Module *M); 1830b57cec5SDimitry Andric void EndModule(const Module *M); 1840b57cec5SDimitry Andric }; 1850b57cec5SDimitry Andric } // end anonymous namespace 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, 1880b57cec5SDimitry Andric const char *Extra, 1890b57cec5SDimitry Andric unsigned ExtraLen) { 1900b57cec5SDimitry Andric startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric // Emit #line directives or GNU line markers depending on what mode we're in. 1930b57cec5SDimitry Andric if (UseLineDirectives) { 1940b57cec5SDimitry Andric OS << "#line" << ' ' << LineNo << ' ' << '"'; 1950b57cec5SDimitry Andric OS.write_escaped(CurFilename); 1960b57cec5SDimitry Andric OS << '"'; 1970b57cec5SDimitry Andric } else { 1980b57cec5SDimitry Andric OS << '#' << ' ' << LineNo << ' ' << '"'; 1990b57cec5SDimitry Andric OS.write_escaped(CurFilename); 2000b57cec5SDimitry Andric OS << '"'; 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric if (ExtraLen) 2030b57cec5SDimitry Andric OS.write(Extra, ExtraLen); 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric if (FileType == SrcMgr::C_System) 2060b57cec5SDimitry Andric OS.write(" 3", 2); 2070b57cec5SDimitry Andric else if (FileType == SrcMgr::C_ExternCSystem) 2080b57cec5SDimitry Andric OS.write(" 3 4", 4); 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric OS << '\n'; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric /// MoveToLine - Move the output to the source line specified by the location 2140b57cec5SDimitry Andric /// object. We can do this by emitting some number of \n's, or be emitting a 2150b57cec5SDimitry Andric /// #line directive. This returns false if already at the specified line, true 2160b57cec5SDimitry Andric /// if some newlines were emitted. 2170b57cec5SDimitry Andric bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) { 2180b57cec5SDimitry Andric // If this line is "close enough" to the original line, just print newlines, 2190b57cec5SDimitry Andric // otherwise print a #line directive. 2200b57cec5SDimitry Andric if (LineNo-CurLine <= 8) { 2210b57cec5SDimitry Andric if (LineNo-CurLine == 1) 2220b57cec5SDimitry Andric OS << '\n'; 2230b57cec5SDimitry Andric else if (LineNo == CurLine) 2240b57cec5SDimitry Andric return false; // Spelling line moved, but expansion line didn't. 2250b57cec5SDimitry Andric else { 2260b57cec5SDimitry Andric const char *NewLines = "\n\n\n\n\n\n\n\n"; 2270b57cec5SDimitry Andric OS.write(NewLines, LineNo-CurLine); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric } else if (!DisableLineMarkers) { 2300b57cec5SDimitry Andric // Emit a #line or line marker. 2310b57cec5SDimitry Andric WriteLineInfo(LineNo, nullptr, 0); 2320b57cec5SDimitry Andric } else { 2330b57cec5SDimitry Andric // Okay, we're in -P mode, which turns off line markers. However, we still 2340b57cec5SDimitry Andric // need to emit a newline between tokens on different lines. 2350b57cec5SDimitry Andric startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric CurLine = LineNo; 2390b57cec5SDimitry Andric return true; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric bool 2430b57cec5SDimitry Andric PrintPPOutputPPCallbacks::startNewLineIfNeeded(bool ShouldUpdateCurrentLine) { 2440b57cec5SDimitry Andric if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) { 2450b57cec5SDimitry Andric OS << '\n'; 2460b57cec5SDimitry Andric EmittedTokensOnThisLine = false; 2470b57cec5SDimitry Andric EmittedDirectiveOnThisLine = false; 2480b57cec5SDimitry Andric if (ShouldUpdateCurrentLine) 2490b57cec5SDimitry Andric ++CurLine; 2500b57cec5SDimitry Andric return true; 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric return false; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric /// FileChanged - Whenever the preprocessor enters or exits a #include file 2570b57cec5SDimitry Andric /// it invokes this handler. Update our conception of the current source 2580b57cec5SDimitry Andric /// position. 2590b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, 2600b57cec5SDimitry Andric FileChangeReason Reason, 2610b57cec5SDimitry Andric SrcMgr::CharacteristicKind NewFileType, 2620b57cec5SDimitry Andric FileID PrevFID) { 2630b57cec5SDimitry Andric // Unless we are exiting a #include, make sure to skip ahead to the line the 2640b57cec5SDimitry Andric // #include directive was at. 2650b57cec5SDimitry Andric SourceManager &SourceMgr = SM; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); 2680b57cec5SDimitry Andric if (UserLoc.isInvalid()) 2690b57cec5SDimitry Andric return; 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric unsigned NewLine = UserLoc.getLine(); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric if (Reason == PPCallbacks::EnterFile) { 2740b57cec5SDimitry Andric SourceLocation IncludeLoc = UserLoc.getIncludeLoc(); 2750b57cec5SDimitry Andric if (IncludeLoc.isValid()) 2760b57cec5SDimitry Andric MoveToLine(IncludeLoc); 2770b57cec5SDimitry Andric } else if (Reason == PPCallbacks::SystemHeaderPragma) { 2780b57cec5SDimitry Andric // GCC emits the # directive for this directive on the line AFTER the 2790b57cec5SDimitry Andric // directive and emits a bunch of spaces that aren't needed. This is because 2800b57cec5SDimitry Andric // otherwise we will emit a line marker for THIS line, which requires an 2810b57cec5SDimitry Andric // extra blank line after the directive to avoid making all following lines 2820b57cec5SDimitry Andric // off by one. We can do better by simply incrementing NewLine here. 2830b57cec5SDimitry Andric NewLine += 1; 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric CurLine = NewLine; 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric CurFilename.clear(); 2890b57cec5SDimitry Andric CurFilename += UserLoc.getFilename(); 2900b57cec5SDimitry Andric FileType = NewFileType; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric if (DisableLineMarkers) { 2930b57cec5SDimitry Andric startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 2940b57cec5SDimitry Andric return; 2950b57cec5SDimitry Andric } 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric if (!Initialized) { 2980b57cec5SDimitry Andric WriteLineInfo(CurLine); 2990b57cec5SDimitry Andric Initialized = true; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric // Do not emit an enter marker for the main file (which we expect is the first 3030b57cec5SDimitry Andric // entered file). This matches gcc, and improves compatibility with some tools 3040b57cec5SDimitry Andric // which track the # line markers as a way to determine when the preprocessed 3050b57cec5SDimitry Andric // output is in the context of the main file. 3060b57cec5SDimitry Andric if (Reason == PPCallbacks::EnterFile && !IsFirstFileEntered) { 3070b57cec5SDimitry Andric IsFirstFileEntered = true; 3080b57cec5SDimitry Andric return; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric switch (Reason) { 3120b57cec5SDimitry Andric case PPCallbacks::EnterFile: 3130b57cec5SDimitry Andric WriteLineInfo(CurLine, " 1", 2); 3140b57cec5SDimitry Andric break; 3150b57cec5SDimitry Andric case PPCallbacks::ExitFile: 3160b57cec5SDimitry Andric WriteLineInfo(CurLine, " 2", 2); 3170b57cec5SDimitry Andric break; 3180b57cec5SDimitry Andric case PPCallbacks::SystemHeaderPragma: 3190b57cec5SDimitry Andric case PPCallbacks::RenameFile: 3200b57cec5SDimitry Andric WriteLineInfo(CurLine); 3210b57cec5SDimitry Andric break; 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::InclusionDirective( 3260b57cec5SDimitry Andric SourceLocation HashLoc, 3270b57cec5SDimitry Andric const Token &IncludeTok, 3280b57cec5SDimitry Andric StringRef FileName, 3290b57cec5SDimitry Andric bool IsAngled, 3300b57cec5SDimitry Andric CharSourceRange FilenameRange, 3310b57cec5SDimitry Andric const FileEntry *File, 3320b57cec5SDimitry Andric StringRef SearchPath, 3330b57cec5SDimitry Andric StringRef RelativePath, 3340b57cec5SDimitry Andric const Module *Imported, 3350b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType) { 3360b57cec5SDimitry Andric // In -dI mode, dump #include directives prior to dumping their content or 3370b57cec5SDimitry Andric // interpretation. 3380b57cec5SDimitry Andric if (DumpIncludeDirectives) { 3390b57cec5SDimitry Andric startNewLineIfNeeded(); 3400b57cec5SDimitry Andric MoveToLine(HashLoc); 3410b57cec5SDimitry Andric const std::string TokenText = PP.getSpelling(IncludeTok); 3420b57cec5SDimitry Andric assert(!TokenText.empty()); 3430b57cec5SDimitry Andric OS << "#" << TokenText << " " 3440b57cec5SDimitry Andric << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') 3450b57cec5SDimitry Andric << " /* clang -E -dI */"; 3460b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 3470b57cec5SDimitry Andric startNewLineIfNeeded(); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric // When preprocessing, turn implicit imports into module import pragmas. 3510b57cec5SDimitry Andric if (Imported) { 3520b57cec5SDimitry Andric switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { 3530b57cec5SDimitry Andric case tok::pp_include: 3540b57cec5SDimitry Andric case tok::pp_import: 3550b57cec5SDimitry Andric case tok::pp_include_next: 3560b57cec5SDimitry Andric startNewLineIfNeeded(); 3570b57cec5SDimitry Andric MoveToLine(HashLoc); 3580b57cec5SDimitry Andric OS << "#pragma clang module import " << Imported->getFullModuleName(true) 3590b57cec5SDimitry Andric << " /* clang -E: implicit import for " 3600b57cec5SDimitry Andric << "#" << PP.getSpelling(IncludeTok) << " " 3610b57cec5SDimitry Andric << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') 3620b57cec5SDimitry Andric << " */"; 3630b57cec5SDimitry Andric // Since we want a newline after the pragma, but not a #<line>, start a 3640b57cec5SDimitry Andric // new line immediately. 3650b57cec5SDimitry Andric EmittedTokensOnThisLine = true; 3660b57cec5SDimitry Andric startNewLineIfNeeded(); 3670b57cec5SDimitry Andric break; 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric case tok::pp___include_macros: 3700b57cec5SDimitry Andric // #__include_macros has no effect on a user of a preprocessed source 3710b57cec5SDimitry Andric // file; the only effect is on preprocessing. 3720b57cec5SDimitry Andric // 3730b57cec5SDimitry Andric // FIXME: That's not *quite* true: it causes the module in question to 3740b57cec5SDimitry Andric // be loaded, which can affect downstream diagnostics. 3750b57cec5SDimitry Andric break; 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric default: 3780b57cec5SDimitry Andric llvm_unreachable("unknown include directive kind"); 3790b57cec5SDimitry Andric break; 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric /// Handle entering the scope of a module during a module compilation. 3850b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::BeginModule(const Module *M) { 3860b57cec5SDimitry Andric startNewLineIfNeeded(); 3870b57cec5SDimitry Andric OS << "#pragma clang module begin " << M->getFullModuleName(true); 3880b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric /// Handle leaving the scope of a module during a module compilation. 3920b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::EndModule(const Module *M) { 3930b57cec5SDimitry Andric startNewLineIfNeeded(); 3940b57cec5SDimitry Andric OS << "#pragma clang module end /*" << M->getFullModuleName(true) << "*/"; 3950b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric /// Ident - Handle #ident directives when read by the preprocessor. 3990b57cec5SDimitry Andric /// 4000b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) { 4010b57cec5SDimitry Andric MoveToLine(Loc); 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric OS.write("#ident ", strlen("#ident ")); 4040b57cec5SDimitry Andric OS.write(S.begin(), S.size()); 4050b57cec5SDimitry Andric EmittedTokensOnThisLine = true; 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric /// MacroDefined - This hook is called whenever a macro definition is seen. 4090b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, 4100b57cec5SDimitry Andric const MacroDirective *MD) { 4110b57cec5SDimitry Andric const MacroInfo *MI = MD->getMacroInfo(); 4120b57cec5SDimitry Andric // Only print out macro definitions in -dD mode. 4130b57cec5SDimitry Andric if (!DumpDefines || 4140b57cec5SDimitry Andric // Ignore __FILE__ etc. 4150b57cec5SDimitry Andric MI->isBuiltinMacro()) return; 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric MoveToLine(MI->getDefinitionLoc()); 4180b57cec5SDimitry Andric PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS); 4190b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, 4230b57cec5SDimitry Andric const MacroDefinition &MD, 4240b57cec5SDimitry Andric const MacroDirective *Undef) { 4250b57cec5SDimitry Andric // Only print out macro definitions in -dD mode. 4260b57cec5SDimitry Andric if (!DumpDefines) return; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric MoveToLine(MacroNameTok.getLocation()); 4290b57cec5SDimitry Andric OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName(); 4300b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric static void outputPrintable(raw_ostream &OS, StringRef Str) { 4340b57cec5SDimitry Andric for (unsigned char Char : Str) { 4350b57cec5SDimitry Andric if (isPrintable(Char) && Char != '\\' && Char != '"') 4360b57cec5SDimitry Andric OS << (char)Char; 4370b57cec5SDimitry Andric else // Output anything hard as an octal escape. 4380b57cec5SDimitry Andric OS << '\\' 4390b57cec5SDimitry Andric << (char)('0' + ((Char >> 6) & 7)) 4400b57cec5SDimitry Andric << (char)('0' + ((Char >> 3) & 7)) 4410b57cec5SDimitry Andric << (char)('0' + ((Char >> 0) & 7)); 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, 4460b57cec5SDimitry Andric StringRef Namespace, 4470b57cec5SDimitry Andric PragmaMessageKind Kind, 4480b57cec5SDimitry Andric StringRef Str) { 4490b57cec5SDimitry Andric startNewLineIfNeeded(); 4500b57cec5SDimitry Andric MoveToLine(Loc); 4510b57cec5SDimitry Andric OS << "#pragma "; 4520b57cec5SDimitry Andric if (!Namespace.empty()) 4530b57cec5SDimitry Andric OS << Namespace << ' '; 4540b57cec5SDimitry Andric switch (Kind) { 4550b57cec5SDimitry Andric case PMK_Message: 4560b57cec5SDimitry Andric OS << "message(\""; 4570b57cec5SDimitry Andric break; 4580b57cec5SDimitry Andric case PMK_Warning: 4590b57cec5SDimitry Andric OS << "warning \""; 4600b57cec5SDimitry Andric break; 4610b57cec5SDimitry Andric case PMK_Error: 4620b57cec5SDimitry Andric OS << "error \""; 4630b57cec5SDimitry Andric break; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric outputPrintable(OS, Str); 4670b57cec5SDimitry Andric OS << '"'; 4680b57cec5SDimitry Andric if (Kind == PMK_Message) 4690b57cec5SDimitry Andric OS << ')'; 4700b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc, 4740b57cec5SDimitry Andric StringRef DebugType) { 4750b57cec5SDimitry Andric startNewLineIfNeeded(); 4760b57cec5SDimitry Andric MoveToLine(Loc); 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric OS << "#pragma clang __debug "; 4790b57cec5SDimitry Andric OS << DebugType; 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 4850b57cec5SDimitry Andric PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { 4860b57cec5SDimitry Andric startNewLineIfNeeded(); 4870b57cec5SDimitry Andric MoveToLine(Loc); 4880b57cec5SDimitry Andric OS << "#pragma " << Namespace << " diagnostic push"; 4890b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 4930b57cec5SDimitry Andric PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { 4940b57cec5SDimitry Andric startNewLineIfNeeded(); 4950b57cec5SDimitry Andric MoveToLine(Loc); 4960b57cec5SDimitry Andric OS << "#pragma " << Namespace << " diagnostic pop"; 4970b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 4980b57cec5SDimitry Andric } 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc, 5010b57cec5SDimitry Andric StringRef Namespace, 5020b57cec5SDimitry Andric diag::Severity Map, 5030b57cec5SDimitry Andric StringRef Str) { 5040b57cec5SDimitry Andric startNewLineIfNeeded(); 5050b57cec5SDimitry Andric MoveToLine(Loc); 5060b57cec5SDimitry Andric OS << "#pragma " << Namespace << " diagnostic "; 5070b57cec5SDimitry Andric switch (Map) { 5080b57cec5SDimitry Andric case diag::Severity::Remark: 5090b57cec5SDimitry Andric OS << "remark"; 5100b57cec5SDimitry Andric break; 5110b57cec5SDimitry Andric case diag::Severity::Warning: 5120b57cec5SDimitry Andric OS << "warning"; 5130b57cec5SDimitry Andric break; 5140b57cec5SDimitry Andric case diag::Severity::Error: 5150b57cec5SDimitry Andric OS << "error"; 5160b57cec5SDimitry Andric break; 5170b57cec5SDimitry Andric case diag::Severity::Ignored: 5180b57cec5SDimitry Andric OS << "ignored"; 5190b57cec5SDimitry Andric break; 5200b57cec5SDimitry Andric case diag::Severity::Fatal: 5210b57cec5SDimitry Andric OS << "fatal"; 5220b57cec5SDimitry Andric break; 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric OS << " \"" << Str << '"'; 5250b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5260b57cec5SDimitry Andric } 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc, 5290b57cec5SDimitry Andric StringRef WarningSpec, 5300b57cec5SDimitry Andric ArrayRef<int> Ids) { 5310b57cec5SDimitry Andric startNewLineIfNeeded(); 5320b57cec5SDimitry Andric MoveToLine(Loc); 5330b57cec5SDimitry Andric OS << "#pragma warning(" << WarningSpec << ':'; 5340b57cec5SDimitry Andric for (ArrayRef<int>::iterator I = Ids.begin(), E = Ids.end(); I != E; ++I) 5350b57cec5SDimitry Andric OS << ' ' << *I; 5360b57cec5SDimitry Andric OS << ')'; 5370b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc, 5410b57cec5SDimitry Andric int Level) { 5420b57cec5SDimitry Andric startNewLineIfNeeded(); 5430b57cec5SDimitry Andric MoveToLine(Loc); 5440b57cec5SDimitry Andric OS << "#pragma warning(push"; 5450b57cec5SDimitry Andric if (Level >= 0) 5460b57cec5SDimitry Andric OS << ", " << Level; 5470b57cec5SDimitry Andric OS << ')'; 5480b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { 5520b57cec5SDimitry Andric startNewLineIfNeeded(); 5530b57cec5SDimitry Andric MoveToLine(Loc); 5540b57cec5SDimitry Andric OS << "#pragma warning(pop)"; 5550b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc, 5590b57cec5SDimitry Andric StringRef Str) { 5600b57cec5SDimitry Andric startNewLineIfNeeded(); 5610b57cec5SDimitry Andric MoveToLine(Loc); 5620b57cec5SDimitry Andric OS << "#pragma character_execution_set(push"; 5630b57cec5SDimitry Andric if (!Str.empty()) 5640b57cec5SDimitry Andric OS << ", " << Str; 5650b57cec5SDimitry Andric OS << ')'; 5660b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaExecCharsetPop(SourceLocation Loc) { 5700b57cec5SDimitry Andric startNewLineIfNeeded(); 5710b57cec5SDimitry Andric MoveToLine(Loc); 5720b57cec5SDimitry Andric OS << "#pragma character_execution_set(pop)"; 5730b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 5770b57cec5SDimitry Andric PragmaAssumeNonNullBegin(SourceLocation Loc) { 5780b57cec5SDimitry Andric startNewLineIfNeeded(); 5790b57cec5SDimitry Andric MoveToLine(Loc); 5800b57cec5SDimitry Andric OS << "#pragma clang assume_nonnull begin"; 5810b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 5850b57cec5SDimitry Andric PragmaAssumeNonNullEnd(SourceLocation Loc) { 5860b57cec5SDimitry Andric startNewLineIfNeeded(); 5870b57cec5SDimitry Andric MoveToLine(Loc); 5880b57cec5SDimitry Andric OS << "#pragma clang assume_nonnull end"; 5890b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this 5930b57cec5SDimitry Andric /// is called for the first token on each new line. If this really is the start 5940b57cec5SDimitry Andric /// of a new logical line, handle it and return true, otherwise return false. 5950b57cec5SDimitry Andric /// This may not be the start of a logical line because the "start of line" 5960b57cec5SDimitry Andric /// marker is set for spelling lines, not expansion ones. 5970b57cec5SDimitry Andric bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { 5980b57cec5SDimitry Andric // Figure out what line we went to and insert the appropriate number of 5990b57cec5SDimitry Andric // newline characters. 6000b57cec5SDimitry Andric if (!MoveToLine(Tok.getLocation())) 6010b57cec5SDimitry Andric return false; 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric // Print out space characters so that the first token on a line is 6040b57cec5SDimitry Andric // indented for easy reading. 6050b57cec5SDimitry Andric unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation()); 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric // The first token on a line can have a column number of 1, yet still expect 6080b57cec5SDimitry Andric // leading white space, if a macro expansion in column 1 starts with an empty 6090b57cec5SDimitry Andric // macro argument, or an empty nested macro expansion. In this case, move the 6100b57cec5SDimitry Andric // token to column 2. 6110b57cec5SDimitry Andric if (ColNo == 1 && Tok.hasLeadingSpace()) 6120b57cec5SDimitry Andric ColNo = 2; 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric // This hack prevents stuff like: 6150b57cec5SDimitry Andric // #define HASH # 6160b57cec5SDimitry Andric // HASH define foo bar 6170b57cec5SDimitry Andric // From having the # character end up at column 1, which makes it so it 6180b57cec5SDimitry Andric // is not handled as a #define next time through the preprocessor if in 6190b57cec5SDimitry Andric // -fpreprocessed mode. 6200b57cec5SDimitry Andric if (ColNo <= 1 && Tok.is(tok::hash)) 6210b57cec5SDimitry Andric OS << ' '; 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric // Otherwise, indent the appropriate number of spaces. 6240b57cec5SDimitry Andric for (; ColNo > 1; --ColNo) 6250b57cec5SDimitry Andric OS << ' '; 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric return true; 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr, 6310b57cec5SDimitry Andric unsigned Len) { 6320b57cec5SDimitry Andric unsigned NumNewlines = 0; 6330b57cec5SDimitry Andric for (; Len; --Len, ++TokStr) { 6340b57cec5SDimitry Andric if (*TokStr != '\n' && 6350b57cec5SDimitry Andric *TokStr != '\r') 6360b57cec5SDimitry Andric continue; 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric ++NumNewlines; 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric // If we have \n\r or \r\n, skip both and count as one line. 6410b57cec5SDimitry Andric if (Len != 1 && 6420b57cec5SDimitry Andric (TokStr[1] == '\n' || TokStr[1] == '\r') && 6430b57cec5SDimitry Andric TokStr[0] != TokStr[1]) { 6440b57cec5SDimitry Andric ++TokStr; 6450b57cec5SDimitry Andric --Len; 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric if (NumNewlines == 0) return; 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric CurLine += NumNewlines; 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric namespace { 6560b57cec5SDimitry Andric struct UnknownPragmaHandler : public PragmaHandler { 6570b57cec5SDimitry Andric const char *Prefix; 6580b57cec5SDimitry Andric PrintPPOutputPPCallbacks *Callbacks; 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric // Set to true if tokens should be expanded 6610b57cec5SDimitry Andric bool ShouldExpandTokens; 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks, 6640b57cec5SDimitry Andric bool RequireTokenExpansion) 6650b57cec5SDimitry Andric : Prefix(prefix), Callbacks(callbacks), 6660b57cec5SDimitry Andric ShouldExpandTokens(RequireTokenExpansion) {} 6670b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 6680b57cec5SDimitry Andric Token &PragmaTok) override { 6690b57cec5SDimitry Andric // Figure out what line we went to and insert the appropriate number of 6700b57cec5SDimitry Andric // newline characters. 6710b57cec5SDimitry Andric Callbacks->startNewLineIfNeeded(); 6720b57cec5SDimitry Andric Callbacks->MoveToLine(PragmaTok.getLocation()); 6730b57cec5SDimitry Andric Callbacks->OS.write(Prefix, strlen(Prefix)); 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric if (ShouldExpandTokens) { 6760b57cec5SDimitry Andric // The first token does not have expanded macros. Expand them, if 6770b57cec5SDimitry Andric // required. 678*a7dea167SDimitry Andric auto Toks = std::make_unique<Token[]>(1); 6790b57cec5SDimitry Andric Toks[0] = PragmaTok; 6800b57cec5SDimitry Andric PP.EnterTokenStream(std::move(Toks), /*NumToks=*/1, 6810b57cec5SDimitry Andric /*DisableMacroExpansion=*/false, 6820b57cec5SDimitry Andric /*IsReinject=*/false); 6830b57cec5SDimitry Andric PP.Lex(PragmaTok); 6840b57cec5SDimitry Andric } 6850b57cec5SDimitry Andric Token PrevToken; 6860b57cec5SDimitry Andric Token PrevPrevToken; 6870b57cec5SDimitry Andric PrevToken.startToken(); 6880b57cec5SDimitry Andric PrevPrevToken.startToken(); 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric // Read and print all of the pragma tokens. 6910b57cec5SDimitry Andric while (PragmaTok.isNot(tok::eod)) { 6920b57cec5SDimitry Andric if (PragmaTok.hasLeadingSpace() || 6930b57cec5SDimitry Andric Callbacks->AvoidConcat(PrevPrevToken, PrevToken, PragmaTok)) 6940b57cec5SDimitry Andric Callbacks->OS << ' '; 6950b57cec5SDimitry Andric std::string TokSpell = PP.getSpelling(PragmaTok); 6960b57cec5SDimitry Andric Callbacks->OS.write(&TokSpell[0], TokSpell.size()); 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric PrevPrevToken = PrevToken; 6990b57cec5SDimitry Andric PrevToken = PragmaTok; 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric if (ShouldExpandTokens) 7020b57cec5SDimitry Andric PP.Lex(PragmaTok); 7030b57cec5SDimitry Andric else 7040b57cec5SDimitry Andric PP.LexUnexpandedToken(PragmaTok); 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric Callbacks->setEmittedDirectiveOnThisLine(); 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric }; 7090b57cec5SDimitry Andric } // end anonymous namespace 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, 7130b57cec5SDimitry Andric PrintPPOutputPPCallbacks *Callbacks, 7140b57cec5SDimitry Andric raw_ostream &OS) { 7150b57cec5SDimitry Andric bool DropComments = PP.getLangOpts().TraditionalCPP && 7160b57cec5SDimitry Andric !PP.getCommentRetentionState(); 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric char Buffer[256]; 7190b57cec5SDimitry Andric Token PrevPrevTok, PrevTok; 7200b57cec5SDimitry Andric PrevPrevTok.startToken(); 7210b57cec5SDimitry Andric PrevTok.startToken(); 7220b57cec5SDimitry Andric while (1) { 7230b57cec5SDimitry Andric if (Callbacks->hasEmittedDirectiveOnThisLine()) { 7240b57cec5SDimitry Andric Callbacks->startNewLineIfNeeded(); 7250b57cec5SDimitry Andric Callbacks->MoveToLine(Tok.getLocation()); 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric // If this token is at the start of a line, emit newlines if needed. 7290b57cec5SDimitry Andric if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) { 7300b57cec5SDimitry Andric // done. 7310b57cec5SDimitry Andric } else if (Tok.hasLeadingSpace() || 7320b57cec5SDimitry Andric // If we haven't emitted a token on this line yet, PrevTok isn't 7330b57cec5SDimitry Andric // useful to look at and no concatenation could happen anyway. 7340b57cec5SDimitry Andric (Callbacks->hasEmittedTokensOnThisLine() && 7350b57cec5SDimitry Andric // Don't print "-" next to "-", it would form "--". 7360b57cec5SDimitry Andric Callbacks->AvoidConcat(PrevPrevTok, PrevTok, Tok))) { 7370b57cec5SDimitry Andric OS << ' '; 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric if (DropComments && Tok.is(tok::comment)) { 7410b57cec5SDimitry Andric // Skip comments. Normally the preprocessor does not generate 7420b57cec5SDimitry Andric // tok::comment nodes at all when not keeping comments, but under 7430b57cec5SDimitry Andric // -traditional-cpp the lexer keeps /all/ whitespace, including comments. 7440b57cec5SDimitry Andric SourceLocation StartLoc = Tok.getLocation(); 7450b57cec5SDimitry Andric Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength())); 7460b57cec5SDimitry Andric } else if (Tok.is(tok::eod)) { 7470b57cec5SDimitry Andric // Don't print end of directive tokens, since they are typically newlines 7480b57cec5SDimitry Andric // that mess up our line tracking. These come from unknown pre-processor 7490b57cec5SDimitry Andric // directives or hash-prefixed comments in standalone assembly files. 7500b57cec5SDimitry Andric PP.Lex(Tok); 7510b57cec5SDimitry Andric continue; 7520b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_include)) { 7530b57cec5SDimitry Andric // PrintPPOutputPPCallbacks::InclusionDirective handles producing 7540b57cec5SDimitry Andric // appropriate output here. Ignore this token entirely. 7550b57cec5SDimitry Andric PP.Lex(Tok); 7560b57cec5SDimitry Andric continue; 7570b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_begin)) { 7580b57cec5SDimitry Andric // FIXME: We retrieve this token after the FileChanged callback, and 7590b57cec5SDimitry Andric // retrieve the module_end token before the FileChanged callback, so 7600b57cec5SDimitry Andric // we render this within the file and render the module end outside the 7610b57cec5SDimitry Andric // file, but this is backwards from the token locations: the module_begin 7620b57cec5SDimitry Andric // token is at the include location (outside the file) and the module_end 7630b57cec5SDimitry Andric // token is at the EOF location (within the file). 7640b57cec5SDimitry Andric Callbacks->BeginModule( 7650b57cec5SDimitry Andric reinterpret_cast<Module *>(Tok.getAnnotationValue())); 7660b57cec5SDimitry Andric PP.Lex(Tok); 7670b57cec5SDimitry Andric continue; 7680b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_end)) { 7690b57cec5SDimitry Andric Callbacks->EndModule( 7700b57cec5SDimitry Andric reinterpret_cast<Module *>(Tok.getAnnotationValue())); 7710b57cec5SDimitry Andric PP.Lex(Tok); 7720b57cec5SDimitry Andric continue; 7730b57cec5SDimitry Andric } else if (Tok.is(tok::annot_header_unit)) { 7740b57cec5SDimitry Andric // This is a header-name that has been (effectively) converted into a 7750b57cec5SDimitry Andric // module-name. 7760b57cec5SDimitry Andric // FIXME: The module name could contain non-identifier module name 7770b57cec5SDimitry Andric // components. We don't have a good way to round-trip those. 7780b57cec5SDimitry Andric Module *M = reinterpret_cast<Module *>(Tok.getAnnotationValue()); 7790b57cec5SDimitry Andric std::string Name = M->getFullModuleName(); 7800b57cec5SDimitry Andric OS.write(Name.data(), Name.size()); 7810b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(Name.data(), Name.size()); 7820b57cec5SDimitry Andric } else if (Tok.isAnnotation()) { 7830b57cec5SDimitry Andric // Ignore annotation tokens created by pragmas - the pragmas themselves 7840b57cec5SDimitry Andric // will be reproduced in the preprocessed output. 7850b57cec5SDimitry Andric PP.Lex(Tok); 7860b57cec5SDimitry Andric continue; 7870b57cec5SDimitry Andric } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { 7880b57cec5SDimitry Andric OS << II->getName(); 7890b57cec5SDimitry Andric } else if (Tok.isLiteral() && !Tok.needsCleaning() && 7900b57cec5SDimitry Andric Tok.getLiteralData()) { 7910b57cec5SDimitry Andric OS.write(Tok.getLiteralData(), Tok.getLength()); 7920b57cec5SDimitry Andric } else if (Tok.getLength() < llvm::array_lengthof(Buffer)) { 7930b57cec5SDimitry Andric const char *TokPtr = Buffer; 7940b57cec5SDimitry Andric unsigned Len = PP.getSpelling(Tok, TokPtr); 7950b57cec5SDimitry Andric OS.write(TokPtr, Len); 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric // Tokens that can contain embedded newlines need to adjust our current 7980b57cec5SDimitry Andric // line number. 7990b57cec5SDimitry Andric if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) 8000b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(TokPtr, Len); 8010b57cec5SDimitry Andric } else { 8020b57cec5SDimitry Andric std::string S = PP.getSpelling(Tok); 8030b57cec5SDimitry Andric OS.write(S.data(), S.size()); 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric // Tokens that can contain embedded newlines need to adjust our current 8060b57cec5SDimitry Andric // line number. 8070b57cec5SDimitry Andric if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) 8080b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(S.data(), S.size()); 8090b57cec5SDimitry Andric } 8100b57cec5SDimitry Andric Callbacks->setEmittedTokensOnThisLine(); 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric if (Tok.is(tok::eof)) break; 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric PrevPrevTok = PrevTok; 8150b57cec5SDimitry Andric PrevTok = Tok; 8160b57cec5SDimitry Andric PP.Lex(Tok); 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric typedef std::pair<const IdentifierInfo *, MacroInfo *> id_macro_pair; 8210b57cec5SDimitry Andric static int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS) { 8220b57cec5SDimitry Andric return LHS->first->getName().compare(RHS->first->getName()); 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) { 8260b57cec5SDimitry Andric // Ignore unknown pragmas. 8270b57cec5SDimitry Andric PP.IgnorePragmas(); 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric // -dM mode just scans and ignores all tokens in the files, then dumps out 8300b57cec5SDimitry Andric // the macro table at the end. 8310b57cec5SDimitry Andric PP.EnterMainSourceFile(); 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric Token Tok; 8340b57cec5SDimitry Andric do PP.Lex(Tok); 8350b57cec5SDimitry Andric while (Tok.isNot(tok::eof)); 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric SmallVector<id_macro_pair, 128> MacrosByID; 8380b57cec5SDimitry Andric for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); 8390b57cec5SDimitry Andric I != E; ++I) { 8400b57cec5SDimitry Andric auto *MD = I->second.getLatest(); 8410b57cec5SDimitry Andric if (MD && MD->isDefined()) 8420b57cec5SDimitry Andric MacrosByID.push_back(id_macro_pair(I->first, MD->getMacroInfo())); 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare); 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) { 8470b57cec5SDimitry Andric MacroInfo &MI = *MacrosByID[i].second; 8480b57cec5SDimitry Andric // Ignore computed macros like __LINE__ and friends. 8490b57cec5SDimitry Andric if (MI.isBuiltinMacro()) continue; 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS); 8520b57cec5SDimitry Andric *OS << '\n'; 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric 8560b57cec5SDimitry Andric /// DoPrintPreprocessedInput - This implements -E mode. 8570b57cec5SDimitry Andric /// 8580b57cec5SDimitry Andric void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, 8590b57cec5SDimitry Andric const PreprocessorOutputOptions &Opts) { 8600b57cec5SDimitry Andric // Show macros with no output is handled specially. 8610b57cec5SDimitry Andric if (!Opts.ShowCPP) { 8620b57cec5SDimitry Andric assert(Opts.ShowMacros && "Not yet implemented!"); 8630b57cec5SDimitry Andric DoPrintMacros(PP, OS); 8640b57cec5SDimitry Andric return; 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric // Inform the preprocessor whether we want it to retain comments or not, due 8680b57cec5SDimitry Andric // to -C or -CC. 8690b57cec5SDimitry Andric PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments); 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks( 8720b57cec5SDimitry Andric PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, 8730b57cec5SDimitry Andric Opts.ShowIncludeDirectives, Opts.UseLineDirectives); 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric // Expand macros in pragmas with -fms-extensions. The assumption is that 8760b57cec5SDimitry Andric // the majority of pragmas in such a file will be Microsoft pragmas. 8770b57cec5SDimitry Andric // Remember the handlers we will add so that we can remove them later. 8780b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> MicrosoftExtHandler( 8790b57cec5SDimitry Andric new UnknownPragmaHandler( 8800b57cec5SDimitry Andric "#pragma", Callbacks, 8810b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> GCCHandler(new UnknownPragmaHandler( 8840b57cec5SDimitry Andric "#pragma GCC", Callbacks, 8850b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 8860b57cec5SDimitry Andric 8870b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> ClangHandler(new UnknownPragmaHandler( 8880b57cec5SDimitry Andric "#pragma clang", Callbacks, 8890b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric PP.AddPragmaHandler(MicrosoftExtHandler.get()); 8920b57cec5SDimitry Andric PP.AddPragmaHandler("GCC", GCCHandler.get()); 8930b57cec5SDimitry Andric PP.AddPragmaHandler("clang", ClangHandler.get()); 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric // The tokens after pragma omp need to be expanded. 8960b57cec5SDimitry Andric // 8970b57cec5SDimitry Andric // OpenMP [2.1, Directive format] 8980b57cec5SDimitry Andric // Preprocessing tokens following the #pragma omp are subject to macro 8990b57cec5SDimitry Andric // replacement. 9000b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> OpenMPHandler( 9010b57cec5SDimitry Andric new UnknownPragmaHandler("#pragma omp", Callbacks, 9020b57cec5SDimitry Andric /*RequireTokenExpansion=*/true)); 9030b57cec5SDimitry Andric PP.AddPragmaHandler("omp", OpenMPHandler.get()); 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks)); 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric // After we have configured the preprocessor, enter the main file. 9080b57cec5SDimitry Andric PP.EnterMainSourceFile(); 9090b57cec5SDimitry Andric 9100b57cec5SDimitry Andric // Consume all of the tokens that come from the predefines buffer. Those 9110b57cec5SDimitry Andric // should not be emitted into the output and are guaranteed to be at the 9120b57cec5SDimitry Andric // start. 9130b57cec5SDimitry Andric const SourceManager &SourceMgr = PP.getSourceManager(); 9140b57cec5SDimitry Andric Token Tok; 9150b57cec5SDimitry Andric do { 9160b57cec5SDimitry Andric PP.Lex(Tok); 9170b57cec5SDimitry Andric if (Tok.is(tok::eof) || !Tok.getLocation().isFileID()) 9180b57cec5SDimitry Andric break; 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); 9210b57cec5SDimitry Andric if (PLoc.isInvalid()) 9220b57cec5SDimitry Andric break; 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric if (strcmp(PLoc.getFilename(), "<built-in>")) 9250b57cec5SDimitry Andric break; 9260b57cec5SDimitry Andric } while (true); 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric // Read all the preprocessed tokens, printing them out to the stream. 9290b57cec5SDimitry Andric PrintPreprocessedTokens(PP, Tok, Callbacks, *OS); 9300b57cec5SDimitry Andric *OS << '\n'; 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric // Remove the handlers we just added to leave the preprocessor in a sane state 9330b57cec5SDimitry Andric // so that it can be reused (for example by a clang::Parser instance). 9340b57cec5SDimitry Andric PP.RemovePragmaHandler(MicrosoftExtHandler.get()); 9350b57cec5SDimitry Andric PP.RemovePragmaHandler("GCC", GCCHandler.get()); 9360b57cec5SDimitry Andric PP.RemovePragmaHandler("clang", ClangHandler.get()); 9370b57cec5SDimitry Andric PP.RemovePragmaHandler("omp", OpenMPHandler.get()); 9380b57cec5SDimitry Andric } 939