mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-07 04:36:46 +08:00
cpptrad.c (scan_out_logical_line): Check recursing only when we know we have a macro invocation in the...
* cpptrad.c (scan_out_logical_line): Check recursing only when we know we have a macro invocation in the function-like case. Only call _cpp_handle_directive if we know we have a good directive, or we want to reject a bad directive. testsuite: * gcc.dg/cpp/trad/argcout.c, gcc.dg/cpp/trad/assembler.S, gcc.dg/cpp/trad/argcout.c, gcc.dg/cpp/trad/funlike-4.c, gcc.dg/cpp/trad/null-drctv.c, gcc.dg/cpp/trad/recurse-1.c, gcc.dg/cpp/trad/recurse-2.c, gcc.dg/cpp/trad/recurse-3.c: New tests. * gcc.dg/cpp/trad/directive.c: Update. From-SVN: r54942
This commit is contained in:
parent
66443ad2fd
commit
2c088b53f9
@ -1,3 +1,10 @@
|
||||
2002-06-24 Neil Booth <neil@daikokuya.co.uk>
|
||||
|
||||
* cpptrad.c (scan_out_logical_line): Check recursing only when
|
||||
we know we have a macro invocation in the function-like case.
|
||||
Only call _cpp_handle_directive if we know we have a good
|
||||
directive, or we want to reject a bad directive.
|
||||
|
||||
2002-06-24 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* doloop.c (doloop_valid_p): Correct comment.
|
||||
|
@ -579,8 +579,7 @@ scan_out_logical_line (pfile, macro)
|
||||
if (node->type == NT_MACRO
|
||||
/* Should we expand for ls_answer? */
|
||||
&& (lex_state == ls_none || lex_state == ls_fun_open)
|
||||
&& !pfile->state.prevent_expansion
|
||||
&& !recursive_macro (pfile, node))
|
||||
&& !pfile->state.prevent_expansion)
|
||||
{
|
||||
/* Macros invalidate MI optimization. */
|
||||
pfile->mi_valid = false;
|
||||
@ -592,7 +591,7 @@ scan_out_logical_line (pfile, macro)
|
||||
fmacro.line = pfile->line;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
else if (!recursive_macro (pfile, node))
|
||||
{
|
||||
/* Remove the object-like macro's name from the
|
||||
output, and push its replacement text. */
|
||||
@ -630,10 +629,15 @@ scan_out_logical_line (pfile, macro)
|
||||
paren_depth++;
|
||||
if (lex_state == ls_fun_open)
|
||||
{
|
||||
lex_state = ls_fun_close;
|
||||
paren_depth = 1;
|
||||
out = pfile->out.base + fmacro.offset;
|
||||
fmacro.args[0] = fmacro.offset;
|
||||
if (recursive_macro (pfile, fmacro.node))
|
||||
lex_state = ls_none;
|
||||
else
|
||||
{
|
||||
lex_state = ls_fun_close;
|
||||
paren_depth = 1;
|
||||
out = pfile->out.base + fmacro.offset;
|
||||
fmacro.args[0] = fmacro.offset;
|
||||
}
|
||||
}
|
||||
else if (lex_state == ls_predicate)
|
||||
lex_state = ls_answer;
|
||||
@ -681,15 +685,43 @@ scan_out_logical_line (pfile, macro)
|
||||
break;
|
||||
|
||||
case '#':
|
||||
/* At start of a line it's a directive. */
|
||||
if (out - 1 == pfile->out.base && !pfile->state.in_directive)
|
||||
{
|
||||
/* This is a kludge. We want to have the ISO
|
||||
preprocessor lex the next token. */
|
||||
pfile->buffer->cur = cur;
|
||||
if (_cpp_handle_directive (pfile, false /* indented */))
|
||||
goto start_logical_line;
|
||||
/* A directive. With the way _cpp_handle_directive
|
||||
currently works, we only want to call it if either we
|
||||
know the directive is OK, or we want it to fail and
|
||||
be removed from the output. If we want it to be
|
||||
passed through (the assembler case) then we must not
|
||||
call _cpp_handle_directive. */
|
||||
pfile->out.cur = out;
|
||||
cur = skip_whitespace (pfile, cur, true /* skip_comments */);
|
||||
out = pfile->out.cur;
|
||||
|
||||
if (is_vspace (*cur))
|
||||
/* Null directive ignored. */
|
||||
out = pfile->out.base;
|
||||
else
|
||||
{
|
||||
bool do_it = false;
|
||||
|
||||
if (is_numstart (*cur))
|
||||
do_it = true;
|
||||
else if (is_idstart (*cur))
|
||||
/* Check whether we know this directive, but don't
|
||||
advance. */
|
||||
do_it = lex_identifier (pfile, cur)->directive_index != 0;
|
||||
|
||||
if (do_it || CPP_OPTION (pfile, lang) != CLK_ASM)
|
||||
{
|
||||
/* This is a kludge. We want to have the ISO
|
||||
preprocessor lex the next token. */
|
||||
pfile->buffer->cur = cur;
|
||||
_cpp_handle_directive (pfile, false /* indented */);
|
||||
goto start_logical_line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pfile->state.in_expression)
|
||||
{
|
||||
lex_state = ls_hash;
|
||||
|
@ -1,3 +1,12 @@
|
||||
2002-06-24 Neil Booth <neil@daikokuya.co.uk>
|
||||
|
||||
* gcc.dg/cpp/trad/argcout.c, gcc.dg/cpp/trad/assembler.S,
|
||||
gcc.dg/cpp/trad/argcout.c, gcc.dg/cpp/trad/funlike-4.c,
|
||||
gcc.dg/cpp/trad/null-drctv.c, gcc.dg/cpp/trad/recurse-1.c,
|
||||
gcc.dg/cpp/trad/recurse-2.c, gcc.dg/cpp/trad/recurse-3.c:
|
||||
New tests.
|
||||
* gcc.dg/cpp/trad/directive.c: Update.
|
||||
|
||||
2002-06-23 Andreas Jaeger <aj@suse.de>
|
||||
|
||||
* gcc.c-torture/execute/complex-6.c: New.
|
||||
|
21
gcc/testsuite/gcc.dg/cpp/trad/argcount.c
Normal file
21
gcc/testsuite/gcc.dg/cpp/trad/argcount.c
Normal file
@ -0,0 +1,21 @@
|
||||
/* Test that we correctly complain about an invalid number of macro
|
||||
arguments. */
|
||||
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
#define f(x) x
|
||||
#define g(x, y) x y
|
||||
#define h()
|
||||
|
||||
f(); /* { dg-bogus "requires 1" "no arg is 1 empty arg" } */
|
||||
f( ); /* { dg-bogus "macro" "1 arg to 1 param macro" } */
|
||||
f(1,); /* { dg-error "passed 2" "2 args to 1 param macro" } */
|
||||
f(1,2); /* { dg-error "passed 2" "2 args to 1 param macro" } */
|
||||
h(); /* { dg-bogus "macro" "no arg to 1 param macro" } */
|
||||
h( ); /* { dg-error "passed 1" "1 arg to 0 param macro" } */
|
||||
h(1,2); /* { dg-error "passed 2" "2 args to 0 param macro" } */
|
||||
g(); /* { dg-error "requires 2" "0 args to 2 param macro" } */
|
||||
g( ); /* { dg-error "requires 2" "1 args to 2 param macro" } */
|
||||
g( ,2); /* { dg-bogus "requires 2" "2 args to 2 param macro" } */
|
||||
g(,); /* { dg-bogus "requires 2" "2 args to 2 param macro" } */
|
||||
g(1,2,3); /* { dg-error "passed 3" "3 args to 2 param macro" } */
|
25
gcc/testsuite/gcc.dg/cpp/trad/assembler.S
Normal file
25
gcc/testsuite/gcc.dg/cpp/trad/assembler.S
Normal file
@ -0,0 +1,25 @@
|
||||
/* Regression test - in assembly language, # may have some significance
|
||||
other than 'stringize macro argument' and therefore must be preserved
|
||||
in the output, and should not be warned about. */
|
||||
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
#define foo() mov r0, #5 /* { dg-bogus "not followed" "spurious warning" } */
|
||||
|
||||
entry:
|
||||
foo()
|
||||
|
||||
/* Check we don't EOF on an unknown directive. */
|
||||
#unknown directive
|
||||
#error a later diagnostic /* { dg-error "diagnostic" } */
|
||||
|
||||
/*
|
||||
{ dg-final { if ![file exists 20000510-1.i] { return } } }
|
||||
{ dg-final { set tmp [grep 20000510-1.i # line] } }
|
||||
{ dg-final { if {[string length $tmp] > 0} \{ } }
|
||||
{ dg-final { pass "20000510-1.S: # preservation" } }
|
||||
{ dg-final { \} else \{ } }
|
||||
{ dg-final { fail "20000510-1.S: # preservation" } }
|
||||
{ dg-final { \} } }
|
||||
*/
|
||||
|
@ -8,3 +8,5 @@
|
||||
|
||||
/* Directives with their #s indented are not recognized. */
|
||||
#if 0 /* { dg-bogus "unterminated" } */
|
||||
|
||||
#wrong /* { dg-error "invalid" } */
|
||||
|
26
gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c
Normal file
26
gcc/testsuite/gcc.dg/cpp/trad/funlike-4.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* Test that undefined names evaluate to zero, that macros after a
|
||||
funlike macro are expanded, and that if it is a '(' the funlike
|
||||
macro is not treated as such. */
|
||||
|
||||
/* { dg-do run } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
#define f(x) x
|
||||
|
||||
int main ()
|
||||
{
|
||||
#if f(1) == f /**/ (/**/1/**/)
|
||||
int x;
|
||||
#endif
|
||||
|
||||
x = 0;
|
||||
if (f
|
||||
/**/ (
|
||||
/**/ 0/**/
|
||||
/**/)
|
||||
)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
6
gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c
Normal file
6
gcc/testsuite/gcc.dg/cpp/trad/null-drctv.c
Normal file
@ -0,0 +1,6 @@
|
||||
/* Test that the null directive doesn't swallow the following line. */
|
||||
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
#
|
||||
#error OK /* { dg-error "OK" } */
|
10
gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c
Normal file
10
gcc/testsuite/gcc.dg/cpp/trad/recurse-1.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* Test for warning of and recovery from recursion in object-like
|
||||
macros. */
|
||||
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
#define foo foo
|
||||
foo /* { dg-error "detected recursion" } */
|
||||
|
||||
#define bar a bar b
|
||||
bar /* { dg-error "detected recursion" } */
|
16
gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c
Normal file
16
gcc/testsuite/gcc.dg/cpp/trad/recurse-2.c
Normal file
@ -0,0 +1,16 @@
|
||||
/* Test for warning of and recovery from recursion in function-like
|
||||
macros. */
|
||||
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
#define foo() foo()
|
||||
foo(); /* { dg-error "detected recursion" } */
|
||||
|
||||
#define bar() bar baz() bar
|
||||
bar(); /* { dg-bogus "detected recursion" } */
|
||||
|
||||
#define baz() foo()
|
||||
baz(); /* { dg-error "detected recursion" } */
|
||||
|
||||
#define a(x) x(a)
|
||||
a(a); /* { dg-error "detected recursion" } */
|
16
gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c
Normal file
16
gcc/testsuite/gcc.dg/cpp/trad/recurse-3.c
Normal file
@ -0,0 +1,16 @@
|
||||
/* Tests that macros that look recursive but are not are accepted. */
|
||||
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
#define g(x) x
|
||||
g(g(g(g(g(g(g)))))); /* { dg-bogus "detected recursion" } */
|
||||
|
||||
/* This macro gets longer with each loop, to thwart tests for
|
||||
recursion based on length. */
|
||||
#define f(a,b,c,d,e,f,g,h,i) a(b,c,d,e,f,g,h,i,2 3 4 5)
|
||||
f(f,f,f,f,f,f,f,f,f) /* { dg-bogus "detected recursion" } */
|
||||
|
||||
/* The above cases should be enough, but this is taken from cccp
|
||||
sources so let's try it too. */
|
||||
#define foo(x,y) bar (x (y,0), y)
|
||||
foo (foo, baz); /* { dg-bogus "detected recursion" } */
|
Loading…
Reference in New Issue
Block a user