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

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


Author: sabre
Date: Wed Jul 11 11:24:05 2007
New Revision: 38720

URL: http://llvm.org/viewvc/llvm-project?rev=38720&view=rev
Log:
Implement basic argument substitution.  This implements
test/Preprocessor/macro_fn_disable_expand.c

Modified:
    cfe/cfe/trunk/Lex/MacroExpander.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=38720&r1=38719&r2=38720&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/MacroExpander.cpp (original)
+++ cfe/cfe/trunk/Lex/MacroExpander.cpp Wed Jul 11 11:24:05 2007
@@ -49,9 +49,27 @@
   EOFTok.StartToken();
   EOFTok.SetKind(tok::eof);
   EOFTok.SetLocation(Loc);
+  EOFTok.SetLength(0);
   UnexpArgTokens.back().push_back(EOFTok);
 }
 
+/// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
+/// by pre-expansion, return false.  Otherwise, conservatively return true.
+bool MacroArgs::ArgNeedsPreexpansion(unsigned ArgNo) const {
+  const std::vector<LexerToken> &ArgTokens = getUnexpArgument(ArgNo);
+  
+  // If there are no identifiers in the argument list, or if the identifiers are
+  // known to not be macros, pre-expansion won't modify it.
+  for (unsigned i = 0, e = ArgTokens.size()-1; i != e; ++i)
+    if (IdentifierInfo *II = ArgTokens[i].getIdentifierInfo()) {
+      if (II->getMacroInfo() && II->getMacroInfo()->isEnabled())
+        // Return true even though the macro could be a function-like macro
+        // without a following '(' token.
+        return true;
+    }
+  return false;
+}
+
 
 /// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
 /// tokens into the literal string token that should be produced by the C #
@@ -206,6 +224,55 @@
       MadeChange = true;
       ++i;  // Skip arg name.
     } else {
+      // Otherwise, if this is not an argument token, just add the token to the
+      // output buffer.
+      IdentifierInfo *II = CurTok.getIdentifierInfo();
+      int ArgNo = II ? Macro.getArgumentNum(II) : -1;
+      if (ArgNo == -1) {
+        ResultToks.push_back(CurTok);
+        continue;
+      }
+      
+      // An argument is expanded somehow, the result is different than the
+      // input.
+      MadeChange = true;
+
+      // Otherwise, this is a use of the argument.  Find out if there is a paste
+      // (##) operator before or after the argument.
+      bool PasteBefore = 
+        !ResultToks.empty() && ResultToks.back().getKind() == tok::hashhash;
+      bool PasteAfter =
+        i+1 != e && (*MacroTokens)[i+1].getKind() == tok::hashhash;
+      
+      // If it is not the LHS/RHS of a ## operator, we must pre-expand the
+      // argument and substitute the expanded tokens into the result.  This is
+      // C99 6.10.3.1p1.
+      if (!PasteBefore && !PasteAfter) {
+        const std::vector<LexerToken> *ArgToks;
+        // Only preexpand the argument if it could possibly need it.  This
+        // avoids some work in common cases.
+        if (ActualArgs->ArgNeedsPreexpansion(ArgNo)) {
+          // FIXME: WRONG
+          ArgToks = &ActualArgs->getUnexpArgument(ArgNo);
+        } else {
+          // If we don't need to pre-expand the argument, just substitute in the
+          // unexpanded tokens.
+          ArgToks = &ActualArgs->getUnexpArgument(ArgNo);
+        }
+        
+        unsigned FirstTok = ResultToks.size();
+        ResultToks.insert(ResultToks.end(), ArgToks->begin(), ArgToks->end()-1);
+        
+        // If any tokens were substituted from the argument, the whitespace
+        // before the first token should match the whitespace of the arg
+        // identifier.
+        if (FirstTok != ResultToks.size())
+          ResultToks[FirstTok].SetFlagValue(LexerToken::LeadingSpace,
+                                            CurTok.hasLeadingSpace());
+        continue;
+      }
+      
+      // FIXME: handle pasted args.      
       ResultToks.push_back(CurTok);
     }
   }

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=38720&r1=38719&r2=38720&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroExpander.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroExpander.h Wed Jul 11 11:24:05 2007
@@ -46,6 +46,10 @@
   /// location at the end of the argument, e.g. the ',' token or the ')'.
   void addArgument(std::vector<LexerToken> &ArgToks, SourceLocation Loc);
   
+  /// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
+  /// by pre-expansion, return false.  Otherwise, conservatively return true.
+  bool ArgNeedsPreexpansion(unsigned ArgNo) const;
+  
   /// getUnexpArgument - Return the unexpanded tokens for the specified formal.
   ///
   const std::vector<LexerToken> &getUnexpArgument(unsigned Arg) const {





More information about the cfe-commits mailing list