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