diff options
Diffstat (limited to 'gcc/cpplib.c')
-rw-r--r-- | gcc/cpplib.c | 100 |
1 files changed, 64 insertions, 36 deletions
diff --git a/gcc/cpplib.c b/gcc/cpplib.c index acc6f11..73e12b7 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -70,11 +70,16 @@ struct pragma_entry conditional; IF_COND an opening conditional. INCL means to treat "..." and <...> as q-char and h-char sequences respectively. IN_I means this directive should be handled even if -fpreprocessed is in - effect (these are the directives with callback hooks). */ + effect (these are the directives with callback hooks). + + EXPAND is set on directives that are always macro-expanded. If + INCL is set, macro expansion is special-cased and EXPAND should not + be set. */ #define COND (1 << 0) #define IF_COND (1 << 1) #define INCL (1 << 2) #define IN_I (1 << 3) +#define EXPAND (1 << 4) /* Defines one #-directive, including how to handle it. */ typedef void (*directive_handler) PARAMS ((cpp_reader *)); @@ -93,6 +98,7 @@ struct directive static void skip_rest_of_line PARAMS ((cpp_reader *)); static void check_eol PARAMS ((cpp_reader *)); static void start_directive PARAMS ((cpp_reader *)); +static void prepare_directive_trad PARAMS ((cpp_reader *)); static void end_directive PARAMS ((cpp_reader *, int)); static void directive_diagnostics PARAMS ((cpp_reader *, const directive *, int)); @@ -144,12 +150,12 @@ D(define, T_DEFINE = 0, KANDR, IN_I) /* 270554 */ \ D(include, T_INCLUDE, KANDR, INCL) /* 52262 */ \ D(endif, T_ENDIF, KANDR, COND) /* 45855 */ \ D(ifdef, T_IFDEF, KANDR, COND | IF_COND) /* 22000 */ \ -D(if, T_IF, KANDR, COND | IF_COND) /* 18162 */ \ +D(if, T_IF, KANDR, COND | IF_COND | EXPAND) /* 18162 */ \ D(else, T_ELSE, KANDR, COND) /* 9863 */ \ D(ifndef, T_IFNDEF, KANDR, COND | IF_COND) /* 9675 */ \ D(undef, T_UNDEF, KANDR, IN_I) /* 4837 */ \ -D(line, T_LINE, KANDR, 0) /* 2465 */ \ -D(elif, T_ELIF, STDC89, COND) /* 610 */ \ +D(line, T_LINE, KANDR, EXPAND) /* 2465 */ \ +D(elif, T_ELIF, STDC89, COND | EXPAND) /* 610 */ \ D(error, T_ERROR, STDC89, 0) /* 475 */ \ D(pragma, T_PRAGMA, STDC89, IN_I) /* 195 */ \ D(warning, T_WARNING, EXTENSION, 0) /* 22 */ \ @@ -202,8 +208,7 @@ static const directive linemarker_dir = do_linemarker, U"#", 1, KANDR, IN_I }; -#define SEEN_EOL() (CPP_OPTION (pfile, traditional) \ - || pfile->cur_token[-1].type == CPP_EOF) +#define SEEN_EOL() (pfile->cur_token[-1].type == CPP_EOF) /* Skip any remaining tokens in a directive. */ static void @@ -249,6 +254,14 @@ end_directive (pfile, skip_line) cpp_reader *pfile; int skip_line; { + if (CPP_OPTION (pfile, traditional)) + { + if (pfile->directive == &dtable[T_DEFINE]) + skip_line = false; + else + _cpp_remove_overlay (pfile); + } + /* We don't skip for an assembler #. */ if (skip_line) { @@ -267,6 +280,27 @@ end_directive (pfile, skip_line) pfile->directive = 0; } +/* Prepare to handle the directive in pfile->directive. */ +static void +prepare_directive_trad (pfile) + cpp_reader *pfile; +{ + if (pfile->directive == &dtable[T_DEFINE]) + CUR (pfile->context) = pfile->buffer->cur; + else + { + bool no_expand = ! (pfile->directive->flags & EXPAND); + + if (no_expand) + pfile->state.prevent_expansion++; + _cpp_read_logical_line_trad (pfile); + if (no_expand) + pfile->state.prevent_expansion--; + _cpp_overlay_buffer (pfile, pfile->out.base, + pfile->out.cur - pfile->out.base); + } +} + /* Output diagnostics for a directive DIR. INDENTED is non-zero if the '#' was indented. */ static void @@ -405,6 +439,8 @@ _cpp_handle_directive (pfile, indented) ! CPP_OPTION (pfile, discard_comments_in_macro_exp); pfile->directive = dir; + if (CPP_OPTION (pfile, traditional)) + prepare_directive_trad (pfile); (*pfile->directive->handler) (pfile); } else if (skip == 0) @@ -436,6 +472,8 @@ run_directive (pfile, dir_no, buf, count) /* We don't want a leading # to be interpreted as a directive. */ pfile->buffer->saved_flags = 0; pfile->directive = &dtable[dir_no]; + if (CPP_OPTION (pfile, traditional)) + prepare_directive_trad (pfile); (void) (*pfile->directive->handler) (pfile); end_directive (pfile, 1); _cpp_pop_buffer (pfile); @@ -447,7 +485,7 @@ static cpp_hashnode * lex_macro_node (pfile) cpp_reader *pfile; { - cpp_hashnode *node; + const cpp_token *token = _cpp_lex_token (pfile); /* The token immediately after #define must be an identifier. That identifier may not be "defined", per C99 6.10.8p4. @@ -459,41 +497,31 @@ lex_macro_node (pfile) Note that if we're copying comments into macro expansions, we could encounter comment tokens here, so eat them all up first. */ - if (CPP_OPTION (pfile, traditional)) - node = _cpp_lex_identifier_trad (pfile); - else + if (! CPP_OPTION (pfile, discard_comments_in_macro_exp)) { - const cpp_token *token = _cpp_lex_token (pfile); + while (token->type == CPP_COMMENT) + token = _cpp_lex_token (pfile); + } - if (! CPP_OPTION (pfile, discard_comments_in_macro_exp)) - { - while (token->type == CPP_COMMENT) - token = _cpp_lex_token (pfile); - } + if (token->type == CPP_NAME) + { + cpp_hashnode *node = token->val.node; - if (token->type == CPP_EOF) - { - cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive", - pfile->directive->name); - return NULL; - } - - if (token->type == CPP_NAME || (token->flags & NAMED_OP)) - node = token->val.node; - else - node = NULL; + if (node == pfile->spec_nodes.n_defined) + cpp_error (pfile, DL_ERROR, + "\"defined\" cannot be used as a macro name"); + else if (! (node->flags & NODE_POISONED)) + return node; } - - if (!node) - cpp_error (pfile, DL_ERROR, "macro names must be identifiers"); - else if (node->flags & NODE_OPERATOR) + else if (token->flags & NAMED_OP) cpp_error (pfile, DL_ERROR, "\"%s\" cannot be used as a macro name as it is an operator in C++", - NODE_NAME (node)); - else if (node == pfile->spec_nodes.n_defined) - cpp_error (pfile, DL_ERROR, "\"defined\" cannot be used as a macro name"); - else if (! (node->flags & NODE_POISONED)) - return node; + NODE_NAME (token->val.node)); + else if (token->type == CPP_EOF) + cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive", + pfile->directive->name); + else + cpp_error (pfile, DL_ERROR, "macro names must be identifiers"); return NULL; } |