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

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:23:59 PDT 2007


Author: sabre
Date: Wed Jul 11 11:23:59 2007
New Revision: 38707

URL: http://llvm.org/viewvc/llvm-project?rev=38707&view=rev
Log:
Set up infrastructure for function-like macro expansion with preexpansion
stringizing, etc.

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

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

==============================================================================
--- cfe/cfe/trunk/Lex/MacroExpander.cpp (original)
+++ cfe/cfe/trunk/Lex/MacroExpander.cpp Wed Jul 11 11:23:59 2007
@@ -33,29 +33,112 @@
   ArgTokens.reserve(NumArgs);
 }
 
+/// StringifyArgument - Implement C99 6.10.3.2p2.
+static LexerToken StringifyArgument(const std::vector<LexerToken> &Toks,
+                                    Preprocessor &PP) {
+  LexerToken Tok;
+  Tok.StartToken();
+  Tok.SetKind(tok::string_literal);
+  
+  std::string Val = "\"XXYZLAKSDFJAS\"";
+  Tok.SetLength(Val.size());
+  Tok.SetLocation(PP.CreateString(&Val[0], Val.size()));
+  return Tok;
+}
+
+/// getStringifiedArgument - Compute, cache, and return the specified argument
+/// that has been 'stringified' as required by the # operator.
+const LexerToken &MacroFormalArgs::getStringifiedArgument(unsigned ArgNo,
+                                                          Preprocessor &PP) {
+  assert(ArgNo < ArgTokens.size() && "Invalid argument number!");
+  if (StringifiedArgs.empty()) {
+    StringifiedArgs.resize(ArgTokens.size());
+    memset(&StringifiedArgs[0], 0, sizeof(StringifiedArgs[0])*ArgTokens.size());
+  }
+  if (StringifiedArgs[ArgNo].getKind() != tok::string_literal)
+    StringifiedArgs[ArgNo] = StringifyArgument(ArgTokens[ArgNo], PP);
+  return StringifiedArgs[ArgNo];
+}
+
 //===----------------------------------------------------------------------===//
 // MacroExpander Implementation
 //===----------------------------------------------------------------------===//
 
 MacroExpander::MacroExpander(LexerToken &Tok, MacroFormalArgs *Formals,
                              Preprocessor &pp)
-  : Macro(*Tok.getIdentifierInfo()->getMacroInfo()), FormalArgs(Formals),
-    PP(pp), CurToken(0),
+  : Macro(*Tok.getIdentifierInfo()->getMacroInfo()),
+    FormalArgs(Formals), PP(pp), CurToken(0),
     InstantiateLoc(Tok.getLocation()),
     AtStartOfLine(Tok.isAtStartOfLine()),
     HasLeadingSpace(Tok.hasLeadingSpace()) {
+  MacroTokens = &Macro.getReplacementTokens();
+
+  // If this is a function-like macro, expand the arguments and change
+  // MacroTokens to point to the expanded tokens.
+  if (Macro.isFunctionLike() && Macro.getNumArgs())
+    ExpandFunctionArguments();
+}
+
+MacroExpander::~MacroExpander() {
+  // If this was a function-like macro that actually uses its arguments, delete
+  // the expanded tokens.
+  if (MacroTokens != &Macro.getReplacementTokens())
+    delete MacroTokens;
+  
+  // MacroExpander owns its formal arguments.
+  delete FormalArgs;
 }
 
