diff --git a/gcc/testsuite/gcc.dg/cpp/line10.c b/gcc/testsuite/gcc.dg/cpp/line10.c new file mode 100644 index 00000000000..9f5f0799847 --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/line10.c @@ -0,0 +1,5 @@ +/* Test #line overflow checks: bug 97602. */ +/* { dg-do preprocess } */ +/* { dg-options "-pedantic" } */ + +#line 4294967296 /* { dg-warning "line number out of range" } */ diff --git a/gcc/testsuite/gcc.dg/cpp/line9.c b/gcc/testsuite/gcc.dg/cpp/line9.c new file mode 100644 index 00000000000..8060aff204d --- /dev/null +++ b/gcc/testsuite/gcc.dg/cpp/line9.c @@ -0,0 +1,5 @@ +/* Test #line overflow checks: bug 97602. */ +/* { dg-do preprocess } */ +/* { dg-options "-pedantic" } */ + +#line 5000000000 /* { dg-warning "line number out of range" } */ diff --git a/libcpp/directives.c b/libcpp/directives.c index fa66b5c5f71..75115600e3a 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -915,12 +915,11 @@ read_flag (cpp_reader *pfile, unsigned int last) /* Subroutine of do_line and do_linemarker. Convert a number in STR, of length LEN, to binary; store it in NUMP, and return false if the number was well-formed, true if not. WRAPPED is set to true if the - number did not fit into 'unsigned long'. */ + number did not fit into 'linenum_type'. */ static bool strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped) { linenum_type reg = 0; - linenum_type reg_prev = 0; uchar c; *wrapped = false; @@ -929,11 +928,12 @@ strtolinenum (const uchar *str, size_t len, linenum_type *nump, bool *wrapped) c = *str++; if (!ISDIGIT (c)) return true; - reg *= 10; - reg += c - '0'; - if (reg < reg_prev) + if (reg > ((linenum_type) -1) / 10) *wrapped = true; - reg_prev = reg; + reg *= 10; + if (reg > ((linenum_type) -1) - (c - '0')) + *wrapped = true; + reg += c - '0'; } *nump = reg; return false;