summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticLexKinds.td4
-rw-r--r--clang/lib/Lex/PPDirectives.cpp46
-rw-r--r--clang/test/Preprocessor/line-directive.c10
3 files changed, 33 insertions, 27 deletions
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 564608865e6..e1e903fad06 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -228,8 +228,8 @@ def err_pp_line_requires_integer : Error<
def err_pp_line_invalid_filename : Error<
"invalid filename for #line directive">;
def warn_pp_line_decimal : Warning<
- "#line directive requires decimal line number">;
-def warn_pp_line_digit_sequence : Warning<
+ "#line directive interprets number as decimal, not octal">;
+def err_pp_line_digit_sequence : Error<
"#line directive requires a simple digit sequence">;
def err_pp_linemarker_requires_integer : Error<
"line marker directive requires a positive integer argument">;
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 3d312748f95..e0bd5a1ee07 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -624,24 +624,27 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val,
IntegerBuffer.resize(DigitTok.getLength());
const char *DigitTokBegin = &IntegerBuffer[0];
unsigned ActualLength = PP.getSpelling(DigitTok, DigitTokBegin);
- NumericLiteralParser Literal(DigitTokBegin, DigitTokBegin+ActualLength,
- DigitTok.getLocation(), PP);
- if (Literal.hadError)
- return true; // Error already emitted.
- if (Literal.isFloatingLiteral() || Literal.isImaginary) {
- PP.Diag(DigitTok, DiagID);
- return true;
- }
-
- // Parse the integer literal into Result.
- llvm::APInt APVal(32, 0);
- if (Literal.GetIntegerValue(APVal)) {
- // Overflow parsing integer literal.
- PP.Diag(DigitTok, DiagID);
- return true;
+ // Verify that we have a simple digit-sequence, and compute the value. This
+ // is always a simple digit string computed in decimal, so we do this manually
+ // here.
+ Val = 0;
+ for (unsigned i = 0; i != ActualLength; ++i) {
+ if (!isdigit(DigitTokBegin[i])) {
+ PP.Diag(PP.AdvanceToTokenCharacter(DigitTok.getLocation(), i),
+ diag::err_pp_line_digit_sequence);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+
+ unsigned NextVal = Val*10+(DigitTokBegin[i]-'0');
+ if (NextVal < Val) { // overflow.
+ PP.Diag(DigitTok, DiagID);
+ PP.DiscardUntilEndOfDirective();
+ return true;
+ }
+ Val = NextVal;
}
- Val = APVal.getZExtValue();
// Reject 0, this is needed both by #line numbers and flags.
if (Val == 0) {
@@ -650,12 +653,9 @@ static bool GetLineValue(Token &DigitTok, unsigned &Val,
return true;
}
- // Warn about hex and octal line numbers. Do this after the check for 0,
- // because it is octal.
- if (Literal.getRadix() != 10)
- PP.Diag(DigitTok, diag::warn_pp_line_decimal);
- else if (Literal.hasSuffix())
- PP.Diag(DigitTok, diag::warn_pp_line_digit_sequence);
+ if (DigitTokBegin[0] == '0')
+ PP.Diag(DigitTok.getLocation(), diag::warn_pp_line_decimal);
+
return false;
}
@@ -671,7 +671,7 @@ void Preprocessor::HandleLineDirective(Token &Tok) {
// Validate the number and convert it to an unsigned.
unsigned LineNo;
- if (GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer, *this))
+ if (GetLineValue(DigitTok, LineNo, diag::err_pp_line_requires_integer,*this))
return;
// Enforce C99 6.10.4p3: "The digit sequence shall not specify ... a
diff --git a/clang/test/Preprocessor/line-directive.c b/clang/test/Preprocessor/line-directive.c
index 98f92f130c6..04c69a6791a 100644
--- a/clang/test/Preprocessor/line-directive.c
+++ b/clang/test/Preprocessor/line-directive.c
@@ -4,6 +4,7 @@
#line 'a' // expected-error {{#line directive requires a positive integer argument}}
#line 0 // expected-error {{#line directive requires a positive integer argument}}
+#line 00 // 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 {{invalid filename for #line directive}}
@@ -69,7 +70,12 @@ typedef int w; // expected-error {{redefinition of typedef 'w' is invalid in C}
#line 2 "foo.c" NONEMPTY( ) // expected-warning{{extra tokens at end of #line directive}}
// PR3940
-#line 0xf // expected-warning {{#line directive requires decimal line number}}
-#line 42U // expected-warning {{#line directive requires a simple digit sequence}}
+#line 0xf // expected-error {{#line directive requires a simple digit sequence}}
+#line 42U // expected-error {{#line directive requires a simple digit sequence}}
+// Line markers are digit strings interpreted as decimal numbers, this is
+// 10, not 8.
+#line 010 // expected-warning {{#line directive interprets number as decimal, not octal}}
+extern int array[__LINE__ == 10 ? 1:-1];
+
OpenPOWER on IntegriCloud