[cfe-commits] r68884 - in /cfe/trunk: include/clang/Driver/Options.def lib/Driver/Tools.cpp test/Preprocessor/dump-options.c tools/clang-cc/PrintPreprocessedOutput.cpp

Chris Lattner sabre at nondot.org
Sat Apr 11 18:56:53 PDT 2009


Author: lattner
Date: Sat Apr 11 20:56:53 2009
New Revision: 68884

URL: http://llvm.org/viewvc/llvm-project?rev=68884&view=rev
Log:
Implement support for GCC's -dD mode, which dumps -E output *and*
macro definitions.

Added:
    cfe/trunk/test/Preprocessor/dump-options.c
Modified:
    cfe/trunk/include/clang/Driver/Options.def
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/tools/clang-cc/PrintPreprocessedOutput.cpp

Modified: cfe/trunk/include/clang/Driver/Options.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.def?rev=68884&r1=68883&r2=68884&view=diff

==============================================================================
--- cfe/trunk/include/clang/Driver/Options.def (original)
+++ cfe/trunk/include/clang/Driver/Options.def Sat Apr 11 20:56:53 2009
@@ -400,6 +400,7 @@
 OPTION("-c", c, Flag, INVALID, INVALID, "d", 0, 
        "Only run preprocess, compile, and assemble steps", 0)
 OPTION("-dA", dA, Flag, d_Group, INVALID, "", 0, 0, 0)
+OPTION("-dD", dD, Flag, d_Group, INVALID, "", 0, 0, 0)
 OPTION("-dM", dM, Flag, d_Group, INVALID, "", 0, 0, 0)
 OPTION("-dead_strip", dead__strip, Flag, INVALID, INVALID, "", 0, 0, 0)
 OPTION("-dependency-file", dependency_file, Separate, INVALID, INVALID, "", 0, 0, 0)

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=68884&r1=68883&r2=68884&view=diff

==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Sat Apr 11 20:56:53 2009
@@ -474,6 +474,7 @@
     CmdArgs.push_back("-fno-common");
 
   Args.AddLastArg(CmdArgs, options::OPT_dM);
+  Args.AddLastArg(CmdArgs, options::OPT_dD);
 
   Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
 

Added: cfe/trunk/test/Preprocessor/dump-options.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/dump-options.c?rev=68884&view=auto

==============================================================================
--- cfe/trunk/test/Preprocessor/dump-options.c (added)
+++ cfe/trunk/test/Preprocessor/dump-options.c Sat Apr 11 20:56:53 2009
@@ -0,0 +1,3 @@
+// RUN: clang %s -E -dD | grep __INTMAX_MAX__ &&
+// RUN: clang %s -E -dM | grep __INTMAX_MAX__
+

Modified: cfe/trunk/tools/clang-cc/PrintPreprocessedOutput.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/PrintPreprocessedOutput.cpp?rev=68884&r1=68883&r2=68884&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/PrintPreprocessedOutput.cpp (original)
+++ cfe/trunk/tools/clang-cc/PrintPreprocessedOutput.cpp Sat Apr 11 20:56:53 2009
@@ -30,6 +30,53 @@
 #include <cstdio>
 using namespace clang;
 
+/// PrintMacroDefinition - Print a macro definition in a form that will be
+/// properly accepted back as a definition.
+static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI,
+                                 Preprocessor &PP, llvm::raw_ostream &OS) {
+  OS << "#define " << II.getName();
+  
+  if (MI.isFunctionLike()) {
+    OS << '(';
+    if (MI.arg_empty())
+      ;
+    else if (MI.getNumArgs() == 1) 
+      OS << (*MI.arg_begin())->getName();
+    else {
+      MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end();
+      OS << (*AI++)->getName();
+      while (AI != E)
+        OS << ',' << (*AI++)->getName();
+    }
+    
+    if (MI.isVariadic()) {
+      if (!MI.arg_empty())
+        OS << ',';
+      OS << "...";
+    }
+    OS << ')';
+  }
+  
+  // GCC always emits a space, even if the macro body is empty.  However, do not
+  // want to emit two spaces if the first token has a leading space.
+  if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace())
+    OS << ' ';
+  
+  llvm::SmallVector<char, 128> SpellingBuffer;
+  for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
+       I != E; ++I) {
+    if (I->hasLeadingSpace())
+      OS << ' ';
+    
+    // Make sure we have enough space in the spelling buffer.
+    if (I->getLength() < SpellingBuffer.size())
+      SpellingBuffer.resize(I->getLength());
+    const char *Buffer = &SpellingBuffer[0];
+    unsigned SpellingLen = PP.getSpelling(*I, Buffer);
+    OS.write(Buffer, SpellingLen);
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // Preprocessed token printer
 //===----------------------------------------------------------------------===//
@@ -46,6 +93,9 @@
 DumpMacros("dM", llvm::cl::desc("Print macro definitions in -E mode instead of"
                                 " normal output"));
 
+static llvm::cl::opt<bool>
+DumpDefines("dD", llvm::cl::desc("Print macro definitions in -E mode in "
+                                "addition to normal output"));
 
 namespace {
 class PrintPPOutputPPCallbacks : public PPCallbacks {
@@ -85,6 +135,10 @@
     return ConcatInfo.AvoidConcat(PrevTok, Tok);
   }
   void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
+  
+  /// MacroDefined - This hook is called whenever a macro definition is seen.
+  void MacroDefined(const IdentifierInfo *II, const MacroInfo *MI);
+  
 };
 }  // end anonymous namespace
 
