zcov: / lib/Frontend/PrintPreprocessedOutput.cpp


Files: 1 Branches Taken: 81.3% 135 / 166
Generated: 2010-02-10 01:31 Branches Executed: 89.2% 148 / 166
Line Coverage: 87.2% 198 / 227


Programs: 1 Runs 2897


       1                 : //===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : // This code simply runs the preprocessor on the input file and prints out the
      11                 : // result.  This is the traditional behavior of the -E option.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "clang/Frontend/Utils.h"
      16                 : #include "clang/Basic/Diagnostic.h"
      17                 : #include "clang/Basic/SourceManager.h"
      18                 : #include "clang/Frontend/PreprocessorOutputOptions.h"
      19                 : #include "clang/Lex/MacroInfo.h"
      20                 : #include "clang/Lex/PPCallbacks.h"
      21                 : #include "clang/Lex/Pragma.h"
      22                 : #include "clang/Lex/Preprocessor.h"
      23                 : #include "clang/Lex/TokenConcatenation.h"
      24                 : #include "llvm/ADT/SmallString.h"
      25                 : #include "llvm/ADT/STLExtras.h"
      26                 : #include "llvm/Config/config.h"
      27                 : #include "llvm/Support/raw_ostream.h"
      28                 : #include <cstdio>
      29                 : using namespace clang;
      30                 : 
      31                 : /// PrintMacroDefinition - Print a macro definition in a form that will be
      32                 : /// properly accepted back as a definition.
      33                 : static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
      34             4686:                                  Preprocessor &PP, llvm::raw_ostream &OS) {
      35             4686:   OS << "#define " << II.getName();
      36                 : 
                       10: branch 1 taken
                     4676: branch 2 taken
      37             4686:   if (MI.isFunctionLike()) {
      38               10:     OS << '(';
                        9: branch 1 taken
                        1: branch 2 taken
      39               10:     if (!MI.arg_empty()) {
      40                9:       MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end();
                        3: branch 0 taken
                        9: branch 1 taken
      41               12:       for (; AI+1 != E; ++AI) {
      42                3:         OS << (*AI)->getName();
      43                3:         OS << ',';
      44                 :       }
      45                 : 
      46                 :       // Last argument.
                        2: branch 3 taken
                        7: branch 4 taken
      47                9:       if ((*AI)->getName() == "__VA_ARGS__")
      48                2:         OS << "...";
      49                 :       else
      50                7:         OS << (*AI)->getName();
      51                 :     }
      52                 : 
                        1: branch 1 taken
                        9: branch 2 taken
      53               10:     if (MI.isGNUVarargs())
      54                1:       OS << "...";  // #define foo(x...)
      55                 :     
      56               10:     OS << ')';
      57                 :   }
      58                 : 
      59                 :   // GCC always emits a space, even if the macro body is empty.  However, do not
      60                 :   // want to emit two spaces if the first token has a leading space.
                     4615: branch 1 taken
                       71: branch 2 taken
                     4607: branch 5 taken
                        8: branch 6 taken
                     4678: branch 7 taken
                        8: branch 8 taken
      61             4686:   if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace())
      62             4678:     OS << ' ';
      63                 : 
      64             4686:   llvm::SmallVector<char, 128> SpellingBuffer;
                     6006: branch 2 taken
                     4686: branch 3 taken
      65            10692:   for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
      66                 :        I != E; ++I) {
                      401: branch 1 taken
                     5605: branch 2 taken
      67             6006:     if (I->hasLeadingSpace())
      68              401:       OS << ' ';
      69                 : 
      70                 :     // Make sure we have enough space in the spelling buffer.
                     4955: branch 2 taken
                     1051: branch 3 taken
      71             6006:     if (I->getLength() > SpellingBuffer.size())
      72             4955:       SpellingBuffer.resize(I->getLength());
      73             6006:     const char *Buffer = SpellingBuffer.data();
      74             6006:     unsigned SpellingLen = PP.getSpelling(*I, Buffer);
      75             6006:     OS.write(Buffer, SpellingLen);
      76             4686:   }
      77             4686: }
      78                 : 
      79                 : //===----------------------------------------------------------------------===//
      80                 : // Preprocessed token printer
      81                 : //===----------------------------------------------------------------------===//
      82                 : 
      83                 : namespace {
                      200: branch 2 taken
                        0: branch 3 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
      84              200: class PrintPPOutputPPCallbacks : public PPCallbacks {
      85                 :   Preprocessor &PP;
      86                 :   TokenConcatenation ConcatInfo;
      87                 : public:
      88                 :   llvm::raw_ostream &OS;
      89                 : private:
      90                 :   unsigned CurLine;
      91                 :   bool EmittedTokensOnThisLine;
      92                 :   bool EmittedMacroOnThisLine;
      93                 :   SrcMgr::CharacteristicKind FileType;
      94                 :   llvm::SmallString<512> CurFilename;
      95                 :   bool Initialized;
      96                 :   bool DisableLineMarkers;
      97                 :   bool DumpDefines;
      98                 :   bool UseLineDirective;
      99                 : public:
     100                 :   PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os,
     101              200:                            bool lineMarkers, bool defines)
     102                 :      : PP(pp), ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers),
     103              200:        DumpDefines(defines) {
     104              200:     CurLine = 0;
     105              200:     CurFilename += "<uninit>";
     106              200:     EmittedTokensOnThisLine = false;
     107              200:     EmittedMacroOnThisLine = false;
     108              200:     FileType = SrcMgr::C_User;
     109              200:     Initialized = false;
     110                 :          
     111                 :     // If we're in microsoft mode, use normal #line instead of line markers.
     112              200:     UseLineDirective = PP.getLangOptions().Microsoft;
     113              200:   }
     114                 : 
     115            11115:   void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
     116             4663:   bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
     117                 : 
     118                 :   virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
     119                 :                            SrcMgr::CharacteristicKind FileType);
     120                 :   virtual void Ident(SourceLocation Loc, const std::string &str);
     121                 :   virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
     122                 :                              const std::string &Str);
     123                 : 
     124                 : 
     125                 :   bool HandleFirstTokOnLine(Token &Tok);
     126                 :   bool MoveToLine(SourceLocation Loc);
     127             4619:   bool AvoidConcat(const Token &PrevTok, const Token &Tok) {
     128             4619:     return ConcatInfo.AvoidConcat(PrevTok, Tok);
     129                 :   }
     130                 :   void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
     131                 : 
     132                 :   void HandleNewlinesInToken(const char *TokStr, unsigned Len);
     133                 : 
     134                 :   /// MacroDefined - This hook is called whenever a macro definition is seen.
     135                 :   void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
     136                 : 
     137                 : };
     138                 : }  // end anonymous namespace
     139                 : 
     140                 : void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
     141                 :                                              const char *Extra,
     142             2010:                                              unsigned ExtraLen) {
                     1795: branch 0 taken
                      215: branch 1 taken
                        3: branch 2 taken
                     1792: branch 3 taken
     143             2010:   if (EmittedTokensOnThisLine || EmittedMacroOnThisLine) {
     144              218:     OS << '\n';
     145              218:     EmittedTokensOnThisLine = false;
     146              218:     EmittedMacroOnThisLine = false;
     147                 :   }
     148                 : 
     149                 :   // Emit #line directives or GNU line markers depending on what mode we're in.
                        0: branch 0 not taken
                     2010: branch 1 taken
     150             2010:   if (UseLineDirective) {
     151                0:     OS << "#line" << ' ' << LineNo << ' ' << '"';
     152                0:     OS.write(&CurFilename[0], CurFilename.size());
     153                0:     OS << '"';
     154                 :   } else {
     155             2010:     OS << '#' << ' ' << LineNo << ' ' << '"';
     156             2010:     OS.write(&CurFilename[0], CurFilename.size());
     157             2010:     OS << '"';
     158                 :     
                     1117: branch 0 taken
                      893: branch 1 taken
     159             2010:     if (ExtraLen)
     160             1117:       OS.write(Extra, ExtraLen);
     161                 : 
                      388: branch 0 taken
                     1622: branch 1 taken
     162             2010:     if (FileType == SrcMgr::C_System)
     163              388:       OS.write(" 3", 2);
                      293: branch 0 taken
                     1329: branch 1 taken
     164             1622:     else if (FileType == SrcMgr::C_ExternCSystem)
     165              293:       OS.write(" 3 4", 4);
     166                 :   }
     167             2010:   OS << '\n';
     168             2010: }
     169                 : 
     170                 : /// MoveToLine - Move the output to the source line specified by the location
     171                 : /// object.  We can do this by emitting some number of \n's, or be emitting a
     172                 : /// #line directive.  This returns false if already at the specified line, true
     173                 : /// if some newlines were emitted.
     174             2498: bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) {
     175             2498:   unsigned LineNo = PP.getSourceManager().getInstantiationLineNumber(Loc);
     176                 : 
                       24: branch 0 taken
                     2474: branch 1 taken
     177             2498:   if (DisableLineMarkers) {
                        6: branch 0 taken
                       18: branch 1 taken
     178               24:     if (LineNo == CurLine) return false;
     179                 : 
     180               18:     CurLine = LineNo;
     181                 : 
                       12: branch 0 taken
                        6: branch 1 taken
                       12: branch 2 taken
                        0: branch 3 not taken
     182               18:     if (!EmittedTokensOnThisLine && !EmittedMacroOnThisLine)
     183               12:       return true;
     184                 : 
     185                6:     OS << '\n';
     186                6:     EmittedTokensOnThisLine = false;
     187                6:     EmittedMacroOnThisLine = false;
     188                6:     return true;
     189                 :   }
     190                 : 
     191                 :   // If this line is "close enough" to the original line, just print newlines,
     192                 :   // otherwise print a #line directive.
                     2001: branch 0 taken
                      473: branch 1 taken
     193             2474:   if (LineNo-CurLine <= 8) {
                     1341: branch 0 taken
                      660: branch 1 taken
     194             2001:     if (LineNo-CurLine == 1)
     195             1341:       OS << '\n';
                       29: branch 0 taken
                      631: branch 1 taken
     196              660:     else if (LineNo == CurLine)
     197               29:       return false;    // Spelling line moved, but instantiation line didn't.
     198                 :     else {
     199              631:       const char *NewLines = "\n\n\n\n\n\n\n\n";
     200              631:       OS.write(NewLines, LineNo-CurLine);
     201                 :     }
     202                 :   } else {
     203              473:     WriteLineInfo(LineNo, 0, 0);
     204                 :   }
     205                 : 
     206             2445:   CurLine = LineNo;
     207             2445:   return true;
     208                 : }
     209                 : 
     210                 : 
     211                 : /// FileChanged - Whenever the preprocessor enters or exits a #include file
     212                 : /// it invokes this handler.  Update our conception of the current source
     213                 : /// position.
     214                 : void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
     215                 :                                            FileChangeReason Reason,
     216             1381:                                        SrcMgr::CharacteristicKind NewFileType) {
     217                 :   // Unless we are exiting a #include, make sure to skip ahead to the line the
     218                 :   // #include directive was at.
     219             1381:   SourceManager &SourceMgr = PP.getSourceManager();
                      672: branch 0 taken
                      709: branch 1 taken
     220             1381:   if (Reason == PPCallbacks::EnterFile) {
     221              672:     SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc();
                      272: branch 1 taken
                      400: branch 2 taken
     222              672:     if (IncludeLoc.isValid())
     223              272:       MoveToLine(IncludeLoc);
                        0: branch 0 not taken
                      709: branch 1 taken
     224              709:   } else if (Reason == PPCallbacks::SystemHeaderPragma) {
     225                0:     MoveToLine(Loc);
     226                 : 
     227                 :     // TODO GCC emits the # directive for this directive on the line AFTER the
     228                 :     // directive and emits a bunch of spaces that aren't needed.  Emulate this
     229                 :     // strange behavior.
     230                 :   }
     231                 : 
     232             1381:   Loc = SourceMgr.getInstantiationLoc(Loc);
     233                 :   // FIXME: Should use presumed line #!
     234             1381:   CurLine = SourceMgr.getInstantiationLineNumber(Loc);
     235                 : 
                     1343: branch 0 taken
                       38: branch 1 taken
     236             1381:   if (DisableLineMarkers) return;
     237                 : 
     238             1343:   CurFilename.clear();
     239             1343:   CurFilename += SourceMgr.getPresumedLoc(Loc).getFilename();
     240             1343:   Lexer::Stringify(CurFilename);
     241             1343:   FileType = NewFileType;
     242                 : 
                      194: branch 0 taken
                     1149: branch 1 taken
     243             1343:   if (!Initialized) {
     244              194:     WriteLineInfo(CurLine);
     245              194:     Initialized = true;
     246                 :   }
     247                 : 
                      653: branch 0 taken
                      464: branch 1 taken
                      226: branch 2 taken
                        0: branch 3 not taken
     248             1343:   switch (Reason) {
     249                 :   case PPCallbacks::EnterFile:
     250              653:     WriteLineInfo(CurLine, " 1", 2);
     251              653:     break;
     252                 :   case PPCallbacks::ExitFile:
     253              464:     WriteLineInfo(CurLine, " 2", 2);
     254              464:     break;
     255                 :   case PPCallbacks::SystemHeaderPragma:
     256                 :   case PPCallbacks::RenameFile:
     257              226:     WriteLineInfo(CurLine);
     258                 :     break;
     259                 :   }
     260                 : }
     261                 : 
     262                 : /// Ident - Handle #ident directives when read by the preprocessor.
     263                 : ///
     264                0: void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
     265                0:   MoveToLine(Loc);
     266                 : 
     267                0:   OS.write("#ident ", strlen("#ident "));
     268                0:   OS.write(&S[0], S.size());
     269                0:   EmittedTokensOnThisLine = true;
     270                0: }
     271                 : 
     272                 : /// MacroDefined - This hook is called whenever a macro definition is seen.
     273                 : void PrintPPOutputPPCallbacks::MacroDefined(const IdentifierInfo *II,
     274            23307:                                             const MacroInfo *MI) {
     275                 :   // Only print out macro definitions in -dD mode.
                      211: branch 0 taken
                    23096: branch 1 taken
                        0: branch 3 not taken
                      211: branch 4 taken
                    23096: branch 5 taken
                      211: branch 6 taken
     276            23307:   if (!DumpDefines ||
     277                 :       // Ignore __FILE__ etc.
     278            23096:       MI->isBuiltinMacro()) return;
     279                 : 
     280              211:   MoveToLine(MI->getDefinitionLoc());
     281              211:   PrintMacroDefinition(*II, *MI, PP, OS);
     282              211:   EmittedMacroOnThisLine = true;
     283                 : }
     284                 : 
     285                 : 
     286                 : void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
     287                 :                                              const IdentifierInfo *Kind,
     288                0:                                              const std::string &Str) {
     289                0:   MoveToLine(Loc);
     290                0:   OS << "#pragma comment(" << Kind->getName();
     291                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     292                0:   if (!Str.empty()) {
     293                0:     OS << ", \"";
     294                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
     295                0:     for (unsigned i = 0, e = Str.size(); i != e; ++i) {
     296                0:       unsigned char Char = Str[i];
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     297                0:       if (isprint(Char) && Char != '\\' && Char != '"')
     298                0:         OS << (char)Char;
     299                 :       else  // Output anything hard as an octal escape.
     300                 :         OS << '\\'
     301                 :            << (char)('0'+ ((Char >> 6) & 7))
     302                 :            << (char)('0'+ ((Char >> 3) & 7))
     303                0:            << (char)('0'+ ((Char >> 0) & 7));
     304                 :     }
     305                0:     OS << '"';
     306                 :   }
     307                 : 
     308                0:   OS << ')';
     309                0:   EmittedTokensOnThisLine = true;
     310                0: }
     311                 : 
     312                 : 
     313                 : /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
     314                 : /// is called for the first token on each new line.  If this really is the start
     315                 : /// of a new logical line, handle it and return true, otherwise return false.
     316                 : /// This may not be the start of a logical line because the "start of line"
     317                 : /// marker is set for spelling lines, not instantiation ones.
     318             2009: bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
     319                 :   // Figure out what line we went to and insert the appropriate number of
     320                 :   // newline characters.
                       33: branch 2 taken
                     1976: branch 3 taken
     321             2009:   if (!MoveToLine(Tok.getLocation()))
     322               33:     return false;
     323                 : 
     324                 :   // Print out space characters so that the first token on a line is
     325                 :   // indented for easy reading.
     326             1976:   const SourceManager &SourceMgr = PP.getSourceManager();
     327             1976:   unsigned ColNo = SourceMgr.getInstantiationColumnNumber(Tok.getLocation());
     328                 : 
     329                 :   // This hack prevents stuff like:
     330                 :   // #define HASH #
     331                 :   // HASH define foo bar
     332                 :   // From having the # character end up at column 1, which makes it so it
     333                 :   // is not handled as a #define next time through the preprocessor if in
     334                 :   // -fpreprocessed mode.
                     1806: branch 0 taken
                      170: branch 1 taken
                        7: branch 3 taken
                     1799: branch 4 taken
                        7: branch 5 taken
                     1969: branch 6 taken
     335             1976:   if (ColNo <= 1 && Tok.is(tok::hash))
     336                7:     OS << ' ';
     337                 : 
     338                 :   // Otherwise, indent the appropriate number of spaces.
                      666: branch 0 taken
                     1976: branch 1 taken
     339             2642:   for (; ColNo > 1; --ColNo)
     340              666:     OS << ' ';
     341                 : 
     342             1976:   return true;
     343                 : }
     344                 : 
     345                 : void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr,
     346               38:                                                      unsigned Len) {
     347               38:   unsigned NumNewlines = 0;
                     1418: branch 0 taken
                       38: branch 1 taken
     348             1456:   for (; Len; --Len, ++TokStr) {
                     1416: branch 0 taken
                        2: branch 1 taken
                     1416: branch 2 taken
                        0: branch 3 not taken
     349             1418:     if (*TokStr != '\n' &&
     350                 :         *TokStr != '\r')
     351             1416:       continue;
     352                 : 
     353                2:     ++NumNewlines;
     354                 : 
     355                 :     // If we have \n\r or \r\n, skip both and count as one line.
                        2: branch 0 taken
                        0: branch 1 not taken
                        2: branch 2 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        2: branch 5 taken
                        2: branch 6 taken
                        2: branch 7 taken
     356                2:     if (Len != 1 &&
     357                 :         (TokStr[1] == '\n' || TokStr[1] == '\r') &&
     358                 :         TokStr[0] != TokStr[1])
     359                0:       ++TokStr, --Len;
     360                 :   }
     361                 : 
                        1: branch 0 taken
                       37: branch 1 taken
     362               38:   if (NumNewlines == 0) return;
     363                 : 
     364                1:   CurLine += NumNewlines;
     365                 : }
     366                 : 
     367                 : 
     368                 : namespace {
                      400: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
     369              400: struct UnknownPragmaHandler : public PragmaHandler {
     370                 :   const char *Prefix;
     371                 :   PrintPPOutputPPCallbacks *Callbacks;
     372                 : 
     373              400:   UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks)
     374              400:     : PragmaHandler(0), Prefix(prefix), Callbacks(callbacks) {}
     375                6:   virtual void HandlePragma(Preprocessor &PP, Token &PragmaTok) {
     376                 :     // Figure out what line we went to and insert the appropriate number of
     377                 :     // newline characters.
     378                6:     Callbacks->MoveToLine(PragmaTok.getLocation());
     379                6:     Callbacks->OS.write(Prefix, strlen(Prefix));
     380                 : 
     381                 :     // Read and print all of the pragma tokens.
                       18: branch 2 taken
                        6: branch 3 taken
     382               24:     while (PragmaTok.isNot(tok::eom)) {
                       15: branch 1 taken
                        3: branch 2 taken
     383               18:       if (PragmaTok.hasLeadingSpace())
     384               15:         Callbacks->OS << ' ';
     385               18:       std::string TokSpell = PP.getSpelling(PragmaTok);
     386               18:       Callbacks->OS.write(&TokSpell[0], TokSpell.size());
     387               18:       PP.LexUnexpandedToken(PragmaTok);
     388                 :     }
     389                6:     Callbacks->OS << '\n';
     390                6:   }
     391                 : };
     392                 : } // end anonymous namespace
     393                 : 
     394                 : 
     395                 : static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,
     396                 :                                     PrintPPOutputPPCallbacks *Callbacks,
     397              200:                                     llvm::raw_ostream &OS) {
     398                 :   char Buffer[256];
     399              200:   Token PrevTok;
     400            10915:   while (1) {
     401                 : 
     402                 :     // If this token is at the start of a line, emit newlines if needed.
                     2009: branch 1 taken
                     9106: branch 2 taken
                     1976: branch 4 taken
                       33: branch 5 taken
                     9139: branch 6 taken
                     1976: branch 7 taken
     403            11115:     if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) {
     404                 :       // done.
                     4663: branch 1 taken
                     4476: branch 2 taken
                     4619: branch 4 taken
                       44: branch 5 taken
                      233: branch 7 taken
                     4386: branch 8 taken
                     4709: branch 9 taken
                     4430: branch 10 taken
     405             9139:     } else if (Tok.hasLeadingSpace() ||
     406                 :                // If we haven't emitted a token on this line yet, PrevTok isn't
     407                 :                // useful to look at and no concatenation could happen anyway.
     408                 :                (Callbacks->hasEmittedTokensOnThisLine() &&
     409                 :                 // Don't print "-" next to "-", it would form "--".
     410                 :                 Callbacks->AvoidConcat(PrevTok, Tok))) {
     411             4709:       OS << ' ';
     412                 :     }
     413                 : 
                     5145: branch 1 taken
                     5970: branch 2 taken
     414            11115:     if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
     415             5145:       OS << II->getName();
                     1417: branch 1 taken
                     4553: branch 2 taken
                     1417: branch 4 taken
                        0: branch 5 not taken
                     1417: branch 7 taken
                        0: branch 8 not taken
                     1417: branch 9 taken
                     4553: branch 10 taken
     416             5970:     } else if (Tok.isLiteral() && !Tok.needsCleaning() &&
     417                 :                Tok.getLiteralData()) {
     418             1417:       OS.write(Tok.getLiteralData(), Tok.getLength());
                     4553: branch 1 taken
                        0: branch 2 not taken
     419             4553:     } else if (Tok.getLength() < 256) {
     420             4553:       const char *TokPtr = Buffer;
     421             4553:       unsigned Len = PP.getSpelling(Tok, TokPtr);
     422             4553:       OS.write(TokPtr, Len);
     423                 : 
     424                 :       // Tokens that can contain embedded newlines need to adjust our current
     425                 :       // line number.
                       38: branch 1 taken
                     4515: branch 2 taken
     426             4553:       if (Tok.getKind() == tok::comment)
     427               38:         Callbacks->HandleNewlinesInToken(TokPtr, Len);
     428                 :     } else {
     429                0:       std::string S = PP.getSpelling(Tok);
     430                0:       OS.write(&S[0], S.size());
     431                 : 
     432                 :       // Tokens that can contain embedded newlines need to adjust our current
     433                 :       // line number.
                        0: branch 1 not taken
                        0: branch 2 not taken
     434                0:       if (Tok.getKind() == tok::comment)
     435                0:         Callbacks->HandleNewlinesInToken(&S[0], S.size());
     436                 :     }
     437            11115:     Callbacks->SetEmittedTokensOnThisLine();
     438                 : 
                    10915: branch 1 taken
                      200: branch 2 taken
     439            11115:     if (Tok.is(tok::eof)) break;
     440                 : 
     441            10915:     PrevTok = Tok;
     442            10915:     PP.Lex(Tok);
     443                 :   }
     444              200: }
     445                 : 
     446                 : typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
     447            27356: static int MacroIDCompare(const void* a, const void* b) {
     448            27356:   const id_macro_pair *LHS = static_cast<const id_macro_pair*>(a);
     449            27356:   const id_macro_pair *RHS = static_cast<const id_macro_pair*>(b);
     450            27356:   return LHS->first->getName().compare(RHS->first->getName());
     451                 : }
     452                 : 
     453               45: static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) {
     454                 :   // -dM mode just scans and ignores all tokens in the files, then dumps out
     455                 :   // the macro table at the end.
     456               45:   PP.EnterMainSourceFile();
     457                 : 
     458               45:   Token Tok;
                      253: branch 2 taken
                       45: branch 3 taken
     459              298:   do PP.Lex(Tok);
     460                 :   while (Tok.isNot(tok::eof));
     461                 : 
     462                 :   llvm::SmallVector<id_macro_pair, 128>
     463               45:     MacrosByID(PP.macro_begin(), PP.macro_end());
     464               45:   llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare);
     465                 : 
                     5060: branch 1 taken
                       45: branch 2 taken
     466             5105:   for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
     467             5060:     MacroInfo &MI = *MacrosByID[i].second;
     468                 :     // Ignore computed macros like __LINE__ and friends.
                     4475: branch 1 taken
                      585: branch 2 taken
     469             5060:     if (MI.isBuiltinMacro()) continue;
     470                 : 
     471             4475:     PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS);
     472             4475:     *OS << '\n';
     473               45:   }
     474               45: }
     475                 : 
     476                 : /// DoPrintPreprocessedInput - This implements -E mode.
     477                 : ///
     478                 : void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS,
     479              245:                                      const PreprocessorOutputOptions &Opts) {
     480                 :   // Show macros with no output is handled specially.
                       45: branch 0 taken
                      200: branch 1 taken
     481              245:   if (!Opts.ShowCPP) {
                        0: branch 0 not taken
                       45: branch 1 taken
     482               45:     assert(Opts.ShowMacros && "Not yet implemented!");
     483               45:     DoPrintMacros(PP, OS);
     484               45:     return;
     485                 :   }
     486                 : 
     487                 :   // Inform the preprocessor whether we want it to retain comments or not, due
     488                 :   // to -C or -CC.
     489              200:   PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments);
     490                 : 
     491              200:   OS->SetBufferSize(64*1024);
     492                 : 
     493                 :   PrintPPOutputPPCallbacks *Callbacks =
     494                 :       new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers,
     495              200:                                    Opts.ShowMacros);
     496              200:   PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
     497                 :   PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
     498              200:                                                       Callbacks));
     499                 : 
     500              200:   PP.setPPCallbacks(Callbacks);
     501                 : 
     502                 :   // After we have configured the preprocessor, enter the main file.
     503              200:   PP.EnterMainSourceFile();
     504                 : 
     505                 :   // Consume all of the tokens that come from the predefines buffer.  Those
     506                 :   // should not be emitted into the output and are guaranteed to be at the
     507                 :   // start.
     508              200:   const SourceManager &SourceMgr = PP.getSourceManager();
     509              200:   Token Tok;
                     1211: branch 2 taken
                       37: branch 3 taken
                     1171: branch 6 taken
                       40: branch 7 taken
                     1048: branch 12 taken
                      123: branch 13 taken
                     1048: branch 14 taken
                      200: branch 15 taken
     510             1248:   do PP.Lex(Tok);
     511                 :   while (Tok.isNot(tok::eof) && Tok.getLocation().isFileID() &&
     512                 :          !strcmp(SourceMgr.getPresumedLoc(Tok.getLocation()).getFilename(),
     513                 :                  "<built-in>"));
     514                 : 
     515                 :   // Read all the preprocessed tokens, printing them out to the stream.
     516              200:   PrintPreprocessedTokens(PP, Tok, Callbacks, *OS);
     517              200:   *OS << '\n';
     518                 : }
     519                 : 

Generated: 2010-02-10 01:31 by zcov