[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