1193326Sed//===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This code simply runs the preprocessor on the input file and prints out the 11193326Sed// result. This is the traditional behavior of the -E option. 12193326Sed// 13193326Sed//===----------------------------------------------------------------------===// 14193326Sed 15193326Sed#include "clang/Frontend/Utils.h" 16252723Sdim#include "clang/Basic/CharInfo.h" 17199482Srdivacky#include "clang/Basic/Diagnostic.h" 18199482Srdivacky#include "clang/Basic/SourceManager.h" 19199482Srdivacky#include "clang/Frontend/PreprocessorOutputOptions.h" 20193326Sed#include "clang/Lex/MacroInfo.h" 21193326Sed#include "clang/Lex/PPCallbacks.h" 22199482Srdivacky#include "clang/Lex/Pragma.h" 23193326Sed#include "clang/Lex/Preprocessor.h" 24193326Sed#include "clang/Lex/TokenConcatenation.h" 25252723Sdim#include "llvm/ADT/STLExtras.h" 26193326Sed#include "llvm/ADT/SmallString.h" 27210299Sed#include "llvm/ADT/StringRef.h" 28252723Sdim#include "llvm/Support/ErrorHandling.h" 29193326Sed#include "llvm/Support/raw_ostream.h" 30193326Sed#include <cstdio> 31193326Sedusing namespace clang; 32193326Sed 33193326Sed/// PrintMacroDefinition - Print a macro definition in a form that will be 34193326Sed/// properly accepted back as a definition. 35193326Sedstatic void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, 36226890Sdim Preprocessor &PP, raw_ostream &OS) { 37193326Sed OS << "#define " << II.getName(); 38198092Srdivacky 39193326Sed if (MI.isFunctionLike()) { 40193326Sed OS << '('; 41200583Srdivacky if (!MI.arg_empty()) { 42193326Sed MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end(); 43200583Srdivacky for (; AI+1 != E; ++AI) { 44200583Srdivacky OS << (*AI)->getName(); 45200583Srdivacky OS << ','; 46200583Srdivacky } 47200583Srdivacky 48200583Srdivacky // Last argument. 49200583Srdivacky if ((*AI)->getName() == "__VA_ARGS__") 50200583Srdivacky OS << "..."; 51200583Srdivacky else 52200583Srdivacky OS << (*AI)->getName(); 53193326Sed } 54198092Srdivacky 55200583Srdivacky if (MI.isGNUVarargs()) 56200583Srdivacky OS << "..."; // #define foo(x...) 57204962Srdivacky 58193326Sed OS << ')'; 59193326Sed } 60198092Srdivacky 61193326Sed // GCC always emits a space, even if the macro body is empty. However, do not 62193326Sed // want to emit two spaces if the first token has a leading space. 63193326Sed if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace()) 64193326Sed OS << ' '; 65198092Srdivacky 66235633Sdim SmallString<128> SpellingBuffer; 67193326Sed for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end(); 68193326Sed I != E; ++I) { 69193326Sed if (I->hasLeadingSpace()) 70193326Sed OS << ' '; 71198092Srdivacky 72204643Srdivacky OS << PP.getSpelling(*I, SpellingBuffer); 73193326Sed } 74193326Sed} 75193326Sed 76193326Sed//===----------------------------------------------------------------------===// 77193326Sed// Preprocessed token printer 78193326Sed//===----------------------------------------------------------------------===// 79193326Sed 80193326Sednamespace { 81193326Sedclass PrintPPOutputPPCallbacks : public PPCallbacks { 82193326Sed Preprocessor &PP; 83207619Srdivacky SourceManager &SM; 84193326Sed TokenConcatenation ConcatInfo; 85193326Sedpublic: 86226890Sdim raw_ostream &OS; 87193326Sedprivate: 88193326Sed unsigned CurLine; 89212904Sdim 90193326Sed bool EmittedTokensOnThisLine; 91245431Sdim bool EmittedDirectiveOnThisLine; 92193326Sed SrcMgr::CharacteristicKind FileType; 93235633Sdim SmallString<512> CurFilename; 94193326Sed bool Initialized; 95193326Sed bool DisableLineMarkers; 96193326Sed bool DumpDefines; 97200583Srdivacky bool UseLineDirective; 98252723Sdim bool IsFirstFileEntered; 99193326Sedpublic: 100226890Sdim PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, 101218893Sdim bool lineMarkers, bool defines) 102207619Srdivacky : PP(pp), SM(PP.getSourceManager()), 103207619Srdivacky ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers), 104218893Sdim DumpDefines(defines) { 105218893Sdim CurLine = 0; 106193326Sed CurFilename += "<uninit>"; 107193326Sed EmittedTokensOnThisLine = false; 108245431Sdim EmittedDirectiveOnThisLine = false; 109193326Sed FileType = SrcMgr::C_User; 110193326Sed Initialized = false; 111252723Sdim IsFirstFileEntered = false; 112204962Srdivacky 113200583Srdivacky // If we're in microsoft mode, use normal #line instead of line markers. 114235633Sdim UseLineDirective = PP.getLangOpts().MicrosoftExt; 115193326Sed } 116198092Srdivacky 117245431Sdim void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } 118193326Sed bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } 119198092Srdivacky 120245431Sdim void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; } 121245431Sdim bool hasEmittedDirectiveOnThisLine() const { 122245431Sdim return EmittedDirectiveOnThisLine; 123245431Sdim } 124245431Sdim 125245431Sdim bool startNewLineIfNeeded(bool ShouldUpdateCurrentLine = true); 126218893Sdim 127193326Sed virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, 128226890Sdim SrcMgr::CharacteristicKind FileType, 129226890Sdim FileID PrevFID); 130252723Sdim virtual void InclusionDirective(SourceLocation HashLoc, 131252723Sdim const Token &IncludeTok, 132252723Sdim StringRef FileName, 133252723Sdim bool IsAngled, 134252723Sdim CharSourceRange FilenameRange, 135252723Sdim const FileEntry *File, 136252723Sdim StringRef SearchPath, 137252723Sdim StringRef RelativePath, 138252723Sdim const Module *Imported); 139193326Sed virtual void Ident(SourceLocation Loc, const std::string &str); 140252723Sdim virtual void PragmaCaptured(SourceLocation Loc, StringRef Str); 141198092Srdivacky virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, 142193326Sed const std::string &Str); 143263509Sdim virtual void PragmaDetectMismatch(SourceLocation Loc, 144263509Sdim const std::string &Name, 145263509Sdim const std::string &Value); 146252723Sdim virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace, 147252723Sdim PragmaMessageKind Kind, StringRef Str); 148252723Sdim virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType); 149224145Sdim virtual void PragmaDiagnosticPush(SourceLocation Loc, 150226890Sdim StringRef Namespace); 151224145Sdim virtual void PragmaDiagnosticPop(SourceLocation Loc, 152226890Sdim StringRef Namespace); 153226890Sdim virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 154226890Sdim diag::Mapping Map, StringRef Str); 155263509Sdim virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, 156263509Sdim ArrayRef<int> Ids); 157263509Sdim virtual void PragmaWarningPush(SourceLocation Loc, int Level); 158263509Sdim virtual void PragmaWarningPop(SourceLocation Loc); 159193326Sed 160193326Sed bool HandleFirstTokOnLine(Token &Tok); 161252723Sdim 162252723Sdim /// Move to the line of the provided source location. This will 163252723Sdim /// return true if the output stream required adjustment or if 164252723Sdim /// the requested location is on the first line. 165207619Srdivacky bool MoveToLine(SourceLocation Loc) { 166218893Sdim PresumedLoc PLoc = SM.getPresumedLoc(Loc); 167218893Sdim if (PLoc.isInvalid()) 168218893Sdim return false; 169252723Sdim return MoveToLine(PLoc.getLine()) || (PLoc.getLine() == 1); 170193326Sed } 171207619Srdivacky bool MoveToLine(unsigned LineNo); 172207619Srdivacky 173207619Srdivacky bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, 174207619Srdivacky const Token &Tok) { 175207619Srdivacky return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok); 176207619Srdivacky } 177193326Sed void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0); 178218893Sdim bool LineMarkersAreDisabled() const { return DisableLineMarkers; } 179194613Sed void HandleNewlinesInToken(const char *TokStr, unsigned Len); 180198092Srdivacky 181193326Sed /// MacroDefined - This hook is called whenever a macro definition is seen. 182252723Sdim void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD); 183198092Srdivacky 184212904Sdim /// MacroUndefined - This hook is called whenever a macro #undef is seen. 185252723Sdim void MacroUndefined(const Token &MacroNameTok, const MacroDirective *MD); 186193326Sed}; 187193326Sed} // end anonymous namespace 188193326Sed 189193326Sedvoid PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, 190193326Sed const char *Extra, 191193326Sed unsigned ExtraLen) { 192245431Sdim startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 193193326Sed 194200583Srdivacky // Emit #line directives or GNU line markers depending on what mode we're in. 195200583Srdivacky if (UseLineDirective) { 196200583Srdivacky OS << "#line" << ' ' << LineNo << ' ' << '"'; 197263509Sdim OS.write_escaped(CurFilename); 198200583Srdivacky OS << '"'; 199200583Srdivacky } else { 200200583Srdivacky OS << '#' << ' ' << LineNo << ' ' << '"'; 201263509Sdim OS.write_escaped(CurFilename); 202200583Srdivacky OS << '"'; 203204962Srdivacky 204200583Srdivacky if (ExtraLen) 205200583Srdivacky OS.write(Extra, ExtraLen); 206198092Srdivacky 207200583Srdivacky if (FileType == SrcMgr::C_System) 208200583Srdivacky OS.write(" 3", 2); 209200583Srdivacky else if (FileType == SrcMgr::C_ExternCSystem) 210200583Srdivacky OS.write(" 3 4", 4); 211200583Srdivacky } 212193326Sed OS << '\n'; 213193326Sed} 214193326Sed 215193326Sed/// MoveToLine - Move the output to the source line specified by the location 216193326Sed/// object. We can do this by emitting some number of \n's, or be emitting a 217193326Sed/// #line directive. This returns false if already at the specified line, true 218193326Sed/// if some newlines were emitted. 219207619Srdivackybool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) { 220193326Sed // If this line is "close enough" to the original line, just print newlines, 221193326Sed // otherwise print a #line directive. 222193326Sed if (LineNo-CurLine <= 8) { 223193326Sed if (LineNo-CurLine == 1) 224193326Sed OS << '\n'; 225193326Sed else if (LineNo == CurLine) 226224145Sdim return false; // Spelling line moved, but expansion line didn't. 227193326Sed else { 228193326Sed const char *NewLines = "\n\n\n\n\n\n\n\n"; 229193326Sed OS.write(NewLines, LineNo-CurLine); 230193326Sed } 231210299Sed } else if (!DisableLineMarkers) { 232210299Sed // Emit a #line or line marker. 233210299Sed WriteLineInfo(LineNo, 0, 0); 234193326Sed } else { 235210299Sed // Okay, we're in -P mode, which turns off line markers. However, we still 236210299Sed // need to emit a newline between tokens on different lines. 237245431Sdim startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 238198092Srdivacky } 239193326Sed 240198092Srdivacky CurLine = LineNo; 241193326Sed return true; 242193326Sed} 243193326Sed 244245431Sdimbool 245245431SdimPrintPPOutputPPCallbacks::startNewLineIfNeeded(bool ShouldUpdateCurrentLine) { 246245431Sdim if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) { 247218893Sdim OS << '\n'; 248218893Sdim EmittedTokensOnThisLine = false; 249245431Sdim EmittedDirectiveOnThisLine = false; 250245431Sdim if (ShouldUpdateCurrentLine) 251245431Sdim ++CurLine; 252218893Sdim return true; 253218893Sdim } 254218893Sdim 255218893Sdim return false; 256218893Sdim} 257193326Sed 258193326Sed/// FileChanged - Whenever the preprocessor enters or exits a #include file 259193326Sed/// it invokes this handler. Update our conception of the current source 260193326Sed/// position. 261193326Sedvoid PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, 262193326Sed FileChangeReason Reason, 263226890Sdim SrcMgr::CharacteristicKind NewFileType, 264226890Sdim FileID PrevFID) { 265193326Sed // Unless we are exiting a #include, make sure to skip ahead to the line the 266193326Sed // #include directive was at. 267207619Srdivacky SourceManager &SourceMgr = SM; 268207619Srdivacky 269207619Srdivacky PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); 270218893Sdim if (UserLoc.isInvalid()) 271218893Sdim return; 272218893Sdim 273207619Srdivacky unsigned NewLine = UserLoc.getLine(); 274212904Sdim 275193326Sed if (Reason == PPCallbacks::EnterFile) { 276218893Sdim SourceLocation IncludeLoc = UserLoc.getIncludeLoc(); 277193326Sed if (IncludeLoc.isValid()) 278193326Sed MoveToLine(IncludeLoc); 279193326Sed } else if (Reason == PPCallbacks::SystemHeaderPragma) { 280252723Sdim // GCC emits the # directive for this directive on the line AFTER the 281252723Sdim // directive and emits a bunch of spaces that aren't needed. This is because 282252723Sdim // otherwise we will emit a line marker for THIS line, which requires an 283252723Sdim // extra blank line after the directive to avoid making all following lines 284252723Sdim // off by one. We can do better by simply incrementing NewLine here. 285252723Sdim NewLine += 1; 286193326Sed } 287207619Srdivacky 288207619Srdivacky CurLine = NewLine; 289198092Srdivacky 290193326Sed CurFilename.clear(); 291207619Srdivacky CurFilename += UserLoc.getFilename(); 292193326Sed FileType = NewFileType; 293193326Sed 294252723Sdim if (DisableLineMarkers) { 295252723Sdim startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); 296252723Sdim return; 297252723Sdim } 298212904Sdim 299193326Sed if (!Initialized) { 300193326Sed WriteLineInfo(CurLine); 301193326Sed Initialized = true; 302193326Sed } 303193326Sed 304252723Sdim // Do not emit an enter marker for the main file (which we expect is the first 305252723Sdim // entered file). This matches gcc, and improves compatibility with some tools 306252723Sdim // which track the # line markers as a way to determine when the preprocessed 307252723Sdim // output is in the context of the main file. 308252723Sdim if (Reason == PPCallbacks::EnterFile && !IsFirstFileEntered) { 309252723Sdim IsFirstFileEntered = true; 310252723Sdim return; 311252723Sdim } 312252723Sdim 313193326Sed switch (Reason) { 314193326Sed case PPCallbacks::EnterFile: 315193326Sed WriteLineInfo(CurLine, " 1", 2); 316193326Sed break; 317193326Sed case PPCallbacks::ExitFile: 318193326Sed WriteLineInfo(CurLine, " 2", 2); 319193326Sed break; 320198092Srdivacky case PPCallbacks::SystemHeaderPragma: 321198092Srdivacky case PPCallbacks::RenameFile: 322193326Sed WriteLineInfo(CurLine); 323193326Sed break; 324193326Sed } 325193326Sed} 326193326Sed 327252723Sdimvoid PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc, 328252723Sdim const Token &IncludeTok, 329252723Sdim StringRef FileName, 330252723Sdim bool IsAngled, 331252723Sdim CharSourceRange FilenameRange, 332252723Sdim const FileEntry *File, 333252723Sdim StringRef SearchPath, 334252723Sdim StringRef RelativePath, 335252723Sdim const Module *Imported) { 336252723Sdim // When preprocessing, turn implicit imports into @imports. 337252723Sdim // FIXME: This is a stop-gap until a more comprehensive "preprocessing with 338252723Sdim // modules" solution is introduced. 339252723Sdim if (Imported) { 340252723Sdim startNewLineIfNeeded(); 341252723Sdim MoveToLine(HashLoc); 342252723Sdim OS << "@import " << Imported->getFullModuleName() << ";" 343252723Sdim << " /* clang -E: implicit import for \"" << File->getName() << "\" */"; 344252723Sdim EmittedTokensOnThisLine = true; 345252723Sdim } 346252723Sdim} 347252723Sdim 348193326Sed/// Ident - Handle #ident directives when read by the preprocessor. 349193326Sed/// 350193326Sedvoid PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) { 351193326Sed MoveToLine(Loc); 352198092Srdivacky 353193326Sed OS.write("#ident ", strlen("#ident ")); 354193326Sed OS.write(&S[0], S.size()); 355193326Sed EmittedTokensOnThisLine = true; 356193326Sed} 357193326Sed 358252723Sdimvoid PrintPPOutputPPCallbacks::PragmaCaptured(SourceLocation Loc, 359252723Sdim StringRef Str) { 360252723Sdim startNewLineIfNeeded(); 361252723Sdim MoveToLine(Loc); 362252723Sdim OS << "#pragma captured"; 363252723Sdim 364252723Sdim setEmittedDirectiveOnThisLine(); 365252723Sdim} 366252723Sdim 367193326Sed/// MacroDefined - This hook is called whenever a macro definition is seen. 368218893Sdimvoid PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, 369252723Sdim const MacroDirective *MD) { 370252723Sdim const MacroInfo *MI = MD->getMacroInfo(); 371193326Sed // Only print out macro definitions in -dD mode. 372193326Sed if (!DumpDefines || 373193326Sed // Ignore __FILE__ etc. 374193326Sed MI->isBuiltinMacro()) return; 375198092Srdivacky 376193326Sed MoveToLine(MI->getDefinitionLoc()); 377218893Sdim PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS); 378245431Sdim setEmittedDirectiveOnThisLine(); 379193326Sed} 380193326Sed 381218893Sdimvoid PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, 382252723Sdim const MacroDirective *MD) { 383212904Sdim // Only print out macro definitions in -dD mode. 384212904Sdim if (!DumpDefines) return; 385193326Sed 386218893Sdim MoveToLine(MacroNameTok.getLocation()); 387218893Sdim OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName(); 388245431Sdim setEmittedDirectiveOnThisLine(); 389212904Sdim} 390212904Sdim 391263509Sdimstatic void outputPrintable(llvm::raw_ostream& OS, 392193326Sed const std::string &Str) { 393193326Sed for (unsigned i = 0, e = Str.size(); i != e; ++i) { 394193326Sed unsigned char Char = Str[i]; 395252723Sdim if (isPrintable(Char) && Char != '\\' && Char != '"') 396193326Sed OS << (char)Char; 397193326Sed else // Output anything hard as an octal escape. 398193326Sed OS << '\\' 399193326Sed << (char)('0'+ ((Char >> 6) & 7)) 400193326Sed << (char)('0'+ ((Char >> 3) & 7)) 401193326Sed << (char)('0'+ ((Char >> 0) & 7)); 402193326Sed } 403263509Sdim} 404263509Sdim 405263509Sdimvoid PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, 406263509Sdim const IdentifierInfo *Kind, 407263509Sdim const std::string &Str) { 408263509Sdim startNewLineIfNeeded(); 409263509Sdim MoveToLine(Loc); 410263509Sdim OS << "#pragma comment(" << Kind->getName(); 411263509Sdim 412263509Sdim if (!Str.empty()) { 413263509Sdim OS << ", \""; 414263509Sdim outputPrintable(OS, Str); 415193326Sed OS << '"'; 416193326Sed } 417198092Srdivacky 418193326Sed OS << ')'; 419245431Sdim setEmittedDirectiveOnThisLine(); 420193326Sed} 421193326Sed 422263509Sdimvoid PrintPPOutputPPCallbacks::PragmaDetectMismatch(SourceLocation Loc, 423263509Sdim const std::string &Name, 424263509Sdim const std::string &Value) { 425263509Sdim startNewLineIfNeeded(); 426263509Sdim MoveToLine(Loc); 427263509Sdim OS << "#pragma detect_mismatch(\"" << Name << '"'; 428263509Sdim outputPrintable(OS, Name); 429263509Sdim OS << "\", \""; 430263509Sdim outputPrintable(OS, Value); 431263509Sdim OS << "\")"; 432263509Sdim setEmittedDirectiveOnThisLine(); 433263509Sdim} 434263509Sdim 435210299Sedvoid PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, 436252723Sdim StringRef Namespace, 437252723Sdim PragmaMessageKind Kind, 438226890Sdim StringRef Str) { 439245431Sdim startNewLineIfNeeded(); 440210299Sed MoveToLine(Loc); 441252723Sdim OS << "#pragma "; 442252723Sdim if (!Namespace.empty()) 443252723Sdim OS << Namespace << ' '; 444252723Sdim switch (Kind) { 445252723Sdim case PMK_Message: 446252723Sdim OS << "message(\""; 447252723Sdim break; 448252723Sdim case PMK_Warning: 449252723Sdim OS << "warning \""; 450252723Sdim break; 451252723Sdim case PMK_Error: 452252723Sdim OS << "error \""; 453252723Sdim break; 454252723Sdim } 455193326Sed 456263509Sdim outputPrintable(OS, Str); 457210299Sed OS << '"'; 458252723Sdim if (Kind == PMK_Message) 459252723Sdim OS << ')'; 460252723Sdim setEmittedDirectiveOnThisLine(); 461252723Sdim} 462210299Sed 463252723Sdimvoid PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc, 464252723Sdim StringRef DebugType) { 465252723Sdim startNewLineIfNeeded(); 466252723Sdim MoveToLine(Loc); 467252723Sdim 468252723Sdim OS << "#pragma clang __debug "; 469252723Sdim OS << DebugType; 470252723Sdim 471245431Sdim setEmittedDirectiveOnThisLine(); 472210299Sed} 473210299Sed 474224145Sdimvoid PrintPPOutputPPCallbacks:: 475226890SdimPragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { 476245431Sdim startNewLineIfNeeded(); 477224145Sdim MoveToLine(Loc); 478224145Sdim OS << "#pragma " << Namespace << " diagnostic push"; 479245431Sdim setEmittedDirectiveOnThisLine(); 480224145Sdim} 481210299Sed 482224145Sdimvoid PrintPPOutputPPCallbacks:: 483226890SdimPragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { 484245431Sdim startNewLineIfNeeded(); 485224145Sdim MoveToLine(Loc); 486224145Sdim OS << "#pragma " << Namespace << " diagnostic pop"; 487245431Sdim setEmittedDirectiveOnThisLine(); 488224145Sdim} 489224145Sdim 490224145Sdimvoid PrintPPOutputPPCallbacks:: 491226890SdimPragmaDiagnostic(SourceLocation Loc, StringRef Namespace, 492226890Sdim diag::Mapping Map, StringRef Str) { 493245431Sdim startNewLineIfNeeded(); 494224145Sdim MoveToLine(Loc); 495224145Sdim OS << "#pragma " << Namespace << " diagnostic "; 496224145Sdim switch (Map) { 497224145Sdim case diag::MAP_WARNING: 498224145Sdim OS << "warning"; 499224145Sdim break; 500224145Sdim case diag::MAP_ERROR: 501224145Sdim OS << "error"; 502224145Sdim break; 503224145Sdim case diag::MAP_IGNORE: 504224145Sdim OS << "ignored"; 505224145Sdim break; 506224145Sdim case diag::MAP_FATAL: 507224145Sdim OS << "fatal"; 508224145Sdim break; 509224145Sdim } 510224145Sdim OS << " \"" << Str << '"'; 511245431Sdim setEmittedDirectiveOnThisLine(); 512224145Sdim} 513224145Sdim 514263509Sdimvoid PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc, 515263509Sdim StringRef WarningSpec, 516263509Sdim ArrayRef<int> Ids) { 517263509Sdim startNewLineIfNeeded(); 518263509Sdim MoveToLine(Loc); 519263509Sdim OS << "#pragma warning(" << WarningSpec << ':'; 520263509Sdim for (ArrayRef<int>::iterator I = Ids.begin(), E = Ids.end(); I != E; ++I) 521263509Sdim OS << ' ' << *I; 522263509Sdim OS << ')'; 523263509Sdim setEmittedDirectiveOnThisLine(); 524263509Sdim} 525263509Sdim 526263509Sdimvoid PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc, 527263509Sdim int Level) { 528263509Sdim startNewLineIfNeeded(); 529263509Sdim MoveToLine(Loc); 530263509Sdim OS << "#pragma warning(push"; 531263509Sdim if (Level >= 0) 532263509Sdim OS << ", " << Level; 533263509Sdim OS << ')'; 534263509Sdim setEmittedDirectiveOnThisLine(); 535263509Sdim} 536263509Sdim 537263509Sdimvoid PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { 538263509Sdim startNewLineIfNeeded(); 539263509Sdim MoveToLine(Loc); 540263509Sdim OS << "#pragma warning(pop)"; 541263509Sdim setEmittedDirectiveOnThisLine(); 542263509Sdim} 543263509Sdim 544193326Sed/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this 545193326Sed/// is called for the first token on each new line. If this really is the start 546193326Sed/// of a new logical line, handle it and return true, otherwise return false. 547193326Sed/// This may not be the start of a logical line because the "start of line" 548224145Sdim/// marker is set for spelling lines, not expansion ones. 549193326Sedbool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { 550193326Sed // Figure out what line we went to and insert the appropriate number of 551193326Sed // newline characters. 552193326Sed if (!MoveToLine(Tok.getLocation())) 553193326Sed return false; 554198092Srdivacky 555193326Sed // Print out space characters so that the first token on a line is 556193326Sed // indented for easy reading. 557226890Sdim unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation()); 558198092Srdivacky 559193326Sed // This hack prevents stuff like: 560193326Sed // #define HASH # 561193326Sed // HASH define foo bar 562193326Sed // From having the # character end up at column 1, which makes it so it 563193326Sed // is not handled as a #define next time through the preprocessor if in 564193326Sed // -fpreprocessed mode. 565193326Sed if (ColNo <= 1 && Tok.is(tok::hash)) 566193326Sed OS << ' '; 567198092Srdivacky 568193326Sed // Otherwise, indent the appropriate number of spaces. 569193326Sed for (; ColNo > 1; --ColNo) 570193326Sed OS << ' '; 571198092Srdivacky 572193326Sed return true; 573193326Sed} 574193326Sed 575194613Sedvoid PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr, 576194613Sed unsigned Len) { 577194613Sed unsigned NumNewlines = 0; 578194613Sed for (; Len; --Len, ++TokStr) { 579194613Sed if (*TokStr != '\n' && 580194613Sed *TokStr != '\r') 581194613Sed continue; 582198092Srdivacky 583194613Sed ++NumNewlines; 584198092Srdivacky 585194613Sed // If we have \n\r or \r\n, skip both and count as one line. 586194613Sed if (Len != 1 && 587194613Sed (TokStr[1] == '\n' || TokStr[1] == '\r') && 588194613Sed TokStr[0] != TokStr[1]) 589194613Sed ++TokStr, --Len; 590194613Sed } 591198092Srdivacky 592194613Sed if (NumNewlines == 0) return; 593198092Srdivacky 594194613Sed CurLine += NumNewlines; 595194613Sed} 596194613Sed 597194613Sed 598193326Sednamespace { 599193326Sedstruct UnknownPragmaHandler : public PragmaHandler { 600193326Sed const char *Prefix; 601193326Sed PrintPPOutputPPCallbacks *Callbacks; 602198092Srdivacky 603193326Sed UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks) 604210299Sed : Prefix(prefix), Callbacks(callbacks) {} 605218893Sdim virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, 606218893Sdim Token &PragmaTok) { 607193326Sed // Figure out what line we went to and insert the appropriate number of 608193326Sed // newline characters. 609245431Sdim Callbacks->startNewLineIfNeeded(); 610193326Sed Callbacks->MoveToLine(PragmaTok.getLocation()); 611193326Sed Callbacks->OS.write(Prefix, strlen(Prefix)); 612193326Sed // Read and print all of the pragma tokens. 613221345Sdim while (PragmaTok.isNot(tok::eod)) { 614193326Sed if (PragmaTok.hasLeadingSpace()) 615193326Sed Callbacks->OS << ' '; 616193326Sed std::string TokSpell = PP.getSpelling(PragmaTok); 617193326Sed Callbacks->OS.write(&TokSpell[0], TokSpell.size()); 618193326Sed PP.LexUnexpandedToken(PragmaTok); 619193326Sed } 620245431Sdim Callbacks->setEmittedDirectiveOnThisLine(); 621193326Sed } 622193326Sed}; 623193326Sed} // end anonymous namespace 624193326Sed 625193326Sed 626193326Sedstatic void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, 627193326Sed PrintPPOutputPPCallbacks *Callbacks, 628226890Sdim raw_ostream &OS) { 629252723Sdim bool DropComments = PP.getLangOpts().TraditionalCPP && 630252723Sdim !PP.getCommentRetentionState(); 631252723Sdim 632193326Sed char Buffer[256]; 633210299Sed Token PrevPrevTok, PrevTok; 634210299Sed PrevPrevTok.startToken(); 635210299Sed PrevTok.startToken(); 636193326Sed while (1) { 637245431Sdim if (Callbacks->hasEmittedDirectiveOnThisLine()) { 638245431Sdim Callbacks->startNewLineIfNeeded(); 639245431Sdim Callbacks->MoveToLine(Tok.getLocation()); 640245431Sdim } 641198092Srdivacky 642193326Sed // If this token is at the start of a line, emit newlines if needed. 643193326Sed if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) { 644193326Sed // done. 645198092Srdivacky } else if (Tok.hasLeadingSpace() || 646193326Sed // If we haven't emitted a token on this line yet, PrevTok isn't 647193326Sed // useful to look at and no concatenation could happen anyway. 648193326Sed (Callbacks->hasEmittedTokensOnThisLine() && 649193326Sed // Don't print "-" next to "-", it would form "--". 650207619Srdivacky Callbacks->AvoidConcat(PrevPrevTok, PrevTok, Tok))) { 651193326Sed OS << ' '; 652193326Sed } 653198092Srdivacky 654252723Sdim if (DropComments && Tok.is(tok::comment)) { 655252723Sdim // Skip comments. Normally the preprocessor does not generate 656252723Sdim // tok::comment nodes at all when not keeping comments, but under 657252723Sdim // -traditional-cpp the lexer keeps /all/ whitespace, including comments. 658252723Sdim SourceLocation StartLoc = Tok.getLocation(); 659252723Sdim Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength())); 660263509Sdim } else if (Tok.is(tok::annot_module_include)) { 661263509Sdim // PrintPPOutputPPCallbacks::InclusionDirective handles producing 662263509Sdim // appropriate output here. Ignore this token entirely. 663263509Sdim PP.Lex(Tok); 664263509Sdim continue; 665252723Sdim } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { 666198398Srdivacky OS << II->getName(); 667193326Sed } else if (Tok.isLiteral() && !Tok.needsCleaning() && 668193326Sed Tok.getLiteralData()) { 669193326Sed OS.write(Tok.getLiteralData(), Tok.getLength()); 670193326Sed } else if (Tok.getLength() < 256) { 671193326Sed const char *TokPtr = Buffer; 672193326Sed unsigned Len = PP.getSpelling(Tok, TokPtr); 673193326Sed OS.write(TokPtr, Len); 674198092Srdivacky 675194613Sed // Tokens that can contain embedded newlines need to adjust our current 676198092Srdivacky // line number. 677252723Sdim if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) 678194613Sed Callbacks->HandleNewlinesInToken(TokPtr, Len); 679193326Sed } else { 680193326Sed std::string S = PP.getSpelling(Tok); 681193326Sed OS.write(&S[0], S.size()); 682198092Srdivacky 683194613Sed // Tokens that can contain embedded newlines need to adjust our current 684198092Srdivacky // line number. 685252723Sdim if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) 686194613Sed Callbacks->HandleNewlinesInToken(&S[0], S.size()); 687193326Sed } 688245431Sdim Callbacks->setEmittedTokensOnThisLine(); 689198092Srdivacky 690193326Sed if (Tok.is(tok::eof)) break; 691198092Srdivacky 692207619Srdivacky PrevPrevTok = PrevTok; 693193326Sed PrevTok = Tok; 694193326Sed PP.Lex(Tok); 695193326Sed } 696193326Sed} 697193326Sed 698252723Sdimtypedef std::pair<const IdentifierInfo *, MacroInfo *> id_macro_pair; 699263509Sdimstatic int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS) { 700202879Srdivacky return LHS->first->getName().compare(RHS->first->getName()); 701193326Sed} 702193326Sed 703226890Sdimstatic void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) { 704210299Sed // Ignore unknown pragmas. 705210299Sed PP.AddPragmaHandler(new EmptyPragmaHandler()); 706210299Sed 707193326Sed // -dM mode just scans and ignores all tokens in the files, then dumps out 708193326Sed // the macro table at the end. 709207619Srdivacky PP.EnterMainSourceFile(); 710193326Sed 711193326Sed Token Tok; 712193326Sed do PP.Lex(Tok); 713193326Sed while (Tok.isNot(tok::eof)); 714193326Sed 715245431Sdim SmallVector<id_macro_pair, 128> MacrosByID; 716245431Sdim for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); 717245431Sdim I != E; ++I) { 718245431Sdim if (I->first->hasMacroDefinition()) 719252723Sdim MacrosByID.push_back(id_macro_pair(I->first, I->second->getMacroInfo())); 720245431Sdim } 721202879Srdivacky llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare); 722193326Sed 723193326Sed for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) { 724193326Sed MacroInfo &MI = *MacrosByID[i].second; 725198092Srdivacky // Ignore computed macros like __LINE__ and friends. 726193326Sed if (MI.isBuiltinMacro()) continue; 727193326Sed 728193326Sed PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS); 729202879Srdivacky *OS << '\n'; 730193326Sed } 731193326Sed} 732193326Sed 733193326Sed/// DoPrintPreprocessedInput - This implements -E mode. 734193326Sed/// 735226890Sdimvoid clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, 736199482Srdivacky const PreprocessorOutputOptions &Opts) { 737199482Srdivacky // Show macros with no output is handled specially. 738199482Srdivacky if (!Opts.ShowCPP) { 739199482Srdivacky assert(Opts.ShowMacros && "Not yet implemented!"); 740199482Srdivacky DoPrintMacros(PP, OS); 741199482Srdivacky return; 742199482Srdivacky } 743199482Srdivacky 744193326Sed // Inform the preprocessor whether we want it to retain comments or not, due 745193326Sed // to -C or -CC. 746199482Srdivacky PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments); 747193326Sed 748193326Sed PrintPPOutputPPCallbacks *Callbacks = 749199482Srdivacky new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers, 750218893Sdim Opts.ShowMacros); 751210299Sed PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks)); 752218893Sdim PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks)); 753218893Sdim PP.AddPragmaHandler("clang", 754218893Sdim new UnknownPragmaHandler("#pragma clang", Callbacks)); 755193326Sed 756204962Srdivacky PP.addPPCallbacks(Callbacks); 757193326Sed 758193326Sed // After we have configured the preprocessor, enter the main file. 759207619Srdivacky PP.EnterMainSourceFile(); 760193326Sed 761193326Sed // Consume all of the tokens that come from the predefines buffer. Those 762193326Sed // should not be emitted into the output and are guaranteed to be at the 763193326Sed // start. 764193326Sed const SourceManager &SourceMgr = PP.getSourceManager(); 765193326Sed Token Tok; 766218893Sdim do { 767218893Sdim PP.Lex(Tok); 768218893Sdim if (Tok.is(tok::eof) || !Tok.getLocation().isFileID()) 769218893Sdim break; 770193326Sed 771218893Sdim PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); 772218893Sdim if (PLoc.isInvalid()) 773218893Sdim break; 774218893Sdim 775218893Sdim if (strcmp(PLoc.getFilename(), "<built-in>")) 776218893Sdim break; 777218893Sdim } while (true); 778218893Sdim 779193326Sed // Read all the preprocessed tokens, printing them out to the stream. 780193326Sed PrintPreprocessedTokens(PP, Tok, Callbacks, *OS); 781193326Sed *OS << '\n'; 782193326Sed} 783