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

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


Author: sabre
Date: Wed Jul 11 11:23:47 2007
New Revision: 38682

URL: http://llvm.org/viewvc/llvm-project?rev=38682&view=rev
Log:
Add identifiers for macro arguments to MacroInfo, check for duplicates,
enhance macro equality testing to verify argument lists match.

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

Modified: cfe/cfe/trunk/Lex/IdentifierTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/IdentifierTable.cpp?rev=38682&r1=38681&r2=38682&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/IdentifierTable.cpp (original)
+++ cfe/cfe/trunk/Lex/IdentifierTable.cpp Wed Jul 11 11:23:47 2007
@@ -199,6 +199,7 @@
   Identifier->TokInfo.TokenID = tok::identifier;
   Identifier->TokInfo.IsExtension = false;
   Identifier->TokInfo.IsPoisoned = false;
+  Identifier->TokInfo.IsMacroArg = false;
   Identifier->TokInfo.FETokenInfo = 0;
 
   // Copy the string information.

Modified: cfe/cfe/trunk/Lex/MacroInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/MacroInfo.cpp?rev=38682&r1=38681&r2=38682&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/MacroInfo.cpp (original)
+++ cfe/cfe/trunk/Lex/MacroInfo.cpp Wed Jul 11 11:23:47 2007
@@ -26,20 +26,30 @@
   IsUsed = true;
 }
 