@@ -211,6 +265,19 @@
   EmittedTokensOnThisLine = true;
 }
 
+/// MacroDefined - This hook is called whenever a macro definition is seen.
+void PrintPPOutputPPCallbacks::MacroDefined(const IdentifierInfo *II,
+                                            const MacroInfo *MI) {
+  // Only print out macro definitions in -dD mode.
+  if (!DumpDefines ||
+      // Ignore __FILE__ etc.
+      MI->isBuiltinMacro()) return;
+  
+  MoveToLine(MI->getDefinitionLoc());
+  PrintMacroDefinition(*II, *MI, PP, OS);
+}
+
+
 void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
                                              const IdentifierInfo *Kind, 
                                              const std::string &Str) {
@@ -338,56 +405,6 @@
   }
 }
 
-/// PrintMacroDefinition - Print a macro definition in a form that will be
-/// properly accepted back as a definition.
-static void PrintMacroDefinition(IdentifierInfo &II, const MacroInfo &MI,
-                                 Preprocessor &PP, llvm::raw_ostream &OS) {
-  // Ignore computed macros like __LINE__ and friends. 
-  if (MI.isBuiltinMacro()) return;
-  OS << "#define " << II.getName();
-
-  if (MI.isFunctionLike()) {
-    OS << '(';
-    if (MI.arg_empty())
-      ;
-    else if (MI.getNumArgs() == 1) 
-      OS << (*MI.arg_begin())->getName();
-    else {
-      MacroInfo::arg_iterator AI = MI.arg_begin(), E = MI.arg_end();
-      OS << (*AI++)->getName();
-      while (AI != E)
-        OS << ',' << (*AI++)->getName();
-    }
-    
-    if (MI.isVariadic()) {
-      if (!MI.arg_empty())
-        OS << ',';
-      OS << "...";
-    }
-    OS << ')';
-  }
-  
-  // GCC always emits a space, even if the macro body is empty.  However, do not
-  // want to emit two spaces if the first token has a leading space.
-  if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace())
-    OS << ' ';
-  
-  llvm::SmallVector<char, 128> SpellingBuffer;
-  for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
-       I != E; ++I) {
-    if (I->hasLeadingSpace())
-      OS << ' ';
-    
-    // Make sure we have enough space in the spelling buffer.
-    if (I->getLength() < SpellingBuffer.size())
-      SpellingBuffer.resize(I->getLength());
-    const char *Buffer = &SpellingBuffer[0];
-    unsigned SpellingLen = PP.getSpelling(*I, Buffer);
-    OS.write(Buffer, SpellingLen);
-  }
-  OS << "\n";
-}
-
 namespace {
   struct SortMacrosByID {
     typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;
@@ -430,12 +447,17 @@
       MacrosByID.push_back(*I);
     std::sort(MacrosByID.begin(), MacrosByID.end(), SortMacrosByID());
     
-    for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i)
-      PrintMacroDefinition(*MacrosByID[i].first, *MacrosByID[i].second, PP, OS);
+    for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) {
+      MacroInfo &MI = *MacrosByID[i].second;
+      // Ignore computed macros like __LINE__ and friends. 
+      if (MI.isBuiltinMacro()) continue;
+
+      PrintMacroDefinition(*MacrosByID[i].first, MI, PP, OS);
+      OS << "\n";
+    }
     
   } else {
-    PrintPPOutputPPCallbacks *Callbacks
-      = new PrintPPOutputPPCallbacks(PP, OS);
+    PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(PP, OS);
     PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
     PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
                                                         Callbacks));





More information about the cfe-commits mailing list