[cfe-commits] r38780 - in /cfe/cfe/trunk: Lex/MacroExpander.cpp Lex/Preprocessor.cpp include/clang/Lex/MacroExpander.h

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:24:33 PDT 2007


Author: sabre
Date: Wed Jul 11 11:24:33 2007
New Revision: 38780

URL: http://llvm.org/viewvc/llvm-project?rev=38780&view=rev
Log:
Implement the GNU comma swallowing extension.  This implements
test/Preprocessor/macro_fn_comma_swallow.c

Modified:
    cfe/cfe/trunk/Lex/MacroExpander.cpp
    cfe/cfe/trunk/Lex/Preprocessor.cpp
    cfe/cfe/trunk/include/clang/Lex/MacroExpander.h

Modified: cfe/cfe/trunk/Lex/MacroExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/MacroExpander.cpp?rev=38780&r1=38779&r2=38780&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/MacroExpander.cpp (original)
+++ cfe/cfe/trunk/Lex/MacroExpander.cpp Wed Jul 11 11:24:33 2007
@@ -28,7 +28,7 @@
 /// MacroArgs ctor function - This destroys the vector passed in.
 MacroArgs *MacroArgs::create(const MacroInfo *MI,
                              const LexerToken *UnexpArgTokens,
-                             unsigned NumToks) {
+                             unsigned NumToks, bool VarargsElided) {
   assert(MI->isFunctionLike() &&
          "Can't have args for an object-like macro!");
 
@@ -36,7 +36,7 @@
   MacroArgs *Result = (MacroArgs*)malloc(sizeof(MacroArgs) +
                                          NumToks*sizeof(LexerToken));
   // Construct the macroargs object.
-  new (Result) MacroArgs(NumToks);
+  new (Result) MacroArgs(NumToks, VarargsElided);
   
   // Copy the actual unexpanded tokens to immediately after the result ptr.
   if (NumToks)
@@ -410,8 +410,6 @@
       continue;
     }
     
-    // FIXME: Handle comma swallowing GNU extension.
-    
     // If an empty argument is on the LHS or RHS of a paste, the standard (C99
     // 6.10.3.3p2,3) calls for a bunch of placemarker stuff to occur.  We
     // implement this by eating ## operators when a LHS or RHS expands to
@@ -430,6 +428,17 @@
     assert(PasteBefore && ResultToks.back().getKind() == tok::hashhash);
     NextTokGetsSpace |= ResultToks.back().hasLeadingSpace();
     ResultToks.pop_back();
+    
+    // If this is the __VA_ARGS__ token, and if the argument wasn't provided,
+    // and if the macro had at least one real argument, and if the token before
+    // the ## was a comma, remove the comma.
+    if ((unsigned)ArgNo == Macro->getNumArgs() && // is __VA_ARGS__
+        ActualArgs->isVarargsElidedUse() &&       // Argument elided.
+        !ResultToks.empty() && ResultToks.back().getKind() == tok::comma) {
+      // Never add a space, even if the comma, ##, or arg had a space.
+      NextTokGetsSpace = false;
+      ResultToks.pop_back();
+    }
     continue;
   }
   

Modified: cfe/cfe/trunk/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Preprocessor.cpp?rev=38780&r1=38779&r2=38780&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:24:33 2007
@@ -785,6 +785,9 @@
   // the count.
   MinArgsExpected += MI->isC99Varargs();
   
+  // See MacroArgs instance var for description of this.
+  bool isVarargsElided = false;
+  
   if (NumActuals < MinArgsExpected) {
     // There are several cases where too few arguments is ok, handle them now.
     if (NumActuals+1 == MinArgsExpected && MI->isVariadic()) {
@@ -792,6 +795,10 @@
       // #define A(x, ...)
       // A("blah")
       Diag(Tok, diag::ext_missing_varargs_arg);
+
+      // Remember this occurred if this is a C99 macro invocation with at least
+      // one actual argument.
+      isVarargsElided = (MI->isC99Varargs() && MI->getNumArgs());
     } else if (MI->getNumArgs() == 1) {
       // #define A(x)
       //   A()
@@ -816,7 +823,7 @@
     ArgTokens.push_back(Tok);
   }
   
-  return MacroArgs::create(MI, &ArgTokens[0], ArgTokens.size());
+  return MacroArgs::create(MI, &ArgTokens[0], ArgTokens.size(),isVarargsElided);
 }
 
 /// ComputeDATE_TIME - Compute the current time, enter it into the specified

Modified: cfe/cfe/trunk/include/clang/Lex/MacroExpander.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/MacroExpander.h?rev=38780&r1=38779&r2=38780&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroExpander.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroExpander.h Wed Jul 11 11:24:33 2007
@@ -40,15 +40,23 @@
   /// StringifiedArgs - This contains arguments in 'stringified' form.  If the
   /// stringified form of an argument has not yet been computed, this is empty.
   std::vector<LexerToken> StringifiedArgs;
+
+  /// VarargsElided - True if this is a C99 style varargs macro invocation and
+  /// there was no argument specified for the "..." argument.  If the argument
+  /// was specified (even empty) or this isn't a C99 style varargs function, or
+  /// if in strict mode and the C99 varargs macro had only a ... argument, this
+  /// is false.
+  bool VarargsElided;
   
-  MacroArgs(unsigned NumToks) : NumUnexpArgTokens(NumToks) {}
+  MacroArgs(unsigned NumToks, bool varargsElided)
+    : NumUnexpArgTokens(NumToks), VarargsElided(varargsElided) {}
   ~MacroArgs() {}
 public:
   /// MacroArgs ctor function - Create a new MacroArgs object with the specified
   /// macro and argument info.
   static MacroArgs *create(const MacroInfo *MI,
                            const LexerToken *UnexpArgTokens,
-                           unsigned NumArgTokens);
+                           unsigned NumArgTokens, bool VarargsElided);
   
   /// destroy - Destroy and deallocate the memory for this object.
   ///
@@ -80,6 +88,14 @@
   /// getNumArguments - Return the number of arguments passed into this macro
   /// invocation.
   unsigned getNumArguments() const { return NumUnexpArgTokens; }
+  
+  
+  /// isVarargsElidedUse - Return true if this is a C99 style varargs macro
+  /// invocation and there was no argument specified for the "..." argument.  If
+  /// the argument was specified (even empty) or this isn't a C99 style varargs
+  /// function, or if in strict mode and the C99 varargs macro had only a ...
+  /// argument, this returns false.
+  bool isVarargsElidedUse() const { return VarargsElided; }
 };
 
   





More information about the cfe-commits mailing list