aboutsummaryrefslogtreecommitdiff
path: root/gcc/cpplib.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cpplib.c')
-rw-r--r--gcc/cpplib.c100
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;
}