[cfe-commits] r62999 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def include/clang/Lex/Preprocessor.h lib/Lex/PPDirectives.cpp test/Preprocessor/line-directive.c

Chris Lattner sabre at nondot.org
Sun Jan 25 21:29:09 PST 2009


Author: lattner
Date: Sun Jan 25 23:29:08 2009
New Revision: 62999

URL: http://llvm.org/viewvc/llvm-project?rev=62999&view=rev
Log:
parse and enforce required constraints on #line directives.  Right now
we just discard them.

Added:
    cfe/trunk/test/Preprocessor/line-directive.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/lib/Lex/PPDirectives.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sun Jan 25 23:29:08 2009
@@ -200,6 +200,13 @@
      "duplicate macro parameter name %0")
 DIAG(err_pp_stringize_not_parameter, ERROR,
      "'#' is not followed by a macro parameter")
+DIAG(err_pp_line_requires_integer, ERROR,
+     "#line directive requires a positive integer argument")
+DIAG(err_pp_line_invalid_filename, ERROR,
+     "invalid filename for #line directive")
+DIAG(ext_pp_line_too_big, EXTENSION,
+     "C requires #line number to be less than %0, allowed as extension")
+     
 DIAG(err_pp_malformed_ident, ERROR,
      "invalid #ident directive")
 DIAG(err_pp_unterminated_conditional, ERROR,

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

==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Sun Jan 25 23:29:08 2009
@@ -691,6 +691,7 @@
   /// should side-effect the current preprocessor object so that the next call
   /// to Lex() will return the appropriate token next.
   
+  void HandleLineDirective(Token &Tok);
   void HandleUserDiagnosticDirective(Token &Tok, bool isWarning);
   void HandleIdentSCCSDirective(Token &Tok);
   

Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=62999&r1=62998&r2=62999&view=diff

==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Sun Jan 25 23:29:08 2009
@@ -12,10 +12,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/LiteralSupport.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/APInt.h"
 using namespace clang;
 
 //===----------------------------------------------------------------------===//
@@ -478,8 +480,7 @@
 
   case tok::numeric_constant:
     // FIXME: implement # 7 line numbers!
-    DiscardUntilEndOfDirective();
-    return;
+    return DiscardUntilEndOfDirective();
   default:
     IdentifierInfo *II = Result.getIdentifierInfo();
     if (II == 0) break;  // Not an identifier.
@@ -513,9 +514,7 @@
 
     // C99 6.10.4 - Line Control.
     case tok::pp_line:
-      // FIXME: implement #line
-      DiscardUntilEndOfDirective();
-      return;
+      return HandleLineDirective(Result);
       
     // C99 6.10.5 - Error Directive.
     case tok::pp_error:
@@ -557,22 +556,95 @@
   // Okay, we're done parsing the directive.
 }
 
