[cfe-commits] r38568 - in /cfe/cfe/trunk: Lex/IdentifierTable.cpp Lex/Lexer.cpp Lex/Pragma.cpp Lex/Preprocessor.cpp README.txt include/clang/Basic/DiagnosticKinds.def include/clang/Lex/IdentifierTable.h include/clang/Lex/Preprocessor.h

sabre at cs.uiuc.edu sabre at cs.uiuc.edu
Wed Jul 11 09:22:46 PDT 2007


Author: sabre
Date: Wed Jul 11 11:22:45 2007
New Revision: 38568

URL: http://llvm.org/viewvc/llvm-project?rev=38568&view=rev
Log:
Finish implementation of #pragma once.  Implement #pragma GCC poison.

Modified:
    cfe/cfe/trunk/Lex/IdentifierTable.cpp
    cfe/cfe/trunk/Lex/Lexer.cpp
    cfe/cfe/trunk/Lex/Pragma.cpp
    cfe/cfe/trunk/Lex/Preprocessor.cpp
    cfe/cfe/trunk/README.txt
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/cfe/trunk/include/clang/Lex/IdentifierTable.h
    cfe/cfe/trunk/include/clang/Lex/Preprocessor.h

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

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

Modified: cfe/cfe/trunk/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Lexer.cpp?rev=38568&r1=38567&r2=38568&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/Lexer.cpp (original)
+++ cfe/cfe/trunk/Lex/Lexer.cpp Wed Jul 11 11:22:45 2007
@@ -19,8 +19,6 @@
 // WARNING: `%.*s' is not in NFC
 //
 // Other:
-// ERROR  : attempt to use poisoned \"%s\"
-//
 // TODO: Options to support:
 //    -fexec-charset,-fwide-exec-charset
 //

Modified: cfe/cfe/trunk/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/Pragma.cpp?rev=38568&r1=38567&r2=38568&view=diff

==============================================================================
--- cfe/cfe/trunk/Lex/Pragma.cpp (original)
+++ cfe/cfe/trunk/Lex/Pragma.cpp Wed Jul 11 11:22:45 2007
@@ -32,4 +32,3 @@
   // Otherwise, pass it down.
   Handler->HandlePragma(PP, Tok);
 }
-

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

==============================================================================
--- cfe/cfe/trunk/Lex/Preprocessor.cpp (original)
+++ cfe/cfe/trunk/Lex/Preprocessor.cpp Wed Jul 11 11:22:45 2007
@@ -416,8 +416,9 @@
     return;
   }
   IdentifierTokenInfo &ITI = *Identifier.getIdentifierInfo();
-  
-  // FIXME: Check for poisoning in ITI?
+
+  if (ITI.isPoisoned())
+    Diag(Identifier, diag::err_pp_used_poisoned_id);
   
   if (MacroInfo *MI = ITI.getMacroInfo()) {
     if (MI->isEnabled() && !DisableMacroExpansion) {
@@ -1260,21 +1261,67 @@
   PragmaHandlers->HandlePragma(*this, Tok);
   
   // If the pragma handler didn't read the rest of the line, consume it now.
-  if (CurLexer->ParsingPreprocessorDirective) {
-    do {
-      LexUnexpandedToken(Tok);
-    } while (Tok.getKind() != tok::eom);
-  }
+  if (CurLexer->ParsingPreprocessorDirective)
+    DiscardUntilEndOfDirective();
 }
 
 /// HandlePragmaOnce - Handle #pragma once.  OnceTok is the 'once'.
+///
 void Preprocessor::HandlePragmaOnce(LexerToken &OnceTok) {
   if (IncludeStack.empty()) {
     Diag(OnceTok, diag::pp_pragma_once_in_main_file);
     return;
   }
+  
+  // FIXME: implement the _Pragma thing.
+  assert(CurLexer && "Cannot have a pragma in a macro expansion yet!");
+  
+  // Mark the file as a once-only file now.
+  const FileEntry *File = 
+    SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID());
+  getFileInfo(File).isImport = true;
 }
 
+/// HandlePragmaPoison - Handle #pragma GCC poison.  PoisonTok is the 'poison'.
+///
+void Preprocessor::HandlePragmaPoison(LexerToken &PoisonTok) {
+  LexerToken Tok;
+  assert(!SkippingContents && "Why are we handling pragmas while skipping?");
+  while (1) {
+    // Read the next token to poison.  While doing this, pretend that we are
+    // skipping while reading the identifier to poison.
+    // This avoids errors on code like:
+    //   #pragma GCC poison X
+    //   #pragma GCC poison X
+    SkippingContents = true;
+    LexUnexpandedToken(Tok);
+    SkippingContents = false;
+    
+    // If we reached the end of line, we're done.
+    if (Tok.getKind() == tok::eom) return;
+    
+    // Can only poison identifiers.
+    if (Tok.getKind() != tok::identifier) {
+      Diag(Tok, diag::err_pp_invalid_poison);
+      return;
+    }
+    
+    // Look up the identifier info for the token.
+    std::string TokStr = getSpelling(Tok);
+    IdentifierTokenInfo *II = 
+      getIdentifierInfo(&TokStr[0], &TokStr[0]+TokStr.size());
+    
+    // Already poisoned.
+    if (II->isPoisoned()) continue;
+    
+    // If this is a macro identifier, emit a warning.
+    if (II->getMacroInfo())
+      Diag(Tok, diag::pp_poisoning_existing_macro);
+    
+    // Finally, poison it!
+    II->setIsPoisoned();
+  }
+}
 
 /// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
 /// If 'Namespace' is non-null, then it is a token required to exist on the
