[cfe-commits] r38685 - in /cfe/cfe/trunk: Lex/MacroExpander.cpp Lex/Preprocessor.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Lex/MacroExpander.h include/clang/Lex/MacroInfo.h include/clang/Lex/Preprocessor.h

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


Author: sabre
Date: Wed Jul 11 11:23:48 2007
New Revision: 38685

URL: http://llvm.org/viewvc/llvm-project?rev=38685&view=rev
Log:
Read, remember, and validate the arguments provided the a function-style
macro invocation.

Modified:
    cfe/cfe/trunk/Lex/MacroExpander.cpp
    cfe/cfe/trunk/Lex/Preprocessor.cpp
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/cfe/trunk/include/clang/Lex/MacroExpander.h
    cfe/cfe/trunk/include/clang/Lex/MacroInfo.h
    cfe/cfe/trunk/include/clang/Lex/Preprocessor.h

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

==============================================================================
--- cfe/cfe/trunk/Lex/MacroExpander.cpp (original)
+++ cfe/cfe/trunk/Lex/MacroExpander.cpp Wed Jul 11 11:23:48 2007
@@ -18,8 +18,29 @@
 using namespace llvm;
 using namespace clang;
 
-MacroExpander::MacroExpander(LexerToken &Tok, Preprocessor &pp)
-  : Macro(*Tok.getIdentifierInfo()->getMacroInfo()), PP(pp), CurToken(0),
+//===----------------------------------------------------------------------===//
+// MacroFormalArgs Implementation
+//===----------------------------------------------------------------------===//
+
+MacroFormalArgs::MacroFormalArgs(const MacroInfo *MI) {
+  assert(MI->isFunctionLike() &&
+         "Can't have formal args for an object-like macro!");
+  // Reserve space for arguments to avoid reallocation.
+  unsigned NumArgs = MI->getNumArgs();
+  if (MI->isC99Varargs() || MI->isGNUVarargs())
+    NumArgs += 3;    // Varargs can have more than this, just some guess.
+  
+  ArgTokens.reserve(NumArgs);
+}
+
+//===----------------------------------------------------------------------===//
+// MacroExpander Implementation
+//===----------------------------------------------------------------------===//
+
+MacroExpander::MacroExpander(LexerToken &Tok, MacroFormalArgs *Formals,
+                             Preprocessor &pp)
+  : Macro(*Tok.getIdentifierInfo()->getMacroInfo()), FormalArgs(Formals),
+    PP(pp), CurToken(0),
     InstantiateLoc(Tok.getLocation()),
     AtStartOfLine(Tok.isAtStartOfLine()),
     HasLeadingSpace(Tok.hasLeadingSpace()) {

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

==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:23:48 2007
@@ -11,10 +11,6 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// TODO: GCC Diagnostics emitted by the lexer:
-//
-// ERROR  : __VA_ARGS__ can only appear in the expansion of a C99 variadic macro
-//
 // Options to support:
 //   -H       - Print the name of each header file used.
 //   -C -CC   - Do not discard comments for cpp.
@@ -28,8 +24,6 @@
 // Messages to emit:
 //   "Multiple include guards may be useful for:\n"
 //
-// TODO: Implement the include guard optimization.
-//
 //===----------------------------------------------------------------------===//
 
 #include "clang/Lex/Preprocessor.h"
@@ -55,13 +49,16 @@
   // Clear stats.
   NumDirectives = NumIncluded = NumDefined = NumUndefined = NumPragma = 0;
   NumIf = NumElse = NumEndif = 0;
-  NumEnteredSourceFiles = NumMacroExpanded = NumFastMacroExpanded = 0;
+  NumEnteredSourceFiles = 0;
+  NumMacroExpanded = NumFnMacroExpanded = NumBuiltinMacroExpanded = 0;
+  NumFastMacroExpanded = 0;
   MaxIncludeStackDepth = 0; NumMultiIncludeFileOptzn = 0;
   NumSkipped = 0;
     
   // Macro expansion is enabled.
   DisableMacroExpansion = false;
   SkippingContents = false;
+  InMacroFormalArgs = false;
 
   // There is no file-change handler yet.
   FileChangeHandler = 0;
@@ -199,7 +196,8 @@
   std::cerr << "  " << NumPragma << " #pragma.\n";
   std::cerr << NumSkipped << " #if/#ifndef#ifdef regions skipped\n";
 
-  std::cerr << NumMacroExpanded << " macros expanded, "
+  std::cerr << NumMacroExpanded << "/" << NumFnMacroExpanded << "/"
+            << NumBuiltinMacroExpanded << " obj/fn/builtin macros expanded, "
             << NumFastMacroExpanded << " on the fast path.\n";
 }
 