+/// HandleLineDirective - Handle #line directive: C99 6.10.4.  The two 
+/// acceptable forms are:
+///   # line digit-sequence
+///   # line digit-sequence "s-char-sequence"
+void Preprocessor::HandleLineDirective(Token &Tok) {
+  // Read the line # and string argument.  Per C99 6.10.4p5, these tokens are
+  // expanded.
+  Token DigitTok;
+  Lex(DigitTok);
+
+  // Verify that we get a number.
+  if (DigitTok.isNot(tok::numeric_constant)) {
+    Diag(DigitTok, diag::err_pp_line_requires_integer);
+    if (DigitTok.isNot(tok::eom))
+      DiscardUntilEndOfDirective();
+    return;
+  }
+  
+  // Validate the number and convert it to an unsigned.
+  llvm::SmallString<64> IntegerBuffer;
+  IntegerBuffer.resize(DigitTok.getLength());
+  const char *DigitTokBegin = &IntegerBuffer[0];
+  unsigned ActualLength = getSpelling(DigitTok, DigitTokBegin);
+  NumericLiteralParser Literal(DigitTokBegin, DigitTokBegin+ActualLength, 
+                               DigitTok.getLocation(), *this);
+  if (Literal.hadError)
+    return DiscardUntilEndOfDirective();  // a diagnostic was already reported.
+  
+  if (Literal.isFloatingLiteral() || Literal.isImaginary) {
+    Diag(DigitTok, diag::err_pp_line_requires_integer);
+    return;
+  }
+  
+  // Parse the integer literal into Result.
+  llvm::APInt Val(32, 0);
+  if (Literal.GetIntegerValue(Val)) {
+    // Overflow parsing integer literal.
+    Diag(DigitTok, diag::err_pp_line_requires_integer);
+    return DiscardUntilEndOfDirective();
+  }
+
+  // Enforce C99 6.10.4p3: The digit sequence shall not specify zero, nor a
+  // number greater than 2147483647. 
+  unsigned LineNo = Val.getZExtValue();
+  if (LineNo == 0) {
+    Diag(DigitTok, diag::err_pp_line_requires_integer);
+    return DiscardUntilEndOfDirective();
+  }
+  
+  // C90 requires that the line # be less than 32767, and C99 ups the limit.
+  unsigned LineLimit = Features.C99 ? 2147483648U : 32768U;
+  if (LineNo >= LineLimit)
+    Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit;
+  
+  Token StrTok;
+  Lex(StrTok);
+
+  // If the StrTok is "eom", then it wasn't present.  Otherwise, it must be a
+  // string followed by eom.
+  if (StrTok.is(tok::eom)) 
+    ; // ok
+  else if (StrTok.isNot(tok::string_literal)) {
+    Diag(StrTok, diag::err_pp_line_invalid_filename);
+    DiscardUntilEndOfDirective();
+    return;
+  } else {
+    // Verify that there is nothing after the string, other than EOM.
+    CheckEndOfDirective("#line");
+  }
+  
+  // FIXME: do something with the #line info.
+}
+
+
 void Preprocessor::HandleUserDiagnosticDirective(Token &Tok, 
                                                  bool isWarning) {
+  if (!CurLexer)
+    return CurPTHLexer->DiscardToEndOfLine();
+
   // Read the rest of the line raw.  We do this because we don't want macros
   // to be expanded and we don't require that the tokens be valid preprocessing
   // tokens.  For example, this is allowed: "#warning `   'foo".  GCC does
   // collapse multiple consequtive white space between tokens, but this isn't
   // specified by the standard.
-  
-  if (CurLexer) {
-    std::string Message = CurLexer->ReadToEndOfLine();
-    unsigned DiagID = isWarning ? diag::pp_hash_warning : diag::err_pp_hash_error;
-    Diag(Tok, DiagID) << Message;
-  }
-  else {
-    CurPTHLexer->DiscardToEndOfLine();
-  }    
+  std::string Message = CurLexer->ReadToEndOfLine();
+  if (isWarning)
+    Diag(Tok, diag::pp_hash_warning) << Message;
+  else
+    Diag(Tok, diag::err_pp_hash_error) << Message;
 }
 
 /// HandleIdentSCCSDirective - Handle a #ident/#sccs directive.

Added: cfe/trunk/test/Preprocessor/line-directive.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/line-directive.c?rev=62999&view=auto

==============================================================================
--- cfe/trunk/test/Preprocessor/line-directive.c (added)
+++ cfe/trunk/test/Preprocessor/line-directive.c Sun Jan 25 23:29:08 2009
@@ -0,0 +1,10 @@
+// RUN: clang -fsyntax-only -verify -pedantic %s
+
+#line 'a'            // expected-error {{#line directive requires a positive integer argument}}
+#line 0              // expected-error {{#line directive requires a positive integer argument}}
+#line 2147483648     // expected-warning {{C requires #line number to be less than 2147483648, allowed as extension}}
+#line 42             // ok
+#line 42 'a'         // expected-error {{nvalid filename for #line directive}}
+#line 42 "foo/bar/baz.h"  // ok
+
+





More information about the cfe-commits mailing list