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/Basic/CharInfo.h" 150b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 160b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 170b57cec5SDimitry Andric #include "clang/Frontend/PreprocessorOutputOptions.h" 18*0fca6ea1SDimitry Andric #include "clang/Frontend/Utils.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, 355f757f3fSDimitry Andric Preprocessor &PP, raw_ostream *OS) { 365f757f3fSDimitry Andric *OS << "#define " << II.getName(); 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric if (MI.isFunctionLike()) { 395f757f3fSDimitry 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) { 435f757f3fSDimitry Andric *OS << (*AI)->getName(); 445f757f3fSDimitry Andric *OS << ','; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric // Last argument. 480b57cec5SDimitry Andric if ((*AI)->getName() == "__VA_ARGS__") 495f757f3fSDimitry Andric *OS << "..."; 500b57cec5SDimitry Andric else 515f757f3fSDimitry Andric *OS << (*AI)->getName(); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric if (MI.isGNUVarargs()) 555f757f3fSDimitry Andric *OS << "..."; // #define foo(x...) 560b57cec5SDimitry Andric 575f757f3fSDimitry 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()) 635f757f3fSDimitry Andric *OS << ' '; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric SmallString<128> SpellingBuffer; 660b57cec5SDimitry Andric for (const auto &T : MI.tokens()) { 670b57cec5SDimitry Andric if (T.hasLeadingSpace()) 685f757f3fSDimitry Andric *OS << ' '; 690b57cec5SDimitry Andric 705f757f3fSDimitry 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: 845f757f3fSDimitry 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; 96*0fca6ea1SDimitry Andric bool DumpEmbedDirectives; 970b57cec5SDimitry Andric bool UseLineDirectives; 980b57cec5SDimitry Andric bool IsFirstFileEntered; 99349cc55cSDimitry Andric bool MinimizeWhitespace; 10081ad6265SDimitry Andric bool DirectivesOnly; 1015f757f3fSDimitry Andric bool KeepSystemIncludes; 1025f757f3fSDimitry Andric raw_ostream *OrigOS; 1035f757f3fSDimitry Andric std::unique_ptr<llvm::raw_null_ostream> NullOS; 104*0fca6ea1SDimitry Andric unsigned NumToksToSkip; 105349cc55cSDimitry Andric 106349cc55cSDimitry Andric Token PrevTok; 107349cc55cSDimitry Andric Token PrevPrevTok; 108349cc55cSDimitry Andric 1090b57cec5SDimitry Andric public: 1105f757f3fSDimitry Andric PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream *os, bool lineMarkers, 1110b57cec5SDimitry Andric bool defines, bool DumpIncludeDirectives, 112*0fca6ea1SDimitry Andric bool DumpEmbedDirectives, bool UseLineDirectives, 113*0fca6ea1SDimitry Andric bool MinimizeWhitespace, bool DirectivesOnly, 114*0fca6ea1SDimitry Andric bool KeepSystemIncludes) 1150b57cec5SDimitry Andric : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os), 1160b57cec5SDimitry Andric DisableLineMarkers(lineMarkers), DumpDefines(defines), 1170b57cec5SDimitry Andric DumpIncludeDirectives(DumpIncludeDirectives), 118*0fca6ea1SDimitry Andric DumpEmbedDirectives(DumpEmbedDirectives), 119349cc55cSDimitry Andric UseLineDirectives(UseLineDirectives), 1205f757f3fSDimitry Andric MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly), 121*0fca6ea1SDimitry Andric KeepSystemIncludes(KeepSystemIncludes), OrigOS(os), NumToksToSkip(0) { 1220b57cec5SDimitry Andric CurLine = 0; 1230b57cec5SDimitry Andric CurFilename += "<uninit>"; 1240b57cec5SDimitry Andric EmittedTokensOnThisLine = false; 1250b57cec5SDimitry Andric EmittedDirectiveOnThisLine = false; 1260b57cec5SDimitry Andric FileType = SrcMgr::C_User; 1270b57cec5SDimitry Andric Initialized = false; 1280b57cec5SDimitry Andric IsFirstFileEntered = false; 1295f757f3fSDimitry Andric if (KeepSystemIncludes) 1305f757f3fSDimitry Andric NullOS = std::make_unique<llvm::raw_null_ostream>(); 131349cc55cSDimitry Andric 132349cc55cSDimitry Andric PrevTok.startToken(); 133349cc55cSDimitry Andric PrevPrevTok.startToken(); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 136*0fca6ea1SDimitry Andric /// Returns true if #embed directives should be expanded into a comma- 137*0fca6ea1SDimitry Andric /// delimited list of integer constants or not. 138*0fca6ea1SDimitry Andric bool expandEmbedContents() const { return !DumpEmbedDirectives; } 139*0fca6ea1SDimitry Andric 140349cc55cSDimitry Andric bool isMinimizeWhitespace() const { return MinimizeWhitespace; } 141349cc55cSDimitry Andric 1420b57cec5SDimitry Andric void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } 1430b57cec5SDimitry Andric bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; } 1460b57cec5SDimitry Andric bool hasEmittedDirectiveOnThisLine() const { 1470b57cec5SDimitry Andric return EmittedDirectiveOnThisLine; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 150349cc55cSDimitry Andric /// Ensure that the output stream position is at the beginning of a new line 151349cc55cSDimitry Andric /// and inserts one if it does not. It is intended to ensure that directives 152349cc55cSDimitry Andric /// inserted by the directives not from the input source (such as #line) are 153349cc55cSDimitry Andric /// in the first column. To insert newlines that represent the input, use 154349cc55cSDimitry Andric /// MoveToLine(/*...*/, /*RequireStartOfLine=*/true). 155349cc55cSDimitry Andric void startNewLineIfNeeded(); 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric void FileChanged(SourceLocation Loc, FileChangeReason Reason, 1580b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType, 1590b57cec5SDimitry Andric FileID PrevFID) override; 160*0fca6ea1SDimitry Andric void EmbedDirective(SourceLocation HashLoc, StringRef FileName, bool IsAngled, 161*0fca6ea1SDimitry Andric OptionalFileEntryRef File, 162*0fca6ea1SDimitry Andric const LexEmbedParametersResult &Params) override; 1630b57cec5SDimitry Andric void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, 1640b57cec5SDimitry Andric StringRef FileName, bool IsAngled, 16581ad6265SDimitry Andric CharSourceRange FilenameRange, 166bdd1243dSDimitry Andric OptionalFileEntryRef File, StringRef SearchPath, 167*0fca6ea1SDimitry Andric StringRef RelativePath, const Module *SuggestedModule, 168*0fca6ea1SDimitry Andric bool ModuleImported, 1690b57cec5SDimitry Andric SrcMgr::CharacteristicKind FileType) override; 1700b57cec5SDimitry Andric void Ident(SourceLocation Loc, StringRef str) override; 1710b57cec5SDimitry Andric void PragmaMessage(SourceLocation Loc, StringRef Namespace, 1720b57cec5SDimitry Andric PragmaMessageKind Kind, StringRef Str) override; 1730b57cec5SDimitry Andric void PragmaDebug(SourceLocation Loc, StringRef DebugType) override; 1740b57cec5SDimitry Andric void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override; 1750b57cec5SDimitry Andric void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override; 1760b57cec5SDimitry Andric void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 1770b57cec5SDimitry Andric diag::Severity Map, StringRef Str) override; 178349cc55cSDimitry Andric void PragmaWarning(SourceLocation Loc, PragmaWarningSpecifier WarningSpec, 1790b57cec5SDimitry Andric ArrayRef<int> Ids) override; 1800b57cec5SDimitry Andric void PragmaWarningPush(SourceLocation Loc, int Level) override; 1810b57cec5SDimitry Andric void PragmaWarningPop(SourceLocation Loc) override; 1820b57cec5SDimitry Andric void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override; 1830b57cec5SDimitry Andric void PragmaExecCharsetPop(SourceLocation Loc) override; 1840b57cec5SDimitry Andric void PragmaAssumeNonNullBegin(SourceLocation Loc) override; 1850b57cec5SDimitry Andric void PragmaAssumeNonNullEnd(SourceLocation Loc) override; 1860b57cec5SDimitry Andric 187349cc55cSDimitry Andric /// Insert whitespace before emitting the next token. 188349cc55cSDimitry Andric /// 189349cc55cSDimitry Andric /// @param Tok Next token to be emitted. 190349cc55cSDimitry Andric /// @param RequireSpace Ensure at least one whitespace is emitted. Useful 191349cc55cSDimitry Andric /// if non-tokens have been emitted to the stream. 192349cc55cSDimitry Andric /// @param RequireSameLine Never emit newlines. Useful when semantics depend 193349cc55cSDimitry Andric /// on being on the same line, such as directives. 194349cc55cSDimitry Andric void HandleWhitespaceBeforeTok(const Token &Tok, bool RequireSpace, 195349cc55cSDimitry Andric bool RequireSameLine); 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric /// Move to the line of the provided source location. This will 198349cc55cSDimitry Andric /// return true if a newline was inserted or if 199349cc55cSDimitry Andric /// the requested location is the first token on the first line. 200349cc55cSDimitry Andric /// In these cases the next output will be the first column on the line and 201349cc55cSDimitry Andric /// make it possible to insert indention. The newline was inserted 202349cc55cSDimitry Andric /// implicitly when at the beginning of the file. 203349cc55cSDimitry Andric /// 204349cc55cSDimitry Andric /// @param Tok Token where to move to. 205349cc55cSDimitry Andric /// @param RequireStartOfLine Whether the next line depends on being in the 206349cc55cSDimitry Andric /// first column, such as a directive. 207349cc55cSDimitry Andric /// 208349cc55cSDimitry Andric /// @return Whether column adjustments are necessary. 209349cc55cSDimitry Andric bool MoveToLine(const Token &Tok, bool RequireStartOfLine) { 210349cc55cSDimitry Andric PresumedLoc PLoc = SM.getPresumedLoc(Tok.getLocation()); 211349cc55cSDimitry Andric unsigned TargetLine = PLoc.isValid() ? PLoc.getLine() : CurLine; 21281ad6265SDimitry Andric bool IsFirstInFile = 21381ad6265SDimitry Andric Tok.isAtStartOfLine() && PLoc.isValid() && PLoc.getLine() == 1; 214349cc55cSDimitry Andric return MoveToLine(TargetLine, RequireStartOfLine) || IsFirstInFile; 2150b57cec5SDimitry Andric } 216349cc55cSDimitry Andric 217349cc55cSDimitry Andric /// Move to the line of the provided source location. Returns true if a new 218349cc55cSDimitry Andric /// line was inserted. 219349cc55cSDimitry Andric bool MoveToLine(SourceLocation Loc, bool RequireStartOfLine) { 220349cc55cSDimitry Andric PresumedLoc PLoc = SM.getPresumedLoc(Loc); 221349cc55cSDimitry Andric unsigned TargetLine = PLoc.isValid() ? PLoc.getLine() : CurLine; 222349cc55cSDimitry Andric return MoveToLine(TargetLine, RequireStartOfLine); 223349cc55cSDimitry Andric } 224349cc55cSDimitry Andric bool MoveToLine(unsigned LineNo, bool RequireStartOfLine); 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, 2270b57cec5SDimitry Andric const Token &Tok) { 2280b57cec5SDimitry Andric return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok); 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric void WriteLineInfo(unsigned LineNo, const char *Extra=nullptr, 2310b57cec5SDimitry Andric unsigned ExtraLen=0); 2320b57cec5SDimitry Andric bool LineMarkersAreDisabled() const { return DisableLineMarkers; } 2330b57cec5SDimitry Andric void HandleNewlinesInToken(const char *TokStr, unsigned Len); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric /// MacroDefined - This hook is called whenever a macro definition is seen. 2360b57cec5SDimitry Andric void MacroDefined(const Token &MacroNameTok, 2370b57cec5SDimitry Andric const MacroDirective *MD) override; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric /// MacroUndefined - This hook is called whenever a macro #undef is seen. 2400b57cec5SDimitry Andric void MacroUndefined(const Token &MacroNameTok, 2410b57cec5SDimitry Andric const MacroDefinition &MD, 2420b57cec5SDimitry Andric const MacroDirective *Undef) override; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric void BeginModule(const Module *M); 2450b57cec5SDimitry Andric void EndModule(const Module *M); 246*0fca6ea1SDimitry Andric 247*0fca6ea1SDimitry Andric unsigned GetNumToksToSkip() const { return NumToksToSkip; } 248*0fca6ea1SDimitry Andric void ResetSkipToks() { NumToksToSkip = 0; } 2490b57cec5SDimitry Andric }; 2500b57cec5SDimitry Andric } // end anonymous namespace 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, 2530b57cec5SDimitry Andric const char *Extra, 2540b57cec5SDimitry Andric unsigned ExtraLen) { 255349cc55cSDimitry Andric startNewLineIfNeeded(); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric // Emit #line directives or GNU line markers depending on what mode we're in. 2580b57cec5SDimitry Andric if (UseLineDirectives) { 2595f757f3fSDimitry Andric *OS << "#line" << ' ' << LineNo << ' ' << '"'; 2605f757f3fSDimitry Andric OS->write_escaped(CurFilename); 2615f757f3fSDimitry Andric *OS << '"'; 2620b57cec5SDimitry Andric } else { 2635f757f3fSDimitry Andric *OS << '#' << ' ' << LineNo << ' ' << '"'; 2645f757f3fSDimitry Andric OS->write_escaped(CurFilename); 2655f757f3fSDimitry Andric *OS << '"'; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric if (ExtraLen) 2685f757f3fSDimitry Andric OS->write(Extra, ExtraLen); 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric if (FileType == SrcMgr::C_System) 2715f757f3fSDimitry Andric OS->write(" 3", 2); 2720b57cec5SDimitry Andric else if (FileType == SrcMgr::C_ExternCSystem) 2735f757f3fSDimitry Andric OS->write(" 3 4", 4); 2740b57cec5SDimitry Andric } 2755f757f3fSDimitry Andric *OS << '\n'; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric /// MoveToLine - Move the output to the source line specified by the location 2790b57cec5SDimitry Andric /// object. We can do this by emitting some number of \n's, or be emitting a 2800b57cec5SDimitry Andric /// #line directive. This returns false if already at the specified line, true 2810b57cec5SDimitry Andric /// if some newlines were emitted. 282349cc55cSDimitry Andric bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo, 283349cc55cSDimitry Andric bool RequireStartOfLine) { 284349cc55cSDimitry Andric // If it is required to start a new line or finish the current, insert 285349cc55cSDimitry Andric // vertical whitespace now and take it into account when moving to the 286349cc55cSDimitry Andric // expected line. 287349cc55cSDimitry Andric bool StartedNewLine = false; 288349cc55cSDimitry Andric if ((RequireStartOfLine && EmittedTokensOnThisLine) || 289349cc55cSDimitry Andric EmittedDirectiveOnThisLine) { 2905f757f3fSDimitry Andric *OS << '\n'; 291349cc55cSDimitry Andric StartedNewLine = true; 292349cc55cSDimitry Andric CurLine += 1; 293349cc55cSDimitry Andric EmittedTokensOnThisLine = false; 294349cc55cSDimitry Andric EmittedDirectiveOnThisLine = false; 295349cc55cSDimitry Andric } 296349cc55cSDimitry Andric 2970b57cec5SDimitry Andric // If this line is "close enough" to the original line, just print newlines, 2980b57cec5SDimitry Andric // otherwise print a #line directive. 299349cc55cSDimitry Andric if (CurLine == LineNo) { 300349cc55cSDimitry Andric // Nothing to do if we are already on the correct line. 301349cc55cSDimitry Andric } else if (MinimizeWhitespace && DisableLineMarkers) { 302349cc55cSDimitry Andric // With -E -P -fminimize-whitespace, don't emit anything if not necessary. 303349cc55cSDimitry Andric } else if (!StartedNewLine && LineNo - CurLine == 1) { 304349cc55cSDimitry Andric // Printing a single line has priority over printing a #line directive, even 305349cc55cSDimitry Andric // when minimizing whitespace which otherwise would print #line directives 306349cc55cSDimitry Andric // for every single line. 3075f757f3fSDimitry Andric *OS << '\n'; 308349cc55cSDimitry Andric StartedNewLine = true; 309349cc55cSDimitry Andric } else if (!DisableLineMarkers) { 310349cc55cSDimitry Andric if (LineNo - CurLine <= 8) { 3110b57cec5SDimitry Andric const char *NewLines = "\n\n\n\n\n\n\n\n"; 3125f757f3fSDimitry Andric OS->write(NewLines, LineNo - CurLine); 313349cc55cSDimitry Andric } else { 3140b57cec5SDimitry Andric // Emit a #line or line marker. 3150b57cec5SDimitry Andric WriteLineInfo(LineNo, nullptr, 0); 316349cc55cSDimitry Andric } 317349cc55cSDimitry Andric StartedNewLine = true; 318349cc55cSDimitry Andric } else if (EmittedTokensOnThisLine) { 319349cc55cSDimitry Andric // If we are not on the correct line and don't need to be line-correct, 320349cc55cSDimitry Andric // at least ensure we start on a new line. 3215f757f3fSDimitry Andric *OS << '\n'; 322349cc55cSDimitry Andric StartedNewLine = true; 323349cc55cSDimitry Andric } 324349cc55cSDimitry Andric 325349cc55cSDimitry Andric if (StartedNewLine) { 326349cc55cSDimitry Andric EmittedTokensOnThisLine = false; 327349cc55cSDimitry Andric EmittedDirectiveOnThisLine = false; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric CurLine = LineNo; 331349cc55cSDimitry Andric return StartedNewLine; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 334349cc55cSDimitry Andric void PrintPPOutputPPCallbacks::startNewLineIfNeeded() { 3350b57cec5SDimitry Andric if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) { 3365f757f3fSDimitry Andric *OS << '\n'; 3370b57cec5SDimitry Andric EmittedTokensOnThisLine = false; 3380b57cec5SDimitry Andric EmittedDirectiveOnThisLine = false; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric /// FileChanged - Whenever the preprocessor enters or exits a #include file 3430b57cec5SDimitry Andric /// it invokes this handler. Update our conception of the current source 3440b57cec5SDimitry Andric /// position. 3450b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, 3460b57cec5SDimitry Andric FileChangeReason Reason, 3470b57cec5SDimitry Andric SrcMgr::CharacteristicKind NewFileType, 3480b57cec5SDimitry Andric FileID PrevFID) { 3490b57cec5SDimitry Andric // Unless we are exiting a #include, make sure to skip ahead to the line the 3500b57cec5SDimitry Andric // #include directive was at. 3510b57cec5SDimitry Andric SourceManager &SourceMgr = SM; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); 3540b57cec5SDimitry Andric if (UserLoc.isInvalid()) 3550b57cec5SDimitry Andric return; 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric unsigned NewLine = UserLoc.getLine(); 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric if (Reason == PPCallbacks::EnterFile) { 3600b57cec5SDimitry Andric SourceLocation IncludeLoc = UserLoc.getIncludeLoc(); 3610b57cec5SDimitry Andric if (IncludeLoc.isValid()) 362349cc55cSDimitry Andric MoveToLine(IncludeLoc, /*RequireStartOfLine=*/false); 3630b57cec5SDimitry Andric } else if (Reason == PPCallbacks::SystemHeaderPragma) { 3640b57cec5SDimitry Andric // GCC emits the # directive for this directive on the line AFTER the 3650b57cec5SDimitry Andric // directive and emits a bunch of spaces that aren't needed. This is because 3660b57cec5SDimitry Andric // otherwise we will emit a line marker for THIS line, which requires an 3670b57cec5SDimitry Andric // extra blank line after the directive to avoid making all following lines 3680b57cec5SDimitry Andric // off by one. We can do better by simply incrementing NewLine here. 3690b57cec5SDimitry Andric NewLine += 1; 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric CurLine = NewLine; 3730b57cec5SDimitry Andric 3745f757f3fSDimitry Andric // In KeepSystemIncludes mode, redirect OS as needed. 3755f757f3fSDimitry Andric if (KeepSystemIncludes && (isSystem(FileType) != isSystem(NewFileType))) 3765f757f3fSDimitry Andric OS = isSystem(FileType) ? OrigOS : NullOS.get(); 3775f757f3fSDimitry Andric 3780b57cec5SDimitry Andric CurFilename.clear(); 3790b57cec5SDimitry Andric CurFilename += UserLoc.getFilename(); 3800b57cec5SDimitry Andric FileType = NewFileType; 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric if (DisableLineMarkers) { 383349cc55cSDimitry Andric if (!MinimizeWhitespace) 384349cc55cSDimitry Andric startNewLineIfNeeded(); 3850b57cec5SDimitry Andric return; 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric if (!Initialized) { 3890b57cec5SDimitry Andric WriteLineInfo(CurLine); 3900b57cec5SDimitry Andric Initialized = true; 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric // Do not emit an enter marker for the main file (which we expect is the first 3940b57cec5SDimitry Andric // entered file). This matches gcc, and improves compatibility with some tools 3950b57cec5SDimitry Andric // which track the # line markers as a way to determine when the preprocessed 3960b57cec5SDimitry Andric // output is in the context of the main file. 3970b57cec5SDimitry Andric if (Reason == PPCallbacks::EnterFile && !IsFirstFileEntered) { 3980b57cec5SDimitry Andric IsFirstFileEntered = true; 3990b57cec5SDimitry Andric return; 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric switch (Reason) { 4030b57cec5SDimitry Andric case PPCallbacks::EnterFile: 4040b57cec5SDimitry Andric WriteLineInfo(CurLine, " 1", 2); 4050b57cec5SDimitry Andric break; 4060b57cec5SDimitry Andric case PPCallbacks::ExitFile: 4070b57cec5SDimitry Andric WriteLineInfo(CurLine, " 2", 2); 4080b57cec5SDimitry Andric break; 4090b57cec5SDimitry Andric case PPCallbacks::SystemHeaderPragma: 4100b57cec5SDimitry Andric case PPCallbacks::RenameFile: 4110b57cec5SDimitry Andric WriteLineInfo(CurLine); 4120b57cec5SDimitry Andric break; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric 416*0fca6ea1SDimitry Andric void PrintPPOutputPPCallbacks::EmbedDirective( 417*0fca6ea1SDimitry Andric SourceLocation HashLoc, StringRef FileName, bool IsAngled, 418*0fca6ea1SDimitry Andric OptionalFileEntryRef File, const LexEmbedParametersResult &Params) { 419*0fca6ea1SDimitry Andric if (!DumpEmbedDirectives) 420*0fca6ea1SDimitry Andric return; 421*0fca6ea1SDimitry Andric 422*0fca6ea1SDimitry Andric // The EmbedDirective() callback is called before we produce the annotation 423*0fca6ea1SDimitry Andric // token stream for the directive. We skip printing the annotation tokens 424*0fca6ea1SDimitry Andric // within PrintPreprocessedTokens(), but we also need to skip the prefix, 425*0fca6ea1SDimitry Andric // suffix, and if_empty tokens as those are inserted directly into the token 426*0fca6ea1SDimitry Andric // stream and would otherwise be printed immediately after printing the 427*0fca6ea1SDimitry Andric // #embed directive. 428*0fca6ea1SDimitry Andric // 429*0fca6ea1SDimitry Andric // FIXME: counting tokens to skip is a kludge but we have no way to know 430*0fca6ea1SDimitry Andric // which tokens were inserted as part of the embed and which ones were 431*0fca6ea1SDimitry Andric // explicitly written by the user. 432*0fca6ea1SDimitry Andric MoveToLine(HashLoc, /*RequireStartOfLine=*/true); 433*0fca6ea1SDimitry Andric *OS << "#embed " << (IsAngled ? '<' : '"') << FileName 434*0fca6ea1SDimitry Andric << (IsAngled ? '>' : '"'); 435*0fca6ea1SDimitry Andric 436*0fca6ea1SDimitry Andric auto PrintToks = [&](llvm::ArrayRef<Token> Toks) { 437*0fca6ea1SDimitry Andric SmallString<128> SpellingBuffer; 438*0fca6ea1SDimitry Andric for (const Token &T : Toks) { 439*0fca6ea1SDimitry Andric if (T.hasLeadingSpace()) 440*0fca6ea1SDimitry Andric *OS << " "; 441*0fca6ea1SDimitry Andric *OS << PP.getSpelling(T, SpellingBuffer); 442*0fca6ea1SDimitry Andric } 443*0fca6ea1SDimitry Andric }; 444*0fca6ea1SDimitry Andric bool SkipAnnotToks = true; 445*0fca6ea1SDimitry Andric if (Params.MaybeIfEmptyParam) { 446*0fca6ea1SDimitry Andric *OS << " if_empty("; 447*0fca6ea1SDimitry Andric PrintToks(Params.MaybeIfEmptyParam->Tokens); 448*0fca6ea1SDimitry Andric *OS << ")"; 449*0fca6ea1SDimitry Andric // If the file is empty, we can skip those tokens. If the file is not 450*0fca6ea1SDimitry Andric // empty, we skip the annotation tokens. 451*0fca6ea1SDimitry Andric if (File && !File->getSize()) { 452*0fca6ea1SDimitry Andric NumToksToSkip += Params.MaybeIfEmptyParam->Tokens.size(); 453*0fca6ea1SDimitry Andric SkipAnnotToks = false; 454*0fca6ea1SDimitry Andric } 455*0fca6ea1SDimitry Andric } 456*0fca6ea1SDimitry Andric 457*0fca6ea1SDimitry Andric if (Params.MaybeLimitParam) { 458*0fca6ea1SDimitry Andric *OS << " limit(" << Params.MaybeLimitParam->Limit << ")"; 459*0fca6ea1SDimitry Andric } 460*0fca6ea1SDimitry Andric if (Params.MaybeOffsetParam) { 461*0fca6ea1SDimitry Andric *OS << " clang::offset(" << Params.MaybeOffsetParam->Offset << ")"; 462*0fca6ea1SDimitry Andric } 463*0fca6ea1SDimitry Andric if (Params.MaybePrefixParam) { 464*0fca6ea1SDimitry Andric *OS << " prefix("; 465*0fca6ea1SDimitry Andric PrintToks(Params.MaybePrefixParam->Tokens); 466*0fca6ea1SDimitry Andric *OS << ")"; 467*0fca6ea1SDimitry Andric NumToksToSkip += Params.MaybePrefixParam->Tokens.size(); 468*0fca6ea1SDimitry Andric } 469*0fca6ea1SDimitry Andric if (Params.MaybeSuffixParam) { 470*0fca6ea1SDimitry Andric *OS << " suffix("; 471*0fca6ea1SDimitry Andric PrintToks(Params.MaybeSuffixParam->Tokens); 472*0fca6ea1SDimitry Andric *OS << ")"; 473*0fca6ea1SDimitry Andric NumToksToSkip += Params.MaybeSuffixParam->Tokens.size(); 474*0fca6ea1SDimitry Andric } 475*0fca6ea1SDimitry Andric 476*0fca6ea1SDimitry Andric // We may need to skip the annotation token. 477*0fca6ea1SDimitry Andric if (SkipAnnotToks) 478*0fca6ea1SDimitry Andric NumToksToSkip++; 479*0fca6ea1SDimitry Andric 480*0fca6ea1SDimitry Andric *OS << " /* clang -E -dE */"; 481*0fca6ea1SDimitry Andric setEmittedDirectiveOnThisLine(); 482*0fca6ea1SDimitry Andric } 483*0fca6ea1SDimitry Andric 4840b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::InclusionDirective( 485bdd1243dSDimitry Andric SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, 486bdd1243dSDimitry Andric bool IsAngled, CharSourceRange FilenameRange, OptionalFileEntryRef File, 487*0fca6ea1SDimitry Andric StringRef SearchPath, StringRef RelativePath, const Module *SuggestedModule, 488*0fca6ea1SDimitry Andric bool ModuleImported, SrcMgr::CharacteristicKind FileType) { 4890b57cec5SDimitry Andric // In -dI mode, dump #include directives prior to dumping their content or 4905f757f3fSDimitry Andric // interpretation. Similar for -fkeep-system-includes. 4915f757f3fSDimitry Andric if (DumpIncludeDirectives || (KeepSystemIncludes && isSystem(FileType))) { 492349cc55cSDimitry Andric MoveToLine(HashLoc, /*RequireStartOfLine=*/true); 4930b57cec5SDimitry Andric const std::string TokenText = PP.getSpelling(IncludeTok); 4940b57cec5SDimitry Andric assert(!TokenText.empty()); 4955f757f3fSDimitry Andric *OS << "#" << TokenText << " " 4960b57cec5SDimitry Andric << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') 4975f757f3fSDimitry Andric << " /* clang -E " 4985f757f3fSDimitry Andric << (DumpIncludeDirectives ? "-dI" : "-fkeep-system-includes") 4995f757f3fSDimitry Andric << " */"; 5000b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric // When preprocessing, turn implicit imports into module import pragmas. 504*0fca6ea1SDimitry Andric if (ModuleImported) { 5050b57cec5SDimitry Andric switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { 5060b57cec5SDimitry Andric case tok::pp_include: 5070b57cec5SDimitry Andric case tok::pp_import: 5080b57cec5SDimitry Andric case tok::pp_include_next: 509349cc55cSDimitry Andric MoveToLine(HashLoc, /*RequireStartOfLine=*/true); 5105f757f3fSDimitry Andric *OS << "#pragma clang module import " 511*0fca6ea1SDimitry Andric << SuggestedModule->getFullModuleName(true) 5120b57cec5SDimitry Andric << " /* clang -E: implicit import for " 5130b57cec5SDimitry Andric << "#" << PP.getSpelling(IncludeTok) << " " 5140b57cec5SDimitry Andric << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') 5150b57cec5SDimitry Andric << " */"; 516349cc55cSDimitry Andric setEmittedDirectiveOnThisLine(); 5170b57cec5SDimitry Andric break; 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric case tok::pp___include_macros: 5200b57cec5SDimitry Andric // #__include_macros has no effect on a user of a preprocessed source 5210b57cec5SDimitry Andric // file; the only effect is on preprocessing. 5220b57cec5SDimitry Andric // 5230b57cec5SDimitry Andric // FIXME: That's not *quite* true: it causes the module in question to 5240b57cec5SDimitry Andric // be loaded, which can affect downstream diagnostics. 5250b57cec5SDimitry Andric break; 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric default: 5280b57cec5SDimitry Andric llvm_unreachable("unknown include directive kind"); 5290b57cec5SDimitry Andric break; 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric /// Handle entering the scope of a module during a module compilation. 5350b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::BeginModule(const Module *M) { 5360b57cec5SDimitry Andric startNewLineIfNeeded(); 5375f757f3fSDimitry Andric *OS << "#pragma clang module begin " << M->getFullModuleName(true); 5380b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric /// Handle leaving the scope of a module during a module compilation. 5420b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::EndModule(const Module *M) { 5430b57cec5SDimitry Andric startNewLineIfNeeded(); 5445f757f3fSDimitry Andric *OS << "#pragma clang module end /*" << M->getFullModuleName(true) << "*/"; 5450b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric /// Ident - Handle #ident directives when read by the preprocessor. 5490b57cec5SDimitry Andric /// 5500b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) { 551349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 5520b57cec5SDimitry Andric 5535f757f3fSDimitry Andric OS->write("#ident ", strlen("#ident ")); 5545f757f3fSDimitry Andric OS->write(S.begin(), S.size()); 555349cc55cSDimitry Andric setEmittedTokensOnThisLine(); 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric /// MacroDefined - This hook is called whenever a macro definition is seen. 5590b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, 5600b57cec5SDimitry Andric const MacroDirective *MD) { 5610b57cec5SDimitry Andric const MacroInfo *MI = MD->getMacroInfo(); 56281ad6265SDimitry Andric // Print out macro definitions in -dD mode and when we have -fdirectives-only 56381ad6265SDimitry Andric // for C++20 header units. 56481ad6265SDimitry Andric if ((!DumpDefines && !DirectivesOnly) || 5650b57cec5SDimitry Andric // Ignore __FILE__ etc. 56681ad6265SDimitry Andric MI->isBuiltinMacro()) 56781ad6265SDimitry Andric return; 5680b57cec5SDimitry Andric 56981ad6265SDimitry Andric SourceLocation DefLoc = MI->getDefinitionLoc(); 57081ad6265SDimitry Andric if (DirectivesOnly && !MI->isUsed()) { 57181ad6265SDimitry Andric SourceManager &SM = PP.getSourceManager(); 57281ad6265SDimitry Andric if (SM.isWrittenInBuiltinFile(DefLoc) || 57381ad6265SDimitry Andric SM.isWrittenInCommandLineFile(DefLoc)) 57481ad6265SDimitry Andric return; 57581ad6265SDimitry Andric } 57681ad6265SDimitry Andric MoveToLine(DefLoc, /*RequireStartOfLine=*/true); 5770b57cec5SDimitry Andric PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS); 5780b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5790b57cec5SDimitry Andric } 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, 5820b57cec5SDimitry Andric const MacroDefinition &MD, 5830b57cec5SDimitry Andric const MacroDirective *Undef) { 58481ad6265SDimitry Andric // Print out macro definitions in -dD mode and when we have -fdirectives-only 58581ad6265SDimitry Andric // for C++20 header units. 58681ad6265SDimitry Andric if (!DumpDefines && !DirectivesOnly) 58781ad6265SDimitry Andric return; 5880b57cec5SDimitry Andric 589349cc55cSDimitry Andric MoveToLine(MacroNameTok.getLocation(), /*RequireStartOfLine=*/true); 5905f757f3fSDimitry Andric *OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName(); 5910b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5945f757f3fSDimitry Andric static void outputPrintable(raw_ostream *OS, StringRef Str) { 5950b57cec5SDimitry Andric for (unsigned char Char : Str) { 5960b57cec5SDimitry Andric if (isPrintable(Char) && Char != '\\' && Char != '"') 5975f757f3fSDimitry Andric *OS << (char)Char; 5980b57cec5SDimitry Andric else // Output anything hard as an octal escape. 5995f757f3fSDimitry Andric *OS << '\\' 6000b57cec5SDimitry Andric << (char)('0' + ((Char >> 6) & 7)) 6010b57cec5SDimitry Andric << (char)('0' + ((Char >> 3) & 7)) 6020b57cec5SDimitry Andric << (char)('0' + ((Char >> 0) & 7)); 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, 6070b57cec5SDimitry Andric StringRef Namespace, 6080b57cec5SDimitry Andric PragmaMessageKind Kind, 6090b57cec5SDimitry Andric StringRef Str) { 610349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 6115f757f3fSDimitry Andric *OS << "#pragma "; 6120b57cec5SDimitry Andric if (!Namespace.empty()) 6135f757f3fSDimitry Andric *OS << Namespace << ' '; 6140b57cec5SDimitry Andric switch (Kind) { 6150b57cec5SDimitry Andric case PMK_Message: 6165f757f3fSDimitry Andric *OS << "message(\""; 6170b57cec5SDimitry Andric break; 6180b57cec5SDimitry Andric case PMK_Warning: 6195f757f3fSDimitry Andric *OS << "warning \""; 6200b57cec5SDimitry Andric break; 6210b57cec5SDimitry Andric case PMK_Error: 6225f757f3fSDimitry Andric *OS << "error \""; 6230b57cec5SDimitry Andric break; 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric outputPrintable(OS, Str); 6275f757f3fSDimitry Andric *OS << '"'; 6280b57cec5SDimitry Andric if (Kind == PMK_Message) 6295f757f3fSDimitry Andric *OS << ')'; 6300b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc, 6340b57cec5SDimitry Andric StringRef DebugType) { 635349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 6360b57cec5SDimitry Andric 6375f757f3fSDimitry Andric *OS << "#pragma clang __debug "; 6385f757f3fSDimitry Andric *OS << DebugType; 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 6440b57cec5SDimitry Andric PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { 645349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 6465f757f3fSDimitry Andric *OS << "#pragma " << Namespace << " diagnostic push"; 6470b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 6510b57cec5SDimitry Andric PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { 652349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 6535f757f3fSDimitry Andric *OS << "#pragma " << Namespace << " diagnostic pop"; 6540b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc, 6580b57cec5SDimitry Andric StringRef Namespace, 6590b57cec5SDimitry Andric diag::Severity Map, 6600b57cec5SDimitry Andric StringRef Str) { 661349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 6625f757f3fSDimitry Andric *OS << "#pragma " << Namespace << " diagnostic "; 6630b57cec5SDimitry Andric switch (Map) { 6640b57cec5SDimitry Andric case diag::Severity::Remark: 6655f757f3fSDimitry Andric *OS << "remark"; 6660b57cec5SDimitry Andric break; 6670b57cec5SDimitry Andric case diag::Severity::Warning: 6685f757f3fSDimitry Andric *OS << "warning"; 6690b57cec5SDimitry Andric break; 6700b57cec5SDimitry Andric case diag::Severity::Error: 6715f757f3fSDimitry Andric *OS << "error"; 6720b57cec5SDimitry Andric break; 6730b57cec5SDimitry Andric case diag::Severity::Ignored: 6745f757f3fSDimitry Andric *OS << "ignored"; 6750b57cec5SDimitry Andric break; 6760b57cec5SDimitry Andric case diag::Severity::Fatal: 6775f757f3fSDimitry Andric *OS << "fatal"; 6780b57cec5SDimitry Andric break; 6790b57cec5SDimitry Andric } 6805f757f3fSDimitry Andric *OS << " \"" << Str << '"'; 6810b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc, 685349cc55cSDimitry Andric PragmaWarningSpecifier WarningSpec, 6860b57cec5SDimitry Andric ArrayRef<int> Ids) { 687349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 688349cc55cSDimitry Andric 6895f757f3fSDimitry Andric *OS << "#pragma warning("; 690349cc55cSDimitry Andric switch(WarningSpec) { 6915f757f3fSDimitry Andric case PWS_Default: *OS << "default"; break; 6925f757f3fSDimitry Andric case PWS_Disable: *OS << "disable"; break; 6935f757f3fSDimitry Andric case PWS_Error: *OS << "error"; break; 6945f757f3fSDimitry Andric case PWS_Once: *OS << "once"; break; 6955f757f3fSDimitry Andric case PWS_Suppress: *OS << "suppress"; break; 6965f757f3fSDimitry Andric case PWS_Level1: *OS << '1'; break; 6975f757f3fSDimitry Andric case PWS_Level2: *OS << '2'; break; 6985f757f3fSDimitry Andric case PWS_Level3: *OS << '3'; break; 6995f757f3fSDimitry Andric case PWS_Level4: *OS << '4'; break; 700349cc55cSDimitry Andric } 7015f757f3fSDimitry Andric *OS << ':'; 702349cc55cSDimitry Andric 7030b57cec5SDimitry Andric for (ArrayRef<int>::iterator I = Ids.begin(), E = Ids.end(); I != E; ++I) 7045f757f3fSDimitry Andric *OS << ' ' << *I; 7055f757f3fSDimitry Andric *OS << ')'; 7060b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc, 7100b57cec5SDimitry Andric int Level) { 711349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 7125f757f3fSDimitry Andric *OS << "#pragma warning(push"; 7130b57cec5SDimitry Andric if (Level >= 0) 7145f757f3fSDimitry Andric *OS << ", " << Level; 7155f757f3fSDimitry Andric *OS << ')'; 7160b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { 720349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 7215f757f3fSDimitry Andric *OS << "#pragma warning(pop)"; 7220b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 7230b57cec5SDimitry Andric } 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc, 7260b57cec5SDimitry Andric StringRef Str) { 727349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 7285f757f3fSDimitry Andric *OS << "#pragma character_execution_set(push"; 7290b57cec5SDimitry Andric if (!Str.empty()) 7305f757f3fSDimitry Andric *OS << ", " << Str; 7315f757f3fSDimitry Andric *OS << ')'; 7320b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::PragmaExecCharsetPop(SourceLocation Loc) { 736349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 7375f757f3fSDimitry Andric *OS << "#pragma character_execution_set(pop)"; 7380b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 7420b57cec5SDimitry Andric PragmaAssumeNonNullBegin(SourceLocation Loc) { 743349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 7445f757f3fSDimitry Andric *OS << "#pragma clang assume_nonnull begin"; 7450b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric void PrintPPOutputPPCallbacks:: 7490b57cec5SDimitry Andric PragmaAssumeNonNullEnd(SourceLocation Loc) { 750349cc55cSDimitry Andric MoveToLine(Loc, /*RequireStartOfLine=*/true); 7515f757f3fSDimitry Andric *OS << "#pragma clang assume_nonnull end"; 7520b57cec5SDimitry Andric setEmittedDirectiveOnThisLine(); 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 755349cc55cSDimitry Andric void PrintPPOutputPPCallbacks::HandleWhitespaceBeforeTok(const Token &Tok, 756349cc55cSDimitry Andric bool RequireSpace, 757349cc55cSDimitry Andric bool RequireSameLine) { 758349cc55cSDimitry Andric // These tokens are not expanded to anything and don't need whitespace before 759349cc55cSDimitry Andric // them. 760349cc55cSDimitry Andric if (Tok.is(tok::eof) || 761349cc55cSDimitry Andric (Tok.isAnnotation() && !Tok.is(tok::annot_header_unit) && 76206c3fb27SDimitry Andric !Tok.is(tok::annot_module_begin) && !Tok.is(tok::annot_module_end) && 763*0fca6ea1SDimitry Andric !Tok.is(tok::annot_repl_input_end) && !Tok.is(tok::annot_embed))) 764349cc55cSDimitry Andric return; 7650b57cec5SDimitry Andric 766349cc55cSDimitry Andric // EmittedDirectiveOnThisLine takes priority over RequireSameLine. 767349cc55cSDimitry Andric if ((!RequireSameLine || EmittedDirectiveOnThisLine) && 768349cc55cSDimitry Andric MoveToLine(Tok, /*RequireStartOfLine=*/EmittedDirectiveOnThisLine)) { 769349cc55cSDimitry Andric if (MinimizeWhitespace) { 770349cc55cSDimitry Andric // Avoid interpreting hash as a directive under -fpreprocessed. 771349cc55cSDimitry Andric if (Tok.is(tok::hash)) 7725f757f3fSDimitry Andric *OS << ' '; 773349cc55cSDimitry Andric } else { 7740b57cec5SDimitry Andric // Print out space characters so that the first token on a line is 7750b57cec5SDimitry Andric // indented for easy reading. 7760b57cec5SDimitry Andric unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation()); 7770b57cec5SDimitry Andric 778349cc55cSDimitry Andric // The first token on a line can have a column number of 1, yet still 779349cc55cSDimitry Andric // expect leading white space, if a macro expansion in column 1 starts 780349cc55cSDimitry Andric // with an empty macro argument, or an empty nested macro expansion. In 781349cc55cSDimitry Andric // this case, move the token to column 2. 7820b57cec5SDimitry Andric if (ColNo == 1 && Tok.hasLeadingSpace()) 7830b57cec5SDimitry Andric ColNo = 2; 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric // This hack prevents stuff like: 7860b57cec5SDimitry Andric // #define HASH # 7870b57cec5SDimitry Andric // HASH define foo bar 7880b57cec5SDimitry Andric // From having the # character end up at column 1, which makes it so it 7890b57cec5SDimitry Andric // is not handled as a #define next time through the preprocessor if in 7900b57cec5SDimitry Andric // -fpreprocessed mode. 7910b57cec5SDimitry Andric if (ColNo <= 1 && Tok.is(tok::hash)) 7925f757f3fSDimitry Andric *OS << ' '; 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric // Otherwise, indent the appropriate number of spaces. 7950b57cec5SDimitry Andric for (; ColNo > 1; --ColNo) 7965f757f3fSDimitry Andric *OS << ' '; 797349cc55cSDimitry Andric } 798349cc55cSDimitry Andric } else { 799349cc55cSDimitry Andric // Insert whitespace between the previous and next token if either 800349cc55cSDimitry Andric // - The caller requires it 801349cc55cSDimitry Andric // - The input had whitespace between them and we are not in 802349cc55cSDimitry Andric // whitespace-minimization mode 803349cc55cSDimitry Andric // - The whitespace is necessary to keep the tokens apart and there is not 804349cc55cSDimitry Andric // already a newline between them 805349cc55cSDimitry Andric if (RequireSpace || (!MinimizeWhitespace && Tok.hasLeadingSpace()) || 806349cc55cSDimitry Andric ((EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) && 807349cc55cSDimitry Andric AvoidConcat(PrevPrevTok, PrevTok, Tok))) 8085f757f3fSDimitry Andric *OS << ' '; 809349cc55cSDimitry Andric } 8100b57cec5SDimitry Andric 811349cc55cSDimitry Andric PrevPrevTok = PrevTok; 812349cc55cSDimitry Andric PrevTok = Tok; 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric 8150b57cec5SDimitry Andric void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr, 8160b57cec5SDimitry Andric unsigned Len) { 8170b57cec5SDimitry Andric unsigned NumNewlines = 0; 8180b57cec5SDimitry Andric for (; Len; --Len, ++TokStr) { 8190b57cec5SDimitry Andric if (*TokStr != '\n' && 8200b57cec5SDimitry Andric *TokStr != '\r') 8210b57cec5SDimitry Andric continue; 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric ++NumNewlines; 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric // If we have \n\r or \r\n, skip both and count as one line. 8260b57cec5SDimitry Andric if (Len != 1 && 8270b57cec5SDimitry Andric (TokStr[1] == '\n' || TokStr[1] == '\r') && 8280b57cec5SDimitry Andric TokStr[0] != TokStr[1]) { 8290b57cec5SDimitry Andric ++TokStr; 8300b57cec5SDimitry Andric --Len; 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric if (NumNewlines == 0) return; 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric CurLine += NumNewlines; 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric namespace { 8410b57cec5SDimitry Andric struct UnknownPragmaHandler : public PragmaHandler { 8420b57cec5SDimitry Andric const char *Prefix; 8430b57cec5SDimitry Andric PrintPPOutputPPCallbacks *Callbacks; 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric // Set to true if tokens should be expanded 8460b57cec5SDimitry Andric bool ShouldExpandTokens; 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks, 8490b57cec5SDimitry Andric bool RequireTokenExpansion) 8500b57cec5SDimitry Andric : Prefix(prefix), Callbacks(callbacks), 8510b57cec5SDimitry Andric ShouldExpandTokens(RequireTokenExpansion) {} 8520b57cec5SDimitry Andric void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, 8530b57cec5SDimitry Andric Token &PragmaTok) override { 8540b57cec5SDimitry Andric // Figure out what line we went to and insert the appropriate number of 8550b57cec5SDimitry Andric // newline characters. 856349cc55cSDimitry Andric Callbacks->MoveToLine(PragmaTok.getLocation(), /*RequireStartOfLine=*/true); 8575f757f3fSDimitry Andric Callbacks->OS->write(Prefix, strlen(Prefix)); 858349cc55cSDimitry Andric Callbacks->setEmittedTokensOnThisLine(); 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric if (ShouldExpandTokens) { 8610b57cec5SDimitry Andric // The first token does not have expanded macros. Expand them, if 8620b57cec5SDimitry Andric // required. 863a7dea167SDimitry Andric auto Toks = std::make_unique<Token[]>(1); 8640b57cec5SDimitry Andric Toks[0] = PragmaTok; 8650b57cec5SDimitry Andric PP.EnterTokenStream(std::move(Toks), /*NumToks=*/1, 8660b57cec5SDimitry Andric /*DisableMacroExpansion=*/false, 8670b57cec5SDimitry Andric /*IsReinject=*/false); 8680b57cec5SDimitry Andric PP.Lex(PragmaTok); 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric // Read and print all of the pragma tokens. 872349cc55cSDimitry Andric bool IsFirst = true; 8730b57cec5SDimitry Andric while (PragmaTok.isNot(tok::eod)) { 874349cc55cSDimitry Andric Callbacks->HandleWhitespaceBeforeTok(PragmaTok, /*RequireSpace=*/IsFirst, 875349cc55cSDimitry Andric /*RequireSameLine=*/true); 876349cc55cSDimitry Andric IsFirst = false; 8770b57cec5SDimitry Andric std::string TokSpell = PP.getSpelling(PragmaTok); 8785f757f3fSDimitry Andric Callbacks->OS->write(&TokSpell[0], TokSpell.size()); 879349cc55cSDimitry Andric Callbacks->setEmittedTokensOnThisLine(); 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric if (ShouldExpandTokens) 8820b57cec5SDimitry Andric PP.Lex(PragmaTok); 8830b57cec5SDimitry Andric else 8840b57cec5SDimitry Andric PP.LexUnexpandedToken(PragmaTok); 8850b57cec5SDimitry Andric } 8860b57cec5SDimitry Andric Callbacks->setEmittedDirectiveOnThisLine(); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric }; 8890b57cec5SDimitry Andric } // end anonymous namespace 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, 8935f757f3fSDimitry Andric PrintPPOutputPPCallbacks *Callbacks) { 8940b57cec5SDimitry Andric bool DropComments = PP.getLangOpts().TraditionalCPP && 8950b57cec5SDimitry Andric !PP.getCommentRetentionState(); 8960b57cec5SDimitry Andric 897349cc55cSDimitry Andric bool IsStartOfLine = false; 8980b57cec5SDimitry Andric char Buffer[256]; 89904eeddc0SDimitry Andric while (true) { 900349cc55cSDimitry Andric // Two lines joined with line continuation ('\' as last character on the 901349cc55cSDimitry Andric // line) must be emitted as one line even though Tok.getLine() returns two 902349cc55cSDimitry Andric // different values. In this situation Tok.isAtStartOfLine() is false even 903349cc55cSDimitry Andric // though it may be the first token on the lexical line. When 904349cc55cSDimitry Andric // dropping/skipping a token that is at the start of a line, propagate the 905349cc55cSDimitry Andric // start-of-line-ness to the next token to not append it to the previous 906349cc55cSDimitry Andric // line. 907349cc55cSDimitry Andric IsStartOfLine = IsStartOfLine || Tok.isAtStartOfLine(); 9080b57cec5SDimitry Andric 909349cc55cSDimitry Andric Callbacks->HandleWhitespaceBeforeTok(Tok, /*RequireSpace=*/false, 910349cc55cSDimitry Andric /*RequireSameLine=*/!IsStartOfLine); 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric if (DropComments && Tok.is(tok::comment)) { 9130b57cec5SDimitry Andric // Skip comments. Normally the preprocessor does not generate 9140b57cec5SDimitry Andric // tok::comment nodes at all when not keeping comments, but under 9150b57cec5SDimitry Andric // -traditional-cpp the lexer keeps /all/ whitespace, including comments. 916349cc55cSDimitry Andric PP.Lex(Tok); 917349cc55cSDimitry Andric continue; 91806c3fb27SDimitry Andric } else if (Tok.is(tok::annot_repl_input_end)) { 91906c3fb27SDimitry Andric PP.Lex(Tok); 92006c3fb27SDimitry Andric continue; 9210b57cec5SDimitry Andric } else if (Tok.is(tok::eod)) { 9220b57cec5SDimitry Andric // Don't print end of directive tokens, since they are typically newlines 9230b57cec5SDimitry Andric // that mess up our line tracking. These come from unknown pre-processor 9240b57cec5SDimitry Andric // directives or hash-prefixed comments in standalone assembly files. 9250b57cec5SDimitry Andric PP.Lex(Tok); 926349cc55cSDimitry Andric // FIXME: The token on the next line after #include should have 927349cc55cSDimitry Andric // Tok.isAtStartOfLine() set. 928349cc55cSDimitry Andric IsStartOfLine = true; 9290b57cec5SDimitry Andric continue; 9300b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_include)) { 9310b57cec5SDimitry Andric // PrintPPOutputPPCallbacks::InclusionDirective handles producing 9320b57cec5SDimitry Andric // appropriate output here. Ignore this token entirely. 9330b57cec5SDimitry Andric PP.Lex(Tok); 934349cc55cSDimitry Andric IsStartOfLine = true; 9350b57cec5SDimitry Andric continue; 9360b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_begin)) { 9370b57cec5SDimitry Andric // FIXME: We retrieve this token after the FileChanged callback, and 9380b57cec5SDimitry Andric // retrieve the module_end token before the FileChanged callback, so 9390b57cec5SDimitry Andric // we render this within the file and render the module end outside the 9400b57cec5SDimitry Andric // file, but this is backwards from the token locations: the module_begin 9410b57cec5SDimitry Andric // token is at the include location (outside the file) and the module_end 9420b57cec5SDimitry Andric // token is at the EOF location (within the file). 9430b57cec5SDimitry Andric Callbacks->BeginModule( 9440b57cec5SDimitry Andric reinterpret_cast<Module *>(Tok.getAnnotationValue())); 9450b57cec5SDimitry Andric PP.Lex(Tok); 946349cc55cSDimitry Andric IsStartOfLine = true; 9470b57cec5SDimitry Andric continue; 9480b57cec5SDimitry Andric } else if (Tok.is(tok::annot_module_end)) { 9490b57cec5SDimitry Andric Callbacks->EndModule( 9500b57cec5SDimitry Andric reinterpret_cast<Module *>(Tok.getAnnotationValue())); 9510b57cec5SDimitry Andric PP.Lex(Tok); 952349cc55cSDimitry Andric IsStartOfLine = true; 9530b57cec5SDimitry Andric continue; 9540b57cec5SDimitry Andric } else if (Tok.is(tok::annot_header_unit)) { 9550b57cec5SDimitry Andric // This is a header-name that has been (effectively) converted into a 9560b57cec5SDimitry Andric // module-name. 9570b57cec5SDimitry Andric // FIXME: The module name could contain non-identifier module name 9580b57cec5SDimitry Andric // components. We don't have a good way to round-trip those. 9590b57cec5SDimitry Andric Module *M = reinterpret_cast<Module *>(Tok.getAnnotationValue()); 9600b57cec5SDimitry Andric std::string Name = M->getFullModuleName(); 9615f757f3fSDimitry Andric Callbacks->OS->write(Name.data(), Name.size()); 9620b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(Name.data(), Name.size()); 963*0fca6ea1SDimitry Andric } else if (Tok.is(tok::annot_embed)) { 964*0fca6ea1SDimitry Andric // Manually explode the binary data out to a stream of comma-delimited 965*0fca6ea1SDimitry Andric // integer values. If the user passed -dE, that is handled by the 966*0fca6ea1SDimitry Andric // EmbedDirective() callback. We should only get here if the user did not 967*0fca6ea1SDimitry Andric // pass -dE. 968*0fca6ea1SDimitry Andric assert(Callbacks->expandEmbedContents() && 969*0fca6ea1SDimitry Andric "did not expect an embed annotation"); 970*0fca6ea1SDimitry Andric auto *Data = 971*0fca6ea1SDimitry Andric reinterpret_cast<EmbedAnnotationData *>(Tok.getAnnotationValue()); 972*0fca6ea1SDimitry Andric 973*0fca6ea1SDimitry Andric // Loop over the contents and print them as a comma-delimited list of 974*0fca6ea1SDimitry Andric // values. 975*0fca6ea1SDimitry Andric bool PrintComma = false; 976*0fca6ea1SDimitry Andric for (auto Iter = Data->BinaryData.begin(), End = Data->BinaryData.end(); 977*0fca6ea1SDimitry Andric Iter != End; ++Iter) { 978*0fca6ea1SDimitry Andric if (PrintComma) 979*0fca6ea1SDimitry Andric *Callbacks->OS << ", "; 980*0fca6ea1SDimitry Andric *Callbacks->OS << static_cast<unsigned>(*Iter); 981*0fca6ea1SDimitry Andric PrintComma = true; 982*0fca6ea1SDimitry Andric } 983*0fca6ea1SDimitry Andric IsStartOfLine = true; 9840b57cec5SDimitry Andric } else if (Tok.isAnnotation()) { 9850b57cec5SDimitry Andric // Ignore annotation tokens created by pragmas - the pragmas themselves 9860b57cec5SDimitry Andric // will be reproduced in the preprocessed output. 9870b57cec5SDimitry Andric PP.Lex(Tok); 9880b57cec5SDimitry Andric continue; 9890b57cec5SDimitry Andric } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { 9905f757f3fSDimitry Andric *Callbacks->OS << II->getName(); 9910b57cec5SDimitry Andric } else if (Tok.isLiteral() && !Tok.needsCleaning() && 9920b57cec5SDimitry Andric Tok.getLiteralData()) { 9935f757f3fSDimitry Andric Callbacks->OS->write(Tok.getLiteralData(), Tok.getLength()); 994bdd1243dSDimitry Andric } else if (Tok.getLength() < std::size(Buffer)) { 9950b57cec5SDimitry Andric const char *TokPtr = Buffer; 9960b57cec5SDimitry Andric unsigned Len = PP.getSpelling(Tok, TokPtr); 9975f757f3fSDimitry Andric Callbacks->OS->write(TokPtr, Len); 9980b57cec5SDimitry Andric 9990b57cec5SDimitry Andric // Tokens that can contain embedded newlines need to adjust our current 10000b57cec5SDimitry Andric // line number. 1001349cc55cSDimitry Andric // FIXME: The token may end with a newline in which case 1002349cc55cSDimitry Andric // setEmittedDirectiveOnThisLine/setEmittedTokensOnThisLine afterwards is 1003349cc55cSDimitry Andric // wrong. 10040b57cec5SDimitry Andric if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) 10050b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(TokPtr, Len); 1006349cc55cSDimitry Andric if (Tok.is(tok::comment) && Len >= 2 && TokPtr[0] == '/' && 1007349cc55cSDimitry Andric TokPtr[1] == '/') { 1008349cc55cSDimitry Andric // It's a line comment; 1009349cc55cSDimitry Andric // Ensure that we don't concatenate anything behind it. 1010349cc55cSDimitry Andric Callbacks->setEmittedDirectiveOnThisLine(); 1011349cc55cSDimitry Andric } 10120b57cec5SDimitry Andric } else { 10130b57cec5SDimitry Andric std::string S = PP.getSpelling(Tok); 10145f757f3fSDimitry Andric Callbacks->OS->write(S.data(), S.size()); 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric // Tokens that can contain embedded newlines need to adjust our current 10170b57cec5SDimitry Andric // line number. 10180b57cec5SDimitry Andric if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) 10190b57cec5SDimitry Andric Callbacks->HandleNewlinesInToken(S.data(), S.size()); 1020349cc55cSDimitry Andric if (Tok.is(tok::comment) && S.size() >= 2 && S[0] == '/' && S[1] == '/') { 1021349cc55cSDimitry Andric // It's a line comment; 1022349cc55cSDimitry Andric // Ensure that we don't concatenate anything behind it. 1023349cc55cSDimitry Andric Callbacks->setEmittedDirectiveOnThisLine(); 1024349cc55cSDimitry Andric } 10250b57cec5SDimitry Andric } 10260b57cec5SDimitry Andric Callbacks->setEmittedTokensOnThisLine(); 1027349cc55cSDimitry Andric IsStartOfLine = false; 10280b57cec5SDimitry Andric 10290b57cec5SDimitry Andric if (Tok.is(tok::eof)) break; 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric PP.Lex(Tok); 1032*0fca6ea1SDimitry Andric // If lexing that token causes us to need to skip future tokens, do so now. 1033*0fca6ea1SDimitry Andric for (unsigned I = 0, Skip = Callbacks->GetNumToksToSkip(); I < Skip; ++I) 1034*0fca6ea1SDimitry Andric PP.Lex(Tok); 1035*0fca6ea1SDimitry Andric Callbacks->ResetSkipToks(); 10360b57cec5SDimitry Andric } 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric typedef std::pair<const IdentifierInfo *, MacroInfo *> id_macro_pair; 10400b57cec5SDimitry Andric static int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS) { 10410b57cec5SDimitry Andric return LHS->first->getName().compare(RHS->first->getName()); 10420b57cec5SDimitry Andric } 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) { 10450b57cec5SDimitry Andric // Ignore unknown pragmas. 10460b57cec5SDimitry Andric PP.IgnorePragmas(); 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric // -dM mode just scans and ignores all tokens in the files, then dumps out 10490b57cec5SDimitry Andric // the macro table at the end. 10500b57cec5SDimitry Andric PP.EnterMainSourceFile(); 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric Token Tok; 10530b57cec5SDimitry Andric do PP.Lex(Tok); 10540b57cec5SDimitry Andric while (Tok.isNot(tok::eof)); 10550b57cec5SDimitry Andric 10560b57cec5SDimitry Andric SmallVector<id_macro_pair, 128> MacrosByID; 10570b57cec5SDimitry Andric for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); 10580b57cec5SDimitry Andric I != E; ++I) { 10590b57cec5SDimitry Andric auto *MD = I->second.getLatest(); 10600b57cec5SDimitry Andric if (MD && MD->isDefined()) 10610b57cec5SDimitry Andric MacrosByID.push_back(id_macro_pair(I->first, MD->getMacroInfo())); 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare); 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) { 10660b57cec5SDimitry Andric MacroInfo &MI = *MacrosByID[i].second; 10670b57cec5SDimitry Andric // Ignore computed macros like __LINE__ and friends. 10680b57cec5SDimitry Andric if (MI.isBuiltinMacro()) continue; 10690b57cec5SDimitry Andric 10705f757f3fSDimitry Andric PrintMacroDefinition(*MacrosByID[i].first, MI, PP, OS); 10710b57cec5SDimitry Andric *OS << '\n'; 10720b57cec5SDimitry Andric } 10730b57cec5SDimitry Andric } 10740b57cec5SDimitry Andric 10750b57cec5SDimitry Andric /// DoPrintPreprocessedInput - This implements -E mode. 10760b57cec5SDimitry Andric /// 10770b57cec5SDimitry Andric void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, 10780b57cec5SDimitry Andric const PreprocessorOutputOptions &Opts) { 10790b57cec5SDimitry Andric // Show macros with no output is handled specially. 10800b57cec5SDimitry Andric if (!Opts.ShowCPP) { 10810b57cec5SDimitry Andric assert(Opts.ShowMacros && "Not yet implemented!"); 10820b57cec5SDimitry Andric DoPrintMacros(PP, OS); 10830b57cec5SDimitry Andric return; 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric // Inform the preprocessor whether we want it to retain comments or not, due 10870b57cec5SDimitry Andric // to -C or -CC. 10880b57cec5SDimitry Andric PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments); 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks( 10915f757f3fSDimitry Andric PP, OS, !Opts.ShowLineMarkers, Opts.ShowMacros, 1092*0fca6ea1SDimitry Andric Opts.ShowIncludeDirectives, Opts.ShowEmbedDirectives, 1093*0fca6ea1SDimitry Andric Opts.UseLineDirectives, Opts.MinimizeWhitespace, Opts.DirectivesOnly, 1094*0fca6ea1SDimitry Andric Opts.KeepSystemIncludes); 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric // Expand macros in pragmas with -fms-extensions. The assumption is that 10970b57cec5SDimitry Andric // the majority of pragmas in such a file will be Microsoft pragmas. 10980b57cec5SDimitry Andric // Remember the handlers we will add so that we can remove them later. 10990b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> MicrosoftExtHandler( 11000b57cec5SDimitry Andric new UnknownPragmaHandler( 11010b57cec5SDimitry Andric "#pragma", Callbacks, 11020b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> GCCHandler(new UnknownPragmaHandler( 11050b57cec5SDimitry Andric "#pragma GCC", Callbacks, 11060b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 11070b57cec5SDimitry Andric 11080b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> ClangHandler(new UnknownPragmaHandler( 11090b57cec5SDimitry Andric "#pragma clang", Callbacks, 11100b57cec5SDimitry Andric /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric PP.AddPragmaHandler(MicrosoftExtHandler.get()); 11130b57cec5SDimitry Andric PP.AddPragmaHandler("GCC", GCCHandler.get()); 11140b57cec5SDimitry Andric PP.AddPragmaHandler("clang", ClangHandler.get()); 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andric // The tokens after pragma omp need to be expanded. 11170b57cec5SDimitry Andric // 11180b57cec5SDimitry Andric // OpenMP [2.1, Directive format] 11190b57cec5SDimitry Andric // Preprocessing tokens following the #pragma omp are subject to macro 11200b57cec5SDimitry Andric // replacement. 11210b57cec5SDimitry Andric std::unique_ptr<UnknownPragmaHandler> OpenMPHandler( 11220b57cec5SDimitry Andric new UnknownPragmaHandler("#pragma omp", Callbacks, 11230b57cec5SDimitry Andric /*RequireTokenExpansion=*/true)); 11240b57cec5SDimitry Andric PP.AddPragmaHandler("omp", OpenMPHandler.get()); 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks)); 11270b57cec5SDimitry Andric 11280b57cec5SDimitry Andric // After we have configured the preprocessor, enter the main file. 11290b57cec5SDimitry Andric PP.EnterMainSourceFile(); 113081ad6265SDimitry Andric if (Opts.DirectivesOnly) 113181ad6265SDimitry Andric PP.SetMacroExpansionOnlyInDirectives(); 11320b57cec5SDimitry Andric 11330b57cec5SDimitry Andric // Consume all of the tokens that come from the predefines buffer. Those 11340b57cec5SDimitry Andric // should not be emitted into the output and are guaranteed to be at the 11350b57cec5SDimitry Andric // start. 11360b57cec5SDimitry Andric const SourceManager &SourceMgr = PP.getSourceManager(); 11370b57cec5SDimitry Andric Token Tok; 11380b57cec5SDimitry Andric do { 11390b57cec5SDimitry Andric PP.Lex(Tok); 11400b57cec5SDimitry Andric if (Tok.is(tok::eof) || !Tok.getLocation().isFileID()) 11410b57cec5SDimitry Andric break; 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); 11440b57cec5SDimitry Andric if (PLoc.isInvalid()) 11450b57cec5SDimitry Andric break; 11460b57cec5SDimitry Andric 11470b57cec5SDimitry Andric if (strcmp(PLoc.getFilename(), "<built-in>")) 11480b57cec5SDimitry Andric break; 11490b57cec5SDimitry Andric } while (true); 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andric // Read all the preprocessed tokens, printing them out to the stream. 11525f757f3fSDimitry Andric PrintPreprocessedTokens(PP, Tok, Callbacks); 11530b57cec5SDimitry Andric *OS << '\n'; 11540b57cec5SDimitry Andric 11550b57cec5SDimitry Andric // Remove the handlers we just added to leave the preprocessor in a sane state 11560b57cec5SDimitry Andric // so that it can be reused (for example by a clang::Parser instance). 11570b57cec5SDimitry Andric PP.RemovePragmaHandler(MicrosoftExtHandler.get()); 11580b57cec5SDimitry Andric PP.RemovePragmaHandler("GCC", GCCHandler.get()); 11590b57cec5SDimitry Andric PP.RemovePragmaHandler("clang", ClangHandler.get()); 11600b57cec5SDimitry Andric PP.RemovePragmaHandler("omp", OpenMPHandler.get()); 11610b57cec5SDimitry Andric } 1162