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

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


Author: sabre
Date: Wed Jul 11 11:23:08 2007
New Revision: 38606

URL: http://llvm.org/viewvc/llvm-project?rev=38606&view=rev
Log:
Implement the _Pragma-style of pragma handling, implementing
test/Preprocessor/_Pragma-poison.c.

This unifies the MacroStack and IncludeStack together into IncludeMacroStack.

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

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

==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:23:08 2007
@@ -31,8 +31,6 @@
 //
 // TODO: Implement the include guard optimization.
 //
-// Predefined Macros: _Pragma, ...
-//
 //===----------------------------------------------------------------------===//
 
 #include "clang/Lex/Preprocessor.h"
@@ -59,7 +57,7 @@
   NumDirectives = NumIncluded = NumDefined = NumUndefined = NumPragma = 0;
   NumIf = NumElse = NumEndif = 0;
   NumEnteredSourceFiles = NumMacroExpanded = NumFastMacroExpanded = 0;
-  MaxIncludeStackDepth = MaxMacroStackDepth = 0;
+  MaxIncludeStackDepth = 0;
   NumSkipped = 0;
     
   // Macro expansion is enabled.
@@ -81,9 +79,10 @@
   // Free any active lexers.
   delete CurLexer;
   
-  while (!IncludeStack.empty()) {
-    delete IncludeStack.back().TheLexer;
-    IncludeStack.pop_back();
+  while (!IncludeMacroStack.empty()) {
+    delete IncludeMacroStack.back().TheLexer;
+    delete IncludeMacroStack.back().TheMacroExpander;
+    IncludeMacroStack.pop_back();
   }
   
   // Release pragma information.
@@ -206,8 +205,6 @@
 
   std::cerr << NumMacroExpanded << " macros expanded, "
             << NumFastMacroExpanded << " on the fast path.\n";
-  if (MaxMacroStackDepth > 1)
-    std::cerr << "  " << MaxMacroStackDepth << " max macroexpand stack depth\n";
 }
 
 //===----------------------------------------------------------------------===//
@@ -356,22 +353,30 @@
 /// on failure.
 void Preprocessor::EnterSourceFile(unsigned FileID,
                                    const DirectoryLookup *CurDir) {
+  assert(CurMacroExpander == 0 && "Cannot #include a file inside a macro!");
   ++NumEnteredSourceFiles;
   
-  // Add the current lexer to the include stack.
-  if (CurLexer) {
-    IncludeStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup));
-  } else {
-    assert(CurMacroExpander == 0 && "Cannot #include a file inside a macro!");
-  }
+  if (MaxIncludeStackDepth < IncludeMacroStack.size())
+    MaxIncludeStackDepth = IncludeMacroStack.size();
 
-  if (MaxIncludeStackDepth < IncludeStack.size())
-    MaxIncludeStackDepth = IncludeStack.size();
-  
   const SourceBuffer *Buffer = SourceMgr.getBuffer(FileID);
+  Lexer *TheLexer = new Lexer(Buffer, FileID, *this);
+  EnterSourceFileWithLexer(TheLexer, CurDir);
+}  
+  
+/// EnterSourceFile - Add a source file to the top of the include stack and
+/// start lexing tokens from it instead of the current buffer.
+void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, 
+                                            const DirectoryLookup *CurDir) {
+    
+  // Add the current lexer to the include stack.
+  if (CurLexer || CurMacroExpander)
+    IncludeMacroStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup,
+                                                 CurMacroExpander));
   
-  CurLexer     = new Lexer(Buffer, FileID, *this);
+  CurLexer = TheLexer;
   CurDirLookup = CurDir;
+  CurMacroExpander = 0;
   
   // Notify the client, if desired, that we are in a new source file.
   if (FileChangeHandler) {
@@ -387,21 +392,17 @@
   }
 }
 
+
+
 /// 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) {
   IdentifierTokenInfo *Identifier = Tok.getIdentifierInfo();
   MacroInfo &MI = *Identifier->getMacroInfo();
-  if (CurLexer) {
-    IncludeStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup));
-    CurLexer     = 0;
-    CurDirLookup = 0;
-  } else if (CurMacroExpander) {
-    MacroStack.push_back(CurMacroExpander);
-  }
-
-  if (MaxMacroStackDepth < MacroStack.size())
-    MaxMacroStackDepth = MacroStack.size();
+  IncludeMacroStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup,
+                                               CurMacroExpander));
+  CurLexer     = 0;
+  CurDirLookup = 0;
   
   // TODO: Figure out arguments.
   