+/// Expand the arguments of a function-like macro so that we can quickly
+/// return preexpanded tokens from MacroTokens.
+void MacroExpander::ExpandFunctionArguments() {
+  std::vector<LexerToken> ResultToks;
+  
+  // Loop through the MacroTokens tokens, expanding them into ResultToks.  Keep
+  // track of whether we change anything.  If not, no need to keep them.  If so,
+  // we install the newly expanded sequence as MacroTokens.
+  bool MadeChange = false;
+  for (unsigned i = 0, e = MacroTokens->size(); i != e; ++i) {
+    // If we found the stringify operator, get the argument stringified.  The
+    // preprocessor already verified that the following token is a macro name
+    // when the #define was parsed.
+    const LexerToken &CurTok = (*MacroTokens)[i];
+    if (CurTok.getKind() == tok::hash) {
+      int ArgNo = Macro.getArgumentNum((*MacroTokens)[i+1].getIdentifierInfo());
+      assert(ArgNo != -1 && "Token following # is not an argument?");
+      
+      ResultToks.push_back(FormalArgs->getStringifiedArgument(ArgNo, PP));
+      
+      // FIXME: Should the stringified string leading space flag get set to
+      // match the # or the identifier?
+      
+      MadeChange = true;
+      ++i;  // Skip arg name.
+    } else {
+      // FIXME: handle microsoft charize extension.
+      
+      ResultToks.push_back(CurTok);
+    }
+  }
+  
+  // If anything changed, install this as the new MacroTokens list.
+  if (MadeChange) {
+    // This is deleted in the dtor.
+    std::vector<LexerToken> *Res = new std::vector<LexerToken>();
+    Res->swap(ResultToks);
+    MacroTokens = Res;
+  }
+}
 
 /// Lex - Lex and return a token from this macro stream.
 ///
 void MacroExpander::Lex(LexerToken &Tok) {
   // Lexing off the end of the macro, pop this macro off the expansion stack.
-  if (CurToken == Macro.getNumTokens())
+  if (isAtEnd())
     return PP.HandleEndOfMacro(Tok);
   
   // Get the next token to return.
-  Tok = Macro.getReplacementToken(CurToken++);
+  Tok = (*MacroTokens)[CurToken++];
 
   // The token's current location indicate where the token was lexed from.  We
   // need this information to compute the spelling of the token, but any
@@ -84,8 +167,7 @@
 /// 1, otherwise return 0.
 unsigned MacroExpander::isNextTokenLParen() const {
   // Out of tokens?
-  if (CurToken == Macro.getNumTokens())
+  if (isAtEnd())
     return 2;
-
-  return Macro.getReplacementToken(CurToken).getKind() == tok::l_paren;
+  return (*MacroTokens)[CurToken].getKind() == tok::l_paren;
 }

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=38707&r1=38706&r2=38707&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroExpander.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroExpander.h Wed Jul 11 11:23:59 2007
@@ -27,6 +27,10 @@
 /// the formal arguments specified to a function-like macro invocation.
 class MacroFormalArgs {
   std::vector<std::vector<LexerToken> > ArgTokens;
+  
+  /// 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;
 public:
   MacroFormalArgs(const MacroInfo *MI);
   
@@ -37,6 +41,10 @@
     ArgTokens.back().swap(ArgToks);
   }
   
+  /// getStringifiedArgument - Compute, cache, and return the specified argument
+  /// that has been 'stringified' as required by the # operator.
+  const LexerToken &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP);
+  
   /// getNumArguments - Return the number of arguments passed into this macro
   /// invocation.
   unsigned getNumArguments() const { return ArgTokens.size(); }
@@ -50,7 +58,7 @@
   /// Macro - The macro we are expanding from.
   ///
   MacroInfo &Macro;
-  
+
   /// FormalArgs - The formal arguments specified for a function-like macro, or
   /// null.  The MacroExpander owns the pointed-to object.
   MacroFormalArgs *FormalArgs;
@@ -58,8 +66,13 @@
   /// PP - The current preprocessor object we are expanding for.
   ///
   Preprocessor &PP;
+
+  /// MacroTokens - This is the pointer to the list of tokens that the macro is
+  /// defined to, with arguments expanded for function-like macros.
+  const std::vector<LexerToken> *MacroTokens;
   
   /// CurToken - This is the next token that Lex will return.
+  ///
   unsigned CurToken;
   
   /// InstantiateLoc - The source location where this macro was instantiated.
@@ -77,10 +90,7 @@
   /// arguments.  Note that this ctor takes ownership of the FormalArgs pointer.
   MacroExpander(LexerToken &Tok, MacroFormalArgs *FormalArgs,
                 Preprocessor &pp);
-  ~MacroExpander() {
-    // MacroExpander owns its formal arguments.
-    delete FormalArgs;
-  }
+  ~MacroExpander();
   
   /// isNextTokenLParen - If the next token lexed will pop this macro off the
   /// expansion stack, return 2.  If the next unexpanded token is a '(', return
@@ -91,6 +101,17 @@
 
   /// Lex - Lex and return a token from this macro stream.
   void Lex(LexerToken &Tok);
+  
+private:
+  /// isAtEnd - Return true if the next lex call will pop this macro off the
+  /// include stack.
+  bool isAtEnd() const {
+    return CurToken == MacroTokens->size();
+  }
+  
+  /// Expand the arguments of a function-like macro so that we can quickly
+  /// return preexpanded tokens from MacroTokens.
+  void ExpandFunctionArguments();
 };
 
 }  // end namespace llvm

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

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroInfo.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroInfo.h Wed Jul 11 11:23:59 2007
@@ -98,6 +98,14 @@
   void addArgument(IdentifierInfo *Arg) {
     Arguments.push_back(Arg);
   }
+  
+  /// getArgumentNum - Return the argument number of the specified identifier,
+  /// or -1 if the identifier is not a formal argument identifier.
+  int getArgumentNum(IdentifierInfo *Arg) {
+    for (unsigned i = 0, e = Arguments.size(); i != e; ++i)
+      if (Arguments[i] == Arg) return i;
+    return -1;
+  }
 
   /// Arguments - The list of arguments for a function-like macro.  This can be
   /// empty, for, e.g. "#define X()".
@@ -137,6 +145,10 @@
     assert(Tok < ReplacementTokens.size() && "Invalid token #");
     return ReplacementTokens[Tok];
   }
+  
+  const std::vector<LexerToken> &getReplacementTokens() const {
+    return ReplacementTokens;
+  }
 
   /// AddTokenToBody - Add the specified token to the replacement text for the
   /// macro.





More information about the cfe-commits mailing list