@@ -1308,6 +1355,7 @@
   InsertNS->AddPragma(Handler);
 }
 
+namespace {
 class PragmaOnceHandler : public PragmaHandler {
 public:
   PragmaOnceHandler(const IdentifierTokenInfo *OnceID) : PragmaHandler(OnceID){}
@@ -1317,10 +1365,19 @@
   }
 };
 
+class PragmaPoisonHandler : public PragmaHandler {
+public:
+  PragmaPoisonHandler(const IdentifierTokenInfo *ID) : PragmaHandler(ID) {}
+  virtual void HandlePragma(Preprocessor &PP, LexerToken &PoisonTok) {
+    PP.HandlePragmaPoison(PoisonTok);
+  }
+};
+}
+
 
 /// RegisterBuiltinPragmas - Install the standard preprocessor pragmas:
 /// #pragma GCC poison/system_header/dependency and #pragma once.
 void Preprocessor::RegisterBuiltinPragmas() {
   AddPragmaHandler(0, new PragmaOnceHandler(getIdentifierInfo("once")));
-  
+  AddPragmaHandler("GCC", new PragmaPoisonHandler(getIdentifierInfo("poison")));
 }

Modified: cfe/cfe/trunk/README.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/README.txt?rev=38568&r1=38567&r2=38568&view=diff

==============================================================================
--- cfe/cfe/trunk/README.txt (original)
+++ cfe/cfe/trunk/README.txt Wed Jul 11 11:22:45 2007
@@ -40,12 +40,11 @@
    See GCC options: -ftarget-charset and -ftarget-wide-charset.
  * Universal character support.  Experimental in GCC, enabled with
    -fextended-identifiers.
- * Poisoned identifiers.
  * -fpreprocessed mode.
 
 Preprocessor:
  * #line / #file directives
- * Detection of "atomic" headers (#ifndef/#define), #pragma once support.
+ * Detection of "atomic" headers (#ifndef/#define).
  * Function-style #define & macro expansion
  * -C & -P output modes.
 

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=38568&r1=38567&r2=38568&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:22:45 2007
@@ -88,6 +88,8 @@
      "ISO C99 requires whitespace after the macro name")
 DIAG(pp_pragma_once_in_main_file, WARNING,
      "#pragma once in main file")
+DIAG(pp_poisoning_existing_macro, WARNING,
+     "poisoning existing macro")
 
 DIAG(ext_pp_import_directive, EXTENSION,
      "#import is a language extension")
@@ -148,9 +150,12 @@
      "division by zero in preprocessor expression")
 DIAG(err_pp_remainder_by_zero, ERROR,
      "remainder by zero in preprocessor expression")
-
 DIAG(err_pp_expr_bad_token, ERROR,
      "token is not valid in preprocessor expressions")
+DIAG(err_pp_invalid_poison, ERROR,
+     "can only poison identifier tokens")
+DIAG(err_pp_used_poisoned_id, ERROR,
+     "attempt to use a poisoned identifier")
 
 // Should be a sorry?
 DIAG(err_pp_I_dash_not_supported, 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=38568&r1=38567&r2=38568&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/IdentifierTable.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/IdentifierTable.h Wed Jul 11 11:22:45 2007
@@ -30,8 +30,9 @@
 class IdentifierTokenInfo {
   unsigned NameLen;        // String that is the identifier.
   MacroInfo *Macro;        // Set if this identifier is #define'd.
-  tok::TokenKind TokenID:8;// Nonzero if this is a front-end token.
-  bool IsExtension : 1;    // True if this token is a language extension.
+  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.
   void *FETokenInfo;       // Managed by the language front-end.
   friend class IdentifierTable;
 public:
@@ -67,6 +68,12 @@
   bool isExtensionToken() const { return IsExtension; }
   void setIsExtensionToken(bool Val) { IsExtension = Val; }
   
+  /// setIsPoisoned - Mark this identifier as poisoned.  After poisoning, the
+  /// Preprocessor will emit an error every time this token is used.
+  void setIsPoisoned() { IsPoisoned = true; }
+  
+  /// isPoisoned - Return true if this token has been poisoned.
+  bool isPoisoned() const { return IsPoisoned; }
   
   /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
   /// associate arbitrary metadata with this token.

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=38568&r1=38567&r2=38568&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/Preprocessor.h Wed Jul 11 11:22:45 2007
@@ -427,6 +427,7 @@
   void HandlePragmaDirective(LexerToken &Result);
 public:
   void HandlePragmaOnce(LexerToken &OnceTok);
+  void HandlePragmaPoison(LexerToken &PoisonTok);
 };
 
 }  // end namespace clang





More information about the cfe-commits mailing list