@@ -432,18 +433,18 @@
 /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
 /// identifier table.
 void Preprocessor::RegisterBuiltinMacros() {
-  // FIXME: implement them all, including _Pragma.
   Ident__LINE__ = RegisterBuiltinMacro("__LINE__");
   Ident__FILE__ = RegisterBuiltinMacro("__FILE__");
   Ident__DATE__ = RegisterBuiltinMacro("__DATE__");
   Ident__TIME__ = RegisterBuiltinMacro("__TIME__");
+  Ident_Pragma  = RegisterBuiltinMacro("_Pragma");
   
   // GCC Extensions.
   Ident__BASE_FILE__     = RegisterBuiltinMacro("__BASE_FILE__");
   Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__");
   Ident__TIMESTAMP__     = RegisterBuiltinMacro("__TIMESTAMP__");
-  // _Pragma
   
+  // FIXME: implement them all:
 //Pseudo #defines.
   // __STDC__    1 if !stdc_0_in_system_headers and "std"
   // __STDC_VERSION__
@@ -457,12 +458,14 @@
 void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier, 
                                                  MacroInfo *MI) {
   ++NumMacroExpanded;
-  // If we started lexing a macro, enter the macro expansion body.
-  // FIXME: Read/Validate the argument list here!
 
   // If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
   if (MI->isBuiltinMacro())
-    return ExpandBuiltinMacro(Identifier, MI);
+    return ExpandBuiltinMacro(Identifier);
+  
+  // If we started lexing a macro, enter the macro expansion body.
+  // FIXME: 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.
@@ -553,13 +556,19 @@
 
 /// 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'.
-void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI) {
+void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok) {
   // Figure out which token this is.
   IdentifierTokenInfo *ITI = Tok.getIdentifierInfo();
   assert(ITI && "Can't be a macro without id info!");
-  char TmpBuffer[100];
   
+  // If this is an _Pragma directive, expand it, invoke the pragma handler, then
+  // lex the token after it.
+  if (ITI == Ident_Pragma)
+    return Handle_Pragma(Tok);
   
+  char TmpBuffer[100];
+
+  // Set up the return result.
   Tok.SetIdentifierInfo(0);
   Tok.ClearFlag(LexerToken::NeedsCleaning);
   
@@ -621,9 +630,7 @@
     // Get the file that we are lexing out of.  If we're currently lexing from
     // a macro, dig into the include stack.
     const FileEntry *CurFile = 0;
-    Lexer *TheLexer = CurLexer;
-    if (TheLexer == 0 && !IncludeStack.empty())
-      TheLexer = IncludeStack.back().TheLexer;
+    Lexer *TheLexer = getCurrentLexer();
     
     if (TheLexer)
       CurFile = SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
@@ -703,15 +710,16 @@
   
   // If this is a #include'd file, pop it off the include stack and continue
   // lexing the #includer file.
-  if (!IncludeStack.empty()) {
+  if (!IncludeMacroStack.empty()) {
     // We're done with the #included file.
     delete CurLexer;
-    CurLexer     = IncludeStack.back().TheLexer;
-    CurDirLookup = IncludeStack.back().TheDirLookup;
-    IncludeStack.pop_back();
+    CurLexer         = IncludeMacroStack.back().TheLexer;
+    CurDirLookup     = IncludeMacroStack.back().TheDirLookup;
+    CurMacroExpander = IncludeMacroStack.back().TheMacroExpander;
+    IncludeMacroStack.pop_back();
 
     // Notify the client, if desired, that we are in a new source file.
-    if (FileChangeHandler && !isEndOfMacro) {
+    if (FileChangeHandler && !isEndOfMacro && CurLexer) {
       DirectoryLookup::DirType FileType = DirectoryLookup::NormalHeaderDir;
       
       // Get the file entry for the current file.
@@ -746,16 +754,9 @@
   CurMacroExpander->getMacro().EnableMacro();
   delete CurMacroExpander;
 
-  if (!MacroStack.empty()) {
-    // In a nested macro invocation, continue lexing from the macro.
-    CurMacroExpander = MacroStack.back();
-    MacroStack.pop_back();
-    return Lex(Result);
-  } else {
-    CurMacroExpander = 0;
-    // Handle this like a #include file being popped off the stack.
-    return HandleEndOfFile(Result, true);
-  }
+  // Handle this like a #include file being popped off the stack.
+  CurMacroExpander = 0;
+  return HandleEndOfFile(Result, true);
 }
 
 
@@ -831,7 +832,7 @@
                                                 bool FoundNonSkipPortion,
                                                 bool FoundElse) {
   ++NumSkipped;
-  assert(MacroStack.empty() && CurMacroExpander == 0 && CurLexer &&
+  assert(CurMacroExpander == 0 && CurLexer &&
          "Lexing a macro, not a file?");
 
   CurLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/false,
@@ -1059,7 +1060,7 @@
       if (Directive[0] == 'i' && !strcmp(Directive, "import"))
         return HandleImportDirective(Result);
       if (Directive[0] == 'p' && !strcmp(Directive, "pragma"))
-        return HandlePragmaDirective(Result);
+        return HandlePragmaDirective();
       if (Directive[0] == 'a' && !strcmp(Directive, "assert"))
         isExtension = true;  // FIXME: implement #assert
       break;
@@ -1132,7 +1133,7 @@
   CheckEndOfDirective("#include");
 
   // Check that we don't have infinite #include recursion.
-  if (IncludeStack.size() == MaxAllowedIncludeStackDepth-1)
+  if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1)
     return Diag(FilenameTok, diag::err_pp_include_too_deep);
   
   // Find out whether the filename is <x> or "x".
@@ -1187,7 +1188,7 @@
   // the current found directory.  If we can't do this, issue a
   // diagnostic.
   const DirectoryLookup *Lookup = CurDirLookup;
-  if (IncludeStack.empty()) {
+  if (isInPrimaryFile()) {
     Lookup = 0;
     Diag(IncludeNextTok, diag::pp_include_next_in_primary);
   } else if (Lookup == 0) {
@@ -1425,10 +1426,9 @@
 // Preprocessor Pragma Directive Handling.
 //===----------------------------------------------------------------------===//
 
-/// HandlePragmaDirective - The "#pragma" directive has been parsed with
-/// PragmaTok containing the "pragma" identifier.  Lex the rest of the pragma,
-/// passing it to the registered pragma handlers.
-void Preprocessor::HandlePragmaDirective(LexerToken &PragmaTok) {
+/// HandlePragmaDirective - The "#pragma" directive has been parsed.  Lex the
+/// rest of the pragma, passing it to the registered pragma handlers.
+void Preprocessor::HandlePragmaDirective() {
   ++NumPragma;
   
   // Invoke the first level of pragma handlers which reads the namespace id.
@@ -1440,10 +1440,89 @@
     DiscardUntilEndOfDirective();
 }
 
+/// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
+/// return the first token after the directive.  The _Pragma token has just
+/// been read into 'Tok'.
+void Preprocessor::Handle_Pragma(LexerToken &Tok) {
+  // Remember the pragma token location.
+  SourceLocation PragmaLoc = Tok.getLocation();
+  
+  // Read the '('.
+  Lex(Tok);
+  if (Tok.getKind() != tok::l_paren)
+    return Diag(PragmaLoc, diag::err__Pragma_malformed);
+
+  // Read the '"..."'.
+  Lex(Tok);
+  if (Tok.getKind() != tok::string_literal)
+    return Diag(PragmaLoc, diag::err__Pragma_malformed);
+  
+  // Remember the string.
+  std::string StrVal = getSpelling(Tok);
+  SourceLocation StrLoc = Tok.getLocation();
+
+  // Read the ')'.
+  Lex(Tok);
+  if (Tok.getKind() != tok::r_paren)
+    return Diag(PragmaLoc, diag::err__Pragma_malformed);
+  
+  // The _Pragma is lexically sound.  Destringize according to C99 6.10.9.1.
+  if (StrVal[0] == 'L')  // Remove L prefix.
+    StrVal.erase(StrVal.begin());
+  assert(StrVal[0] == '"' && StrVal[StrVal.size()-1] == '"' &&
+         "Invalid string token!");
+  
+  // Remove the front quote, replacing it with a space, so that the pragma
+  // contents appear to have a space before them.
+  StrVal[0] = ' ';
+  
+  // Replace the terminating quote with a \n\0.
+  StrVal[StrVal.size()-1] = '\n';
+  StrVal += '\0';
+  
+  // Remove escaped quotes and escapes.
+  for (unsigned i = 0, e = StrVal.size(); i != e-1; ++i) {
+    if (StrVal[i] == '\\' &&
+        (StrVal[i+1] == '\\' || StrVal[i+1] == '"')) {
+      // \\ -> '\' and \" -> '"'.
+      StrVal.erase(StrVal.begin()+i);
+      --e;
+    }
+  }
+  
+  // Plop the string (including the trailing null) into a buffer where we can
+  // lex it.
+  SourceLocation TokLoc = ScratchBuf->getToken(&StrVal[0], StrVal.size());
+  const char *StrData = SourceMgr.getCharacterData(TokLoc);
+
+  // FIXME: Create appropriate mapping info for this FileID, so that we know the
+  // tokens are coming out of the input string (StrLoc).
+  unsigned FileID = TokLoc.getFileID();
+  assert(FileID && "Could not create FileID for predefines?");
+
+  // Make and enter a lexer object so that we lex and expand the tokens just
+  // like any others.
+  Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID), FileID, *this,
+                        StrData, StrData+StrVal.size()-1 /* no null */);
+  EnterSourceFileWithLexer(TL, 0);
+  
+  // Ensure that the lexer thinks it is inside a directive, so that end \n will
+  // return an EOM token.
+  TL->ParsingPreprocessorDirective = true;
+  
+  // With everything set up, lex this as a #pragma directive.
+  HandlePragmaDirective();
+  
+  // Finally, return whatever came after the pragma directive.
+  return Lex(Tok);
+}
+
+
+
 /// HandlePragmaOnce - Handle #pragma once.  OnceTok is the 'once'.
 ///
 void Preprocessor::HandlePragmaOnce(LexerToken &OnceTok) {
-  if (IncludeStack.empty()) {
+  if (isInPrimaryFile()) {
     Diag(OnceTok, diag::pp_pragma_once_in_main_file);
     return;
   }
@@ -1501,7 +1580,7 @@
 /// HandlePragmaSystemHeader - Implement #pragma GCC system_header.  We know
 /// that the whole directive has been parsed.
 void Preprocessor::HandlePragmaSystemHeader(LexerToken &SysHeaderTok) {
-  if (IncludeStack.empty()) {
+  if (isInPrimaryFile()) {
     Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
     return;
   }
@@ -1540,11 +1619,7 @@
   if (File == 0)
     return Diag(FilenameTok, diag::err_pp_file_not_found);
   
-  Lexer *TheLexer = CurLexer;
-  if (TheLexer == 0) {
-    assert(!IncludeStack.empty() && "No current lexer?");
-    TheLexer = IncludeStack.back().TheLexer;
-  }
+  Lexer *TheLexer = getCurrentLexer();
   const FileEntry *CurFile =
     SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
 

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=38606&r1=38605&r2=38606&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:23:08 2007
@@ -171,6 +171,8 @@
      "can only poison identifier tokens")
 DIAG(err_pp_used_poisoned_id, ERROR,
      "attempt to use a poisoned identifier")
+DIAG(err__Pragma_malformed, ERROR,
+     "_Pragma takes a parenthesized string literal")
 
 // Should be a sorry?
 DIAG(err_pp_I_dash_not_supported, ERROR,

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=38606&r1=38605&r2=38606&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Preprocessor.h Wed Jul 11 11:23:08 2007
@@ -98,6 +98,7 @@
   IdentifierTokenInfo *Ident__INCLUDE_LEVEL__;        // __INCLUDE_LEVEL__
   IdentifierTokenInfo *Ident__BASE_FILE__;            // __BASE_FILE__
   IdentifierTokenInfo *Ident__TIMESTAMP__;            // __TIMESTAMP__
+  IdentifierTokenInfo *Ident_Pragma;                  // _Pragma
   
   SourceLocation DATELoc, TIMELoc;
 public:
@@ -138,25 +139,23 @@
   /// FileEntry, if CurLexer is non-null and if applicable.  This allows us to
   /// implement #include_next and find directory-specific properties.
   const DirectoryLookup *CurDirLookup;
+
+  /// CurMacroExpander - This is the current macro we are expanding, if we are
+  /// expanding a macro.  One of CurLexer and CurMacroExpander must be null.
+  MacroExpander *CurMacroExpander;
   
-  /// IncludeStack - This keeps track of the stack of files currently #included,
-  /// not counting CurLexer.
+  /// IncludeMacroStack - This keeps track of the stack of files currently
+  /// #included, and macros currently being expanded from, not counting
+  /// CurLexer/CurMacroExpander.
   struct IncludeStackInfo {
     Lexer *TheLexer;
     const DirectoryLookup *TheDirLookup;
-    IncludeStackInfo(Lexer *L, const DirectoryLookup *D)
-      : TheLexer(L), TheDirLookup(D) {
+    MacroExpander *TheMacroExpander;
+    IncludeStackInfo(Lexer *L, const DirectoryLookup *D, MacroExpander *M)
+      : TheLexer(L), TheDirLookup(D), TheMacroExpander(M) {
     }
   };
-  std::vector<IncludeStackInfo> IncludeStack;
-  
-  /// CurMacroExpander - This is the current macro we are expanding, if we are
-  /// expanding a macro.  One of CurLexer and CurMacroExpander must be null.
-  MacroExpander *CurMacroExpander;
-  
-  /// MacroStack - This keeps track of the macros that are recursively being
-  /// expanded.
-  std::vector<MacroExpander*> MacroStack;
+  std::vector<IncludeStackInfo> IncludeMacroStack;
   
   
   /// PreFileInfo - The preprocessor keeps track of this information for each
@@ -187,7 +186,7 @@
   unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
   unsigned NumIf, NumElse, NumEndif;
   unsigned NumEnteredSourceFiles, MaxIncludeStackDepth;
-  unsigned NumMacroExpanded, NumFastMacroExpanded, MaxMacroStackDepth;
+  unsigned NumMacroExpanded, NumFastMacroExpanded;
   unsigned NumSkipped;
 public:
   Preprocessor(Diagnostic &diags, const LangOptions &opts, FileManager &FM,
@@ -211,6 +210,29 @@
     return CurLexer == L;
   }
   
+  /// isInPrimaryFile - Return true if we're in the top-level file, not in a
+  /// #include.
+  ///
+  bool isInPrimaryFile() const {
+    /// If there are any stacked lexers, we're in a #include.
+    for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i)
+      if (IncludeMacroStack[i].TheLexer)
+        return false;
+    return true;
+  }
+  
+  /// getCurrentLexer - Return the current lexer being lexed from.  Note that
+  /// this ignores any potentially active macro expansions going on at the time.
+  Lexer *getCurrentLexer() const {
+    if (CurLexer) return CurLexer;
+    
+    // Look for a stacked lexer.
+    for (unsigned i = IncludeMacroStack.size(); i != 0; --i)
+      if (IncludeMacroStack[i].TheLexer)  // Ignore macro expansions.
+        return IncludeMacroStack[i].TheLexer;
+    return 0;
+  }
+  
   /// SetSearchPaths - Interface for setting the file search paths.
   ///
   void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
@@ -423,7 +445,17 @@
 
   /// 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'.
-  void ExpandBuiltinMacro(LexerToken &Tok, MacroInfo *MI);
+  void ExpandBuiltinMacro(LexerToken &Tok);
+  
+  /// Handle_Pragma - Read a _Pragma directive, slice it up, process it, then
+  /// return the first token after the directive.  The _Pragma token has just
+  /// been read into 'Tok'.
+  void Handle_Pragma(LexerToken &Tok);
+  
+  
+  /// EnterSourceFile - Add a source file to the top of the include stack and
+  /// start lexing tokens from it instead of the current buffer.
+  void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir);
   
   //===--------------------------------------------------------------------===//
   /// Handle*Directive - implement the various preprocessor directives.  These
@@ -453,7 +485,7 @@
   void HandleElifDirective(LexerToken &Tok);
   
   // Pragmas.
-  void HandlePragmaDirective(LexerToken &Result);
+  void HandlePragmaDirective();
 public:
   void HandlePragmaOnce(LexerToken &OnceTok);
   void HandlePragmaPoison(LexerToken &PoisonTok);





More information about the cfe-commits mailing list