+/// SetIdentifierIsMacroArgFlags - Set or clear the "isMacroArg" flags on the
+/// identifiers that make up the argument list for this macro.
+void MacroInfo::SetIdentifierIsMacroArgFlags(bool Val) const {
+  for (arg_iterator I = arg_begin(), E = arg_end(); I != E; ++I)
+    (*I)->setIsMacroArg(Val);
+}
 
 /// isIdenticalTo - Return true if the specified macro definition is equal to
 /// this macro in spelling, arguments, and whitespace.  This is used to emit
 /// duplicate definition warnings.  This implements the rules in C99 6.10.3.
 bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const {
-  // TODO: Check param count.
-  
-  // Check # tokens in replacement match.
+  // Check # tokens in replacement, number of args, and various flags all match.
   if (ReplacementTokens.size() != Other.ReplacementTokens.size() ||
+      Arguments.size() != Other.Arguments.size() ||
       isFunctionLike() != Other.isFunctionLike() ||
       isC99Varargs() != Other.isC99Varargs() ||
       isGNUVarargs() != Other.isGNUVarargs())
     return false;
-  
+
+  // Check arguments.
+  for (arg_iterator I = arg_begin(), OI = Other.arg_begin(), E = arg_end();
+       I != E; ++I, ++OI)
+    if (*I != *OI) return false;
+       
   // Check all the tokens.
   for (unsigned i = 0, e = ReplacementTokens.size(); i != e; ++i) {
     const LexerToken &A = ReplacementTokens[i];

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

==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:23:47 2007
@@ -1347,13 +1347,12 @@
 /// parsing the arg list.
 bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) {
   LexerToken Tok;
-  bool isFirst = true;
   while (1) {
     LexUnexpandedToken(Tok);
     switch (Tok.getKind()) {
     case tok::r_paren:
       // Found the end of the argument list.
-      if (isFirst) return false;  // #define FOO()
+      if (MI->arg_begin() == MI->arg_end()) return false;  // #define FOO()
       // Otherwise we have #define FOO(A,)
       Diag(Tok, diag::err_pp_expected_ident_in_arg_list);
       return true;
@@ -1376,13 +1375,19 @@
       Diag(Tok, diag::err_pp_invalid_tok_in_arg_list);
       return true;
     case tok::identifier:
-      isFirst = false;
-      
-      // Fill in Result.IdentifierInfo, looking up the identifier in the
-      // identifier table.
-      IdentifierInfo *II = LookUpIdentifierInfo(Tok);
-      
-      assert(0 && "FIXME: lookup/add identifier, check for conflicts");
+      IdentifierInfo *II = Tok.getIdentifierInfo();
+
+      // If this is already used as an argument, it is used multiple times (e.g.
+      // #define X(A,A.
+      if (II->isMacroArg()) {  // C99 6.10.3p6
+        Diag(Tok, diag::err_pp_duplicate_name_in_arg_list, II->getName());
+        return true;
+      }
+        
+      // Add the argument to the macro info.
+      MI->addArgument(II);
+      // Remember it is an argument now.
+      II->setIsMacroArg(true);
       
       // Lex the token after the identifier.
       LexUnexpandedToken(Tok);
@@ -1431,13 +1436,20 @@
   LexerToken Tok;
   LexUnexpandedToken(Tok);
   
+  // 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.
   if (Tok.getKind() == tok::eom) {
     // If there is no body to this macro, we have no special handling here.
   } else if (Tok.getKind() == tok::l_paren && !Tok.hasLeadingSpace()) {
     // This is a function-like macro definition.  Read the argument list.
     MI->setIsFunctionLike();
     if (ReadMacroDefinitionArgList(MI)) {
+      // Clear the "isMacroArg" flags from all the macro arguments parsed.
+      MI->SetIdentifierIsMacroArgFlags(false);
+      // Forget about MI.
       delete MI;
+      // Throw away the rest of the line.
       if (CurLexer->ParsingPreprocessorDirective)
         DiscardUntilEndOfDirective();
       return;
@@ -1476,11 +1488,15 @@
   if (NumTokens != 0) {
     if (MI->getReplacementToken(0).getKind() == tok::hashhash) {
       SourceLocation Loc = MI->getReplacementToken(0).getLocation();
+      // Clear the "isMacroArg" flags from all the macro arguments.
+      MI->SetIdentifierIsMacroArgFlags(false);
       delete MI;
       return Diag(Loc, diag::err_paste_at_start);
     }
     if (MI->getReplacementToken(NumTokens-1).getKind() == tok::hashhash) {
       SourceLocation Loc = MI->getReplacementToken(NumTokens-1).getLocation();
+      // Clear the "isMacroArg" flags from all the macro arguments.
+      MI->SetIdentifierIsMacroArgFlags(false);
       delete MI;
       return Diag(Loc, diag::err_paste_at_end);
     }
@@ -1509,6 +1525,9 @@
   }
   
   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=38682&r1=38681&r2=38682&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:23:47 2007
@@ -155,6 +155,8 @@
      "expected identifier in macro parameter list")
 DIAG(err_pp_expected_comma_in_arg_list, ERROR,
      "expected comma in macro parameter list")
+DIAG(err_pp_duplicate_name_in_arg_list, ERROR,
+     "duplicate macro parameter name \"%s\"")
 DIAG(err_pp_malformed_ident, ERROR,
      "invalid #ident directive")
 DIAG(err_pp_unterminated_conditional, ERROR,

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

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/IdentifierTable.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/IdentifierTable.h Wed Jul 11 11:23:47 2007
@@ -34,6 +34,7 @@
   tok::TokenKind TokenID:8; // Front-end token ID or tok::identifier.
   bool IsExtension    : 1;  // True if this identifier is a language extension.
   bool IsPoisoned     : 1;  // True if this identifier is poisoned.
+  bool IsMacroArg     : 1;  // True if currently used as a macro argument.
   void *FETokenInfo;        // Managed by the language front-end.
   friend class IdentifierTable;
 public:
@@ -76,6 +77,12 @@
   /// isPoisoned - Return true if this token has been poisoned.
   bool isPoisoned() const { return IsPoisoned; }
   
+  /// IsMacroArg accessors - These indicate if the identifier is currently in
+  /// use as a macro argument identifier.  This is a transient property only
+  /// used during macro definition and expansion.
+  bool isMacroArg() const { return IsMacroArg; }
+  void setIsMacroArg(bool Val) { IsMacroArg = Val; }
+  
   /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
   /// associate arbitrary metadata with this token.
   template<typename T>

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=38682&r1=38681&r2=38682&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroInfo.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroInfo.h Wed Jul 11 11:23:47 2007
@@ -14,7 +14,7 @@
 #ifndef LLVM_CLANG_MACROINFO_H
 #define LLVM_CLANG_MACROINFO_H
 
-#include "clang/Lex/Lexer.h"
+#include "clang/Lex/LexerToken.h"
 #include <vector>
 
 namespace llvm {
@@ -30,8 +30,9 @@
   /// Location - This is the place the macro is defined.
   SourceLocation Location;
 
-  // TODO: Parameter list
-  // TODO: # parameters
+  /// Arguments - The list of arguments for a function-like macro.  This can be
+  /// empty, for, e.g. "#define X()".
+  std::vector<IdentifierInfo*> Arguments;
   
   /// ReplacementTokens - This is the list of tokens that the macro is defined
   /// to.
@@ -91,6 +92,19 @@
   void setIsUsed(bool Val) {
     IsUsed = Val;
   }
+
+  /// addArgument - Add an argument to the list of formal arguments for this
+  /// function-like macro.
+  void addArgument(IdentifierInfo *Arg) {
+    Arguments.push_back(Arg);
+  }
+
+  /// Arguments - The list of arguments for a function-like macro.  This can be
+  /// empty, for, e.g. "#define X()".
+  typedef std::vector<IdentifierInfo*>::const_iterator arg_iterator;
+  arg_iterator arg_begin() const { return Arguments.begin(); }
+  arg_iterator arg_end() const { return Arguments.end(); }
+  
   
   /// Function/Object-likeness.  Keep track of whether this macro has formal
   /// parameters.
@@ -142,6 +156,10 @@
     assert(!IsDisabled && "Cannot disable an already-disabled macro!");
     IsDisabled = true;
   }
+  
+  /// SetIdentifierIsMacroArgFlags - Set or clear the "isMacroArg" flags on the
+  /// identifiers that make up the argument list for this macro.
+  void SetIdentifierIsMacroArgFlags(bool Val) const;
 };
     
 }  // end namespace llvm





More information about the cfe-commits mailing list