[cfe-commits] r63926 - in /cfe/trunk: Driver/PrintPreprocessedOutput.cpp include/clang/Lex/MacroInfo.h lib/Lex/Preprocessor.cpp test/Preprocessor/dump_macros.c
Chris Lattner
sabre at nondot.org
Thu Feb 5 22:45:26 PST 2009
Author: lattner
Date: Fri Feb 6 00:45:26 2009
New Revision: 63926
URL: http://llvm.org/viewvc/llvm-project?rev=63926&view=rev
Log:
Add an implementation of -dM that follows GCC closely enough to permit
diffing the output of:
clang -dM -o - -E -x c foo.c | sort
Added:
cfe/trunk/test/Preprocessor/dump_macros.c
Modified:
cfe/trunk/Driver/PrintPreprocessedOutput.cpp
cfe/trunk/include/clang/Lex/MacroInfo.h
cfe/trunk/lib/Lex/Preprocessor.cpp
Modified: cfe/trunk/Driver/PrintPreprocessedOutput.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/PrintPreprocessedOutput.cpp?rev=63926&r1=63925&r2=63926&view=diff
==============================================================================
--- cfe/trunk/Driver/PrintPreprocessedOutput.cpp (original)
+++ cfe/trunk/Driver/PrintPreprocessedOutput.cpp Fri Feb 6 00:45:26 2009
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang.h"
+#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Pragma.h"
@@ -39,6 +40,10 @@
EnableMacroCommentOutput("CC",
llvm::cl::desc("Enable comment output in -E mode, "
"even from macro expansions"));
+static llvm::cl::opt<bool>
+DumpMacros("dM", llvm::cl::desc("Print macro definitions in -E mode instead of"
+ " normal output"));
+
namespace {
class PrintPPOutputPPCallbacks : public PPCallbacks {
@@ -543,6 +548,49 @@
}
}
+/// 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 << ' ';
+
+ for (MacroInfo::tokens_iterator I = MI.tokens_begin(), E = MI.tokens_end();
+ I != E; ++I) {
+ if (I->hasLeadingSpace())
+ OS << ' ';
+ OS << PP.getSpelling(*I);
+ }
+ OS << "\n";
+}
+
/// DoPrintPreprocessedInput - This implements -E mode.
///
@@ -564,31 +612,45 @@
OS.SetBufferSize(64*1024);
- Token Tok;
- PrintPPOutputPPCallbacks *Callbacks;
- Callbacks = new PrintPPOutputPPCallbacks(PP, OS);
- PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
- PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks));
-
- PP.setPPCallbacks(Callbacks);
-
- // After we have configured the preprocessor, enter the main file.
-
- // Start parsing the specified input file.
- PP.EnterMainSourceFile();
-
- // Consume all of the tokens that come from the predefines buffer. Those
- // should not be emitted into the output and are guaranteed to be at the
- // start.
- const SourceManager &SourceMgr = PP.getSourceManager();
- do PP.Lex(Tok);
- while (Tok.isNot(tok::eof) && Tok.getLocation().isFileID() &&
- !strcmp(SourceMgr.getPresumedLoc(Tok.getLocation()).getFilename(),
- "<predefines>"));
+ if (DumpMacros) {
+ // -dM mode just scans and ignores all tokens in the files, then dumps out
+ // the macro table at the end.
+ PP.EnterMainSourceFile();
+
+ Token Tok;
+ do PP.Lex(Tok);
+ while (Tok.isNot(tok::eof));
+
+ for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
+ I != E; ++I)
+ PrintMacroDefinition(*I->first, *I->second, PP, OS);
+
+ } else {
+ PrintPPOutputPPCallbacks *Callbacks;
+ Callbacks = new PrintPPOutputPPCallbacks(PP, OS);
+ PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
+ PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",
+ Callbacks));
+
+ PP.setPPCallbacks(Callbacks);
+
+ // After we have configured the preprocessor, enter the main file.
+ PP.EnterMainSourceFile();
+
+ // Consume all of the tokens that come from the predefines buffer. Those
+ // should not be emitted into the output and are guaranteed to be at the
+ // start.
+ const SourceManager &SourceMgr = PP.getSourceManager();
+ Token Tok;
+ do PP.Lex(Tok);
+ while (Tok.isNot(tok::eof) && Tok.getLocation().isFileID() &&
+ !strcmp(SourceMgr.getPresumedLoc(Tok.getLocation()).getFilename(),
+ "<predefines>"));
- // Read all the preprocessed tokens, printing them out to the stream.
- PrintPreprocessedTokens(PP, Tok, Callbacks, OS);
- OS << '\n';
+ // Read all the preprocessed tokens, printing them out to the stream.
+ PrintPreprocessedTokens(PP, Tok, Callbacks, OS);
+ OS << '\n';
+ }
// Flush the ostream.
OS.flush();
Modified: cfe/trunk/include/clang/Lex/MacroInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/MacroInfo.h?rev=63926&r1=63925&r2=63926&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/MacroInfo.h (original)
+++ cfe/trunk/include/clang/Lex/MacroInfo.h Fri Feb 6 00:45:26 2009
@@ -116,6 +116,7 @@
/// Arguments - The list of arguments for a function-like macro. This can be
/// empty, for, e.g. "#define X()".
typedef IdentifierInfo* const *arg_iterator;
+ bool arg_empty() const { return NumArguments == 0; }
arg_iterator arg_begin() const { return ArgumentList; }
arg_iterator arg_end() const { return ArgumentList+NumArguments; }
unsigned getNumArgs() const { return NumArguments; }
@@ -163,6 +164,7 @@
typedef llvm::SmallVector<Token, 8>::const_iterator tokens_iterator;
tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); }
tokens_iterator tokens_end() const { return ReplacementTokens.end(); }
+ bool tokens_empty() const { return ReplacementTokens.empty(); }
/// AddTokenToBody - Add the specified token to the replacement text for the
/// macro.
Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=63926&r1=63925&r2=63926&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Fri Feb 6 00:45:26 2009
@@ -13,7 +13,7 @@
//
// Options to support:
// -H - Print the name of each header file used.
-// -d[MDNI] - Dump various things.
+// -d[DNI] - Dump various things.
// -fworking-directory - #line's with preprocessor's working dir.
// -fpreprocessed
// -dependency-file,-M,-MM,-MF,-MG,-MP,-MT,-MQ,-MD,-MMD
Added: cfe/trunk/test/Preprocessor/dump_macros.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/dump_macros.c?rev=63926&view=auto
==============================================================================
--- cfe/trunk/test/Preprocessor/dump_macros.c (added)
+++ cfe/trunk/test/Preprocessor/dump_macros.c Fri Feb 6 00:45:26 2009
@@ -0,0 +1,31 @@
+// RUN: clang -E -dM %s -o %t &&
+
+// Space even without expansion tokens
+// RUN: grep "#define A(x) " %t &&
+#define A(x)
+
+// Space before expansion list.
+// RUN: grep "#define B(x,y) x y" %t &&
+#define B(x,y)x y
+
+// No space in expansion list.
+// RUN: grep "#define C(x,y) x y" %t &&
+#define C(x, y) x y
+
+// No paste avoidance.
+// RUN: grep "#define X() .." %t &&
+#define X() ..
+
+// Simple test.
+// RUN: grep "#define Y ." %t &&
+// RUN: grep "#define Z X()Y" %t &&
+#define Y .
+#define Z X()Y
+
+// gcc prints macros at end of translation unit, so last one wins.
+// RUN: grep "#define foo 2" %t &&
+// RUN: not grep "#define foo 1" %t
+#define foo 1
+#undef foo
+#define foo 2
+
More information about the cfe-commits
mailing list