@@ -433,7 +431,7 @@
 
 /// EnterMacro - Add a Macro to the top of the include stack and start lexing
 /// tokens from it instead of the current buffer.
-void Preprocessor::EnterMacro(LexerToken &Tok) {
+void Preprocessor::EnterMacro(LexerToken &Tok, MacroFormalArgs *Formals) {
   IdentifierInfo *Identifier = Tok.getIdentifierInfo();
   MacroInfo &MI = *Identifier->getMacroInfo();
   IncludeMacroStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup,
@@ -441,12 +439,10 @@
   CurLexer     = 0;
   CurDirLookup = 0;
   
-  // TODO: Figure out arguments.
-  
   // Mark the macro as currently disabled, so that it is not recursively
   // expanded.
   MI.DisableMacro();
-  CurMacroExpander = new MacroExpander(Tok, *this);
+  CurMacroExpander = new MacroExpander(Tok, Formals, *this);
 }
 
 //===----------------------------------------------------------------------===//
@@ -485,24 +481,63 @@
 
 /// HandleMacroExpandedIdentifier - If an identifier token is read that is to be
 /// expanded as a macro, handle it and return the next token as 'Identifier'.
-void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier, 
+bool Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier, 
                                                  MacroInfo *MI) {
-  ++NumMacroExpanded;
+  
+  // If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
+  if (MI->isBuiltinMacro()) {
+    ExpandBuiltinMacro(Identifier);
+    return false;
+  }
+  
+  /// FormalArgs - If this is a function-like macro expansion, this contains,
+  /// for each macro argument, the list of tokens that were provided to the
+  /// invocation.
+  MacroFormalArgs *FormalArgs = 0;
+  
+  // If this is a function-like macro, read the arguments.
+  if (MI->isFunctionLike()) {
+    // FIXME: We need to query to see if the ( exists without reading it.
+    
+    // C99 6.10.3p10: If the preprocessing token immediately after the the macro
+    // name isn't a '(', this macro should not be expanded.
+    bool isFunctionInvocation = true;
+    if (!isFunctionInvocation)
+      return true;
+    
+    LexerToken Tok;
+    LexUnexpandedToken(Tok);
+    assert(Tok.getKind() == tok::l_paren &&
+           "not a function-like macro invocation!");
+
+    // Remember that we are now parsing the arguments to a macro invocation.
+    // Preprocessor directives used inside macro arguments are not portable, and
+    // this enables the warning.
+    InMacroFormalArgs = true;
+    FormalArgs = ReadFunctionLikeMacroFormalArgs(Identifier, MI);
+    
+    // Finished parsing args.
+    InMacroFormalArgs = false;
+    
+    // If there was an error parsing the arguments, bail out.
+    if (FormalArgs == 0) return false;
+    
+    ++NumFnMacroExpanded;
+  } else {
+    ++NumMacroExpanded;
+  }
   
   // Notice that this macro has been used.
   MI->setIsUsed(true);
-
-  // If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
-  if (MI->isBuiltinMacro())
-    return ExpandBuiltinMacro(Identifier);
   
   // If we started lexing a macro, enter the macro expansion body.
-  // FIXME: Fn-Like Macros: Read/Validate the argument list here!
-  
   
   // If this macro expands to no tokens, don't bother to push it onto the
   // expansion stack, only to take it right back off.
   if (MI->getNumTokens() == 0) {
+    // No need for formal arg info.
+    delete FormalArgs;
+    
     // Ignore this macro use, just return the next token in the current
     // buffer.
     bool HadLeadingSpace = Identifier.hasLeadingSpace();
@@ -519,13 +554,14 @@
       if (HadLeadingSpace) Identifier.SetFlag(LexerToken::LeadingSpace);
     }
     ++NumFastMacroExpanded;
-    return;
+    return false;
     
   } else if (MI->getNumTokens() == 1 &&
+             // FIXME: Fn-Like Macros: Fast if arg not used.
+             FormalArgs == 0 &&
              // Don't handle identifiers if they need recursive expansion.
              (MI->getReplacementToken(0).getIdentifierInfo() == 0 ||
               !MI->getReplacementToken(0).getIdentifierInfo()->getMacroInfo())){
-    // FIXME: Fn-Like Macros: Function-style macros only if no arguments?
     
     // Otherwise, if this macro expands into a single trivially-expanded
     // token: expand it now.  This handles common cases like 
@@ -555,15 +591,115 @@
     // Since this is not an identifier token, it can't be macro expanded, so
     // we're done.
     ++NumFastMacroExpanded;
-    return;
+    return false;
   }
   
-  // Start expanding the macro (FIXME: Fn-Like Macros: pass arguments).
-  EnterMacro(Identifier);
+  // Start expanding the macro.
+  EnterMacro(Identifier, FormalArgs);
   
   // Now that the macro is at the top of the include stack, ask the
   // preprocessor to read the next token from it.
-  return Lex(Identifier);
+  Lex(Identifier);
+  return false;
+}
+
+/// ReadFunctionLikeMacroFormalArgs - After reading "MACRO(", this method is
+/// invoked to read all of the formal arguments specified for the macro
+/// invocation.  This returns null on error.
+MacroFormalArgs *Preprocessor::
+ReadFunctionLikeMacroFormalArgs(LexerToken &MacroName, MacroInfo *MI) {
+  // Use an auto_ptr here so that the MacroFormalArgs object is deleted on
+  // all error paths.
+  std::auto_ptr<MacroFormalArgs> Args(new MacroFormalArgs(MI));
+  
+  // The number of fixed arguments to parse.
+  unsigned NumFixedArgsLeft = MI->getNumArgs();
+  bool isVariadic = MI->isVariadic();
+  
+  // If this is a C99-style varargs macro invocation, add an extra expected
+  // argument, which will catch all of the varargs formals in one argument.
+  if (MI->isC99Varargs())
+    ++NumFixedArgsLeft;
+  
+  // Outer loop, while there are more arguments, keep reading them.
+  LexerToken Tok;
+  Tok.SetKind(tok::comma);
+  --NumFixedArgsLeft;  // Start reading the first arg.
+  
+  while (Tok.getKind() == tok::comma) {
+    // ArgTokens - Build up a list of tokens that make up this argument.
+    std::vector<LexerToken> ArgTokens;
+    // C99 6.10.3p11: Keep track of the number of l_parens we have seen.
+    unsigned NumParens = 0;
+
+    while (1) {
+      LexUnexpandedToken(Tok);
+      
+      if (Tok.getKind() == tok::eof) {
+        Diag(MacroName, diag::err_unterm_macro_invoc);
+        // Do not lose the EOF.  Return it to the client.
+        MacroName = Tok;
+        return 0;
+      } else if (Tok.getKind() == tok::r_paren) {
+        // If we found the ) token, the macro arg list is done.
+        if (NumParens-- == 0)
+          break;
+      } else if (Tok.getKind() == tok::l_paren) {
+        ++NumParens;
+      } else if (Tok.getKind() == tok::comma && NumParens == 0) {
+        // Comma ends this argument if there are more fixed arguments expected.
+        if (NumFixedArgsLeft)
+          break;
+        
+        // If this is not a variadic macro, too many formals were specified.
+        if (!isVariadic) {
+          // Emit the diagnostic at the macro name in case there is a missing ).
+          // Emitting it at the , could be far away from the macro name.
+          Diag(MacroName, diag::err_too_many_formals_in_macro_invoc);
+          return 0;
+        }
+        // Otherwise, continue to add the tokens to this variable argument.
+      }
+  
+      ArgTokens.push_back(Tok);
+    }
+
+    // Remember the tokens that make up this argument.  This destroys ArgTokens.
+    Args->addArgument(ArgTokens);
+    --NumFixedArgsLeft;
+  };
+  
+  // Okay, we either found the r_paren.  Check to see if we parsed too few
+  // arguments.
+  unsigned NumFormals = Args->getNumArguments();
+  unsigned MinArgsExpected = MI->getNumArgs();
+  
+  // C99 expects us to pass at least one vararg arg (but as an extension, we
+  // don't require this).
+  if (MI->isC99Varargs())
+    ++MinArgsExpected;
+  
+  if (NumFormals < MinArgsExpected) {
+    // There are several cases where too few arguments is ok, handle them now.
+    if (NumFormals+1 == MinArgsExpected && MI->isVariadic()) {
+      // Varargs where the named vararg parameter is missing: ok as extension.
+      // #define A(x, ...)
+      // A("blah")
+      Diag(Tok, diag::ext_missing_varargs_arg);
+    } else if (MI->getNumArgs() == 1) {
+      // #define A(x)
+      //   A()
+      // is ok.  Add an empty argument.
+      std::vector<LexerToken> ArgTokens;
+      Args->addArgument(ArgTokens);
+    } else {
+      // Otherwise, emit the error.
+      Diag(Tok, diag::err_too_few_formals_in_macro_invoc);
+      return 0;
+    }
+  }
+  
+  return Args.release();
 }
 
 /// ComputeDATE_TIME - Compute the current time, enter it into the specified
@@ -599,6 +735,8 @@
   if (II == Ident_Pragma)
     return Handle_Pragma(Tok);
   
+  ++NumBuiltinMacroExpanded;
+
   char TmpBuffer[100];
 
   // Set up the return result.
@@ -750,9 +888,11 @@
       Diag(Identifier, diag::ext_pp_bad_vaargs_use);
   }
   
+  // If this is a macro to be expanded, do it.
   if (MacroInfo *MI = II.getMacroInfo())
     if (MI->isEnabled() && !DisableMacroExpansion)
-      return HandleMacroExpandedIdentifier(Identifier, MI);
+      if (!HandleMacroExpandedIdentifier(Identifier, MI))
+        return;
 
   // Change the kind of this identifier to the appropriate token kind, e.g.
   // turning "for" into a keyword.
@@ -1101,7 +1241,7 @@
   
   // We just parsed a # character at the start of a line, so we're in directive
   // mode.  Tell the lexer this so any newlines we see will be converted into an
-  // EOM token (this terminates the macro).
+  // EOM token (which terminates the directive).
   CurLexer->ParsingPreprocessorDirective = true;
   
   ++NumDirectives;
@@ -1111,9 +1251,19 @@
   // pp-directive.
   bool ReadAnyTokensBeforeDirective = CurLexer->MIOpt.getHasReadAnyTokensVal();
   
-  // Read the next token, the directive flavor.
+  // Read the next token, the directive flavor.  This isn't expanded due to
+  // C99 6.10.3p8.
   LexUnexpandedToken(Result);
   
+  // C99 6.10.3p11: Is this preprocessor directive in macro invocation?  e.g.:
+  //   #define A(x) #x
+  //   A(abc
+  //     #warning blah
+  //   def)
+  // If so, the user is relying on non-portable behavior, emit a diagnostic.
+  if (InMacroFormalArgs)
+    Diag(Result, diag::ext_embedded_directive);
+  
   switch (Result.getKind()) {
   default: break;
   case tok::eom:
@@ -1436,6 +1586,8 @@
   LexerToken Tok;
   LexUnexpandedToken(Tok);
   
+  // FIXME: Enable __VA_ARGS__.
+
   // If this is a function-like macro definition, parse the argument list,
   // marking each of the identifiers as being used as macro arguments.  Also,
   // check other constraints on the first token of the macro body.
@@ -1503,22 +1655,20 @@
     LexUnexpandedToken(Tok);
   }
 
-  unsigned NumTokens = MI->getNumTokens();
-
+  // Clear the "isMacroArg" flags from all the macro arguments.
+  MI->SetIdentifierIsMacroArgFlags(false);
+  
   // Check that there is no paste (##) operator at the begining or end of the
   // replacement list.
+  unsigned NumTokens = MI->getNumTokens();
   if (NumTokens != 0) {
     if (MI->getReplacementToken(0).getKind() == tok::hashhash) {
       Diag(MI->getReplacementToken(0), diag::err_paste_at_start);
-      // Clear the "isMacroArg" flags from all the macro arguments.
-      MI->SetIdentifierIsMacroArgFlags(false);
       delete MI;
       return;
     }
     if (MI->getReplacementToken(NumTokens-1).getKind() == tok::hashhash) {
       Diag(MI->getReplacementToken(NumTokens-1), diag::err_paste_at_end);
-      // Clear the "isMacroArg" flags from all the macro arguments.
-      MI->SetIdentifierIsMacroArgFlags(false);
       delete MI;
       return;
     }
@@ -1546,9 +1696,6 @@
   }
   
   MacroNameTok.getIdentifierInfo()->setMacroInfo(MI);
-  
-  // Clear the "isMacroArg" flags from all the macro arguments.
-  MI->SetIdentifierIsMacroArgFlags(false);
 }
 
 

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=38685&r1=38684&r2=38685&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:23:48 2007
@@ -123,6 +123,10 @@
      "variadic macros were introduced in C99")
 DIAG(ext_named_variadic_macro, EXTENSION,
      "named variadic macros are a GNU extension")
+DIAG(ext_embedded_directive, EXTENSION,
+     "embedding a directive within macro arguments is not portable")
+DIAG(ext_missing_varargs_arg, EXTENSION,
+     "varargs argument missing, but tolerated as an extension")
 
 DIAG(ext_pp_base_file, EXTENSION,
      "__BASE_FILE__ is a language extension")
@@ -207,6 +211,13 @@
      "\"##\" cannot appear at start of macro expansion")
 DIAG(err_paste_at_end, ERROR,
      "\"##\" cannot appear at end of macro expansion")
+DIAG(err_unterm_macro_invoc, ERROR,
+     "unterminated function-like macro invocation")
+DIAG(err_too_many_formals_in_macro_invoc, ERROR,
+     "too many arguments provided to function-like macro invocation")
+DIAG(err_too_few_formals_in_macro_invoc, ERROR,
+     "too few arguments provided to function-like macro invocation")
+
 
 // Should be a sorry?
 DIAG(err_pp_I_dash_not_supported, ERROR,

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=38685&r1=38684&r2=38685&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroExpander.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroExpander.h Wed Jul 11 11:23:48 2007
@@ -15,6 +15,7 @@
 #define LLVM_CLANG_MACROEXPANDER_H
 
 #include "clang/Basic/SourceLocation.h"
+#include <vector>
 
 namespace llvm {
 namespace clang {
@@ -22,6 +23,26 @@
   class Preprocessor;
   class LexerToken;
 
+/// MacroFormalArgs - An instance of this class captures information about
+/// the formal arguments specified to a function-like macro invocation.
+class MacroFormalArgs {
+  std::vector<std::vector<LexerToken> > ArgTokens;
+public:
+  MacroFormalArgs(const MacroInfo *MI);
+  
+  /// addArgument - Add an argument for this invocation.  This method destroys
+  /// the vector passed in to avoid extraneous memory copies.
+  void addArgument(std::vector<LexerToken> &ArgToks) {
+    ArgTokens.push_back(std::vector<LexerToken>());
+    ArgTokens.back().swap(ArgToks);
+  }
+  
+  /// getNumArguments - Return the number of arguments passed into this macro
+  /// invocation.
+  unsigned getNumArguments() const { return ArgTokens.size(); }
+};
+
+  
 /// MacroExpander - This implements a lexer that returns token from a macro body
 /// instead of lexing from a character buffer.
 ///
@@ -29,6 +50,10 @@
   /// 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;
 
   /// PP - The current preprocessor object we are expanding for.
   ///
@@ -45,15 +70,24 @@
   /// that the macro expanded from had these properties.
   bool AtStartOfLine, HasLeadingSpace;
   
+  MacroExpander(const MacroExpander&);  // DO NOT IMPLEMENT
+  void operator=(const MacroExpander&); // DO NOT IMPLEMENT
 public:
-  MacroExpander(LexerToken &Tok, Preprocessor &pp);
+  /// Create a macro expander of the specified macro with the specified formal
+  /// 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;
+  }
   
   MacroInfo &getMacro() const { return Macro; }
 
   /// Lex - Lex and return a token from this macro stream.
   void Lex(LexerToken &Tok);
 };
-  
+
 }  // end namespace llvm
 }  // end namespace clang
 

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=38685&r1=38684&r2=38685&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroInfo.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroInfo.h Wed Jul 11 11:23:48 2007
@@ -104,7 +104,7 @@
   typedef std::vector<IdentifierInfo*>::const_iterator arg_iterator;
   arg_iterator arg_begin() const { return Arguments.begin(); }
   arg_iterator arg_end() const { return Arguments.end(); }
-  
+  unsigned getNumArgs() const { return Arguments.size(); }
   
   /// Function/Object-likeness.  Keep track of whether this macro has formal
   /// parameters.
@@ -117,6 +117,7 @@
   void setIsGNUVarargs() { IsGNUVarargs = true; }
   bool isC99Varargs() const { return IsC99Varargs; }
   bool isGNUVarargs() const { return IsGNUVarargs; }
+  bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; }
   
   /// isBuiltinMacro - Return true if this macro is a builtin macro, such as
   /// __LINE__, which requires processing before expansion.

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

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Preprocessor.h Wed Jul 11 11:23:48 2007
@@ -130,6 +130,7 @@
   // State that changes while the preprocessor runs:
   bool DisableMacroExpansion;    // True if macro expansion is disabled.
   bool SkippingContents;         // True if in a #if 0 block.
+  bool InMacroFormalArgs;        // True if parsing fn macro invocation args.
 
   /// Identifiers - This is mapping/lookup information for all identifiers in
   /// the program, including program keywords.
@@ -199,7 +200,8 @@
   unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
   unsigned NumIf, NumElse, NumEndif;
   unsigned NumEnteredSourceFiles, MaxIncludeStackDepth,NumMultiIncludeFileOptzn;
-  unsigned NumMacroExpanded, NumFastMacroExpanded;
+  unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded;
+  unsigned NumFastMacroExpanded;
   unsigned NumSkipped;
 public:
   Preprocessor(Diagnostic &diags, const LangOptions &opts, FileManager &FM,
@@ -320,8 +322,9 @@
                        bool isMainFile = false);
 
   /// EnterMacro - Add a Macro to the top of the include stack and start lexing
-  /// tokens from it instead of the current buffer.
-  void EnterMacro(LexerToken &Identifier);
+  /// tokens from it instead of the current buffer.  Formals specifies the
+  /// tokens input to a function-like macro.
+  void EnterMacro(LexerToken &Identifier, MacroFormalArgs *Formals);
   
   
   /// Lex - To lex a token from the preprocessor, just pull a token from the
@@ -460,8 +463,15 @@
   IdentifierInfo *RegisterBuiltinMacro(const char *Name);
   
   /// HandleMacroExpandedIdentifier - If an identifier token is read that is to
-  /// be expanded as a macro, handle it and return the next token as 'Tok'.
-  void HandleMacroExpandedIdentifier(LexerToken &Tok, MacroInfo *MI);
+  /// be expanded as a macro, handle it and return the next token as 'Tok'.  If
+  /// the macro should not be expanded return true, otherwise return false.
+  bool HandleMacroExpandedIdentifier(LexerToken &Tok, MacroInfo *MI);
+  
+  /// ReadFunctionLikeMacroFormalArgs - After reading "MACRO(", this method is
+  /// invoked to read all of the formal arguments specified for the macro
+  /// invocation.  This returns null on error.
+  MacroFormalArgs *ReadFunctionLikeMacroFormalArgs(LexerToken &MacroName,
+                                                   MacroInfo *MI);
 
   /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
   /// as a builtin macro, handle it and return the next token as 'Tok'.





More information about the cfe-commits mailing list