[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