summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cppmacro.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cppmacro.c')
-rw-r--r--contrib/gcc/cppmacro.c761
1 files changed, 452 insertions, 309 deletions
diff --git a/contrib/gcc/cppmacro.c b/contrib/gcc/cppmacro.c
index 70e52fd..b97fe81 100644
--- a/contrib/gcc/cppmacro.c
+++ b/contrib/gcc/cppmacro.c
@@ -28,18 +28,6 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "cpplib.h"
#include "cpphash.h"
-struct cpp_macro
-{
- cpp_hashnode **params; /* Parameters, if any. */
- cpp_token *expansion; /* First token of replacement list. */
- unsigned int line; /* Starting line number. */
- unsigned int count; /* Number of tokens in expansion. */
- unsigned short paramc; /* Number of parameters. */
- unsigned int fun_like : 1; /* If a function-like macro. */
- unsigned int variadic : 1; /* If a variadic macro. */
- unsigned int syshdr : 1; /* If macro defined in system header. */
-};
-
typedef struct macro_arg macro_arg;
struct macro_arg
{
@@ -64,28 +52,51 @@ static cpp_context *next_context PARAMS ((cpp_reader *));
static const cpp_token *padding_token
PARAMS ((cpp_reader *, const cpp_token *));
static void expand_arg PARAMS ((cpp_reader *, macro_arg *));
-static const cpp_token *new_string_token PARAMS ((cpp_reader *, U_CHAR *,
+static const cpp_token *new_string_token PARAMS ((cpp_reader *, uchar *,
unsigned int));
-static const cpp_token *new_number_token PARAMS ((cpp_reader *, unsigned int));
static const cpp_token *stringify_arg PARAMS ((cpp_reader *, macro_arg *));
static void paste_all_tokens PARAMS ((cpp_reader *, const cpp_token *));
static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **,
const cpp_token *));
-static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, macro_arg *));
+static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, cpp_macro *,
+ macro_arg *));
static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *));
+static bool create_iso_definition PARAMS ((cpp_reader *, cpp_macro *));
/* #define directive parsing and handling. */
static cpp_token *alloc_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
-static int warn_of_redefinition PARAMS ((const cpp_hashnode *,
- const cpp_macro *));
-static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *));
-static int parse_params PARAMS ((cpp_reader *, cpp_macro *));
+static bool warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *,
+ const cpp_macro *));
+static bool parse_params PARAMS ((cpp_reader *, cpp_macro *));
static void check_trad_stringification PARAMS ((cpp_reader *,
const cpp_macro *,
const cpp_string *));
+/* Emits a warning if NODE is a macro defined in the main file that
+ has not been used. */
+int
+_cpp_warn_if_unused_macro (pfile, node, v)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+ void *v ATTRIBUTE_UNUSED;
+{
+ if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
+ {
+ cpp_macro *macro = node->value.macro;
+
+ if (!macro->used
+ /* Skip front-end built-ins and command line macros. */
+ && macro->line >= pfile->first_unused_line
+ && MAIN_FILE_P (lookup_line (&pfile->line_maps, macro->line)))
+ cpp_error_with_line (pfile, DL_WARNING, macro->line, 0,
+ "macro \"%s\" is not used", NODE_NAME (node));
+ }
+
+ return 1;
+}
+
/* Allocates and returns a CPP_STRING token, containing TEXT of length
LEN, after null-terminating it. TEXT must be in permanent storage. */
static const cpp_token *
@@ -104,24 +115,6 @@ new_string_token (pfile, text, len)
return token;
}
-/* Allocates and returns a CPP_NUMBER token evaluating to NUMBER. */
-static const cpp_token *
-new_number_token (pfile, number)
- cpp_reader *pfile;
- unsigned int number;
-{
- cpp_token *token = _cpp_temp_token (pfile);
- /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */
- unsigned char *buf = _cpp_unaligned_alloc (pfile, 21);
-
- sprintf ((char *) buf, "%u", number);
- token->type = CPP_NUMBER;
- token->val.str.text = buf;
- token->val.str.len = ustrlen (buf);
- token->flags = 0;
- return token;
-}
-
static const char * const monthnames[] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -132,25 +125,27 @@ static const char * const monthnames[] =
on the context stack. Also handles _Pragma, for which no new token
is created. Returns 1 if it generates a new token context, 0 to
return the token to the caller. */
-static int
-builtin_macro (pfile, node)
+const uchar *
+_cpp_builtin_macro_text (pfile, node)
cpp_reader *pfile;
cpp_hashnode *node;
{
- const cpp_token *result;
+ const uchar *result = NULL;
+ unsigned int number = 1;
switch (node->value.builtin)
{
default:
- cpp_ice (pfile, "invalid built-in macro \"%s\"", NODE_NAME (node));
- return 0;
+ cpp_error (pfile, DL_ICE, "invalid built-in macro \"%s\"",
+ NODE_NAME (node));
+ break;
case BT_FILE:
case BT_BASE_FILE:
{
unsigned int len;
const char *name;
- U_CHAR *buf;
+ uchar *buf;
const struct line_map *map = pfile->map;
if (node->value.builtin == BT_BASE_FILE)
@@ -159,10 +154,12 @@ builtin_macro (pfile, node)
name = map->to_file;
len = strlen (name);
- buf = _cpp_unaligned_alloc (pfile, len * 4 + 1);
- len = cpp_quote_string (buf, (const unsigned char *) name, len) - buf;
-
- result = new_string_token (pfile, buf, len);
+ buf = _cpp_unaligned_alloc (pfile, len * 4 + 3);
+ result = buf;
+ *buf = '"';
+ buf = cpp_quote_string (buf + 1, (const unsigned char *) name, len);
+ *buf++ = '"';
+ *buf = '\0';
}
break;
@@ -170,61 +167,107 @@ builtin_macro (pfile, node)
/* The line map depth counts the primary source as level 1, but
historically __INCLUDE_DEPTH__ has called the primary source
level 0. */
- result = new_number_token (pfile, pfile->line_maps.depth - 1);
+ number = pfile->line_maps.depth - 1;
break;
case BT_SPECLINE:
/* If __LINE__ is embedded in a macro, it must expand to the
line of the macro's invocation, not its definition.
Otherwise things like assert() will not work properly. */
- result = new_number_token (pfile,
- SOURCE_LINE (pfile->map,
- pfile->cur_token[-1].line));
+ if (CPP_OPTION (pfile, traditional))
+ number = pfile->line;
+ else
+ number = pfile->cur_token[-1].line;
+ number = SOURCE_LINE (pfile->map, number);
break;
+ /* __STDC__ has the value 1 under normal circumstances.
+ However, if (a) we are in a system header, (b) the option
+ stdc_0_in_system_headers is true (set by target config), and
+ (c) we are not in strictly conforming mode, then it has the
+ value 0. */
case BT_STDC:
{
- int stdc = (!CPP_IN_SYSTEM_HEADER (pfile)
- || pfile->spec_nodes.n__STRICT_ANSI__->type != NT_VOID);
- result = new_number_token (pfile, stdc);
+ if (CPP_IN_SYSTEM_HEADER (pfile)
+ && CPP_OPTION (pfile, stdc_0_in_system_headers)
+ && !CPP_OPTION (pfile,std))
+ number = 0;
+ else
+ number = 1;
}
break;
case BT_DATE:
case BT_TIME:
- if (pfile->date.type == CPP_EOF)
+ if (pfile->date == NULL)
{
/* Allocate __DATE__ and __TIME__ strings from permanent
storage. We only do this once, and don't generate them
at init time, because time() and localtime() are very
slow on some systems. */
- time_t tt = time (NULL);
- struct tm *tb = localtime (&tt);
-
- pfile->date.val.str.text =
- _cpp_unaligned_alloc (pfile, sizeof ("Oct 11 1347"));
- pfile->date.val.str.len = sizeof ("Oct 11 1347") - 1;
- pfile->date.type = CPP_STRING;
- pfile->date.flags = 0;
- sprintf ((char *) pfile->date.val.str.text, "%s %2d %4d",
- monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900);
-
- pfile->time.val.str.text =
- _cpp_unaligned_alloc (pfile, sizeof ("12:34:56"));
- pfile->time.val.str.len = sizeof ("12:34:56") - 1;
- pfile->time.type = CPP_STRING;
- pfile->time.flags = 0;
- sprintf ((char *) pfile->time.val.str.text, "%02d:%02d:%02d",
- tb->tm_hour, tb->tm_min, tb->tm_sec);
+ time_t tt;
+ struct tm *tb = NULL;
+
+ /* (time_t) -1 is a legitimate value for "number of seconds
+ since the Epoch", so we have to do a little dance to
+ distinguish that from a genuine error. */
+ errno = 0;
+ tt = time(NULL);
+ if (tt != (time_t)-1 || errno == 0)
+ tb = localtime (&tt);
+
+ if (tb)
+ {
+ pfile->date = _cpp_unaligned_alloc (pfile,
+ sizeof ("\"Oct 11 1347\""));
+ sprintf ((char *) pfile->date, "\"%s %2d %4d\"",
+ monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900);
+
+ pfile->time = _cpp_unaligned_alloc (pfile,
+ sizeof ("\"12:34:56\""));
+ sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"",
+ tb->tm_hour, tb->tm_min, tb->tm_sec);
+ }
+ else
+ {
+ cpp_errno (pfile, DL_WARNING,
+ "could not determine date and time");
+
+ pfile->date = U"\"??? ?? ????\"";
+ pfile->time = U"\"??:??:??\"";
+ }
}
if (node->value.builtin == BT_DATE)
- result = &pfile->date;
+ result = pfile->date;
else
- result = &pfile->time;
+ result = pfile->time;
break;
+ }
+
+ if (result == NULL)
+ {
+ /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers. */
+ result = _cpp_unaligned_alloc (pfile, 21);
+ sprintf ((char *) result, "%u", number);
+ }
+
+ return result;
+}
+
+/* Convert builtin macros like __FILE__ to a token and push it on the
+ context stack. Also handles _Pragma, for which no new token is
+ created. Returns 1 if it generates a new token context, 0 to
+ return the token to the caller. */
+static int
+builtin_macro (pfile, node)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+{
+ const uchar *buf;
- case BT_PRAGMA:
+ if (node->value.builtin == BT_PRAGMA)
+ {
/* Don't interpret _Pragma within directives. The standard is
not clear on this, but to me this makes most sense. */
if (pfile->state.in_directive)
@@ -234,7 +277,24 @@ builtin_macro (pfile, node)
return 1;
}
- push_token_context (pfile, NULL, result, 1);
+ buf = _cpp_builtin_macro_text (pfile, node);
+
+ cpp_push_buffer (pfile, buf, ustrlen (buf), /* from_stage3 */ true, 1);
+
+ /* Tweak the column number the lexer will report. */
+ pfile->buffer->col_adjust = pfile->cur_token[-1].col - 1;
+
+ /* We don't want a leading # to be interpreted as a directive. */
+ pfile->buffer->saved_flags = 0;
+
+ /* Set pfile->cur_token as required by _cpp_lex_direct. */
+ pfile->cur_token = _cpp_temp_token (pfile);
+ push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
+ if (pfile->buffer->cur != pfile->buffer->rlimit)
+ cpp_error (pfile, DL_ICE, "invalid built-in macro \"%s\"",
+ NODE_NAME (node));
+ _cpp_pop_buffer (pfile);
+
return 1;
}
@@ -242,15 +302,15 @@ builtin_macro (pfile, node)
backslashes and double quotes. Non-printable characters are
converted to octal. DEST must be of sufficient size. Returns
a pointer to the end of the string. */
-U_CHAR *
+uchar *
cpp_quote_string (dest, src, len)
- U_CHAR *dest;
- const U_CHAR *src;
+ uchar *dest;
+ const uchar *src;
unsigned int len;
{
while (len--)
{
- U_CHAR c = *src++;
+ uchar c = *src++;
if (c == '\\' || c == '"')
{
@@ -343,7 +403,8 @@ stringify_arg (pfile, arg)
/* Ignore the final \ of invalid string literals. */
if (backslash_count & 1)
{
- cpp_warning (pfile, "invalid string literal, ignoring final '\\'");
+ cpp_error (pfile, DL_WARNING,
+ "invalid string literal, ignoring final '\\'");
dest--;
}
@@ -359,7 +420,7 @@ stringify_arg (pfile, arg)
return new_string_token (pfile, dest - len, len);
}
-/* Try to paste two tokens. On success, return non-zero. In any
+/* Try to paste two tokens. On success, return nonzero. In any
case, PLHS is updated to point to the pasted token, which is
guaranteed to not have the PASTE_LEFT flag set. */
static bool
@@ -381,8 +442,7 @@ paste_tokens (pfile, plhs, rhs)
It is simpler to insert a space here, rather than modifying the
lexer to ignore comments in some circumstances. Simply returning
false doesn't work, since we want to clear the PASTE_LEFT flag. */
- if (lhs->type == CPP_DIV
- && (rhs->type == CPP_MULT || rhs->type == CPP_DIV))
+ if (lhs->type == CPP_DIV && rhs->type != CPP_EQ)
*end++ = ' ';
end = cpp_spell_token (pfile, rhs, end);
*end = '\0';
@@ -427,9 +487,9 @@ paste_all_tokens (pfile, lhs)
inserted. In either case, the constraints to #define
guarantee we have at least one more token. */
if (context->direct_p)
- rhs = context->first.token++;
+ rhs = FIRST (context).token++;
else
- rhs = *context->first.ptoken++;
+ rhs = *FIRST (context).ptoken++;
if (rhs->type == CPP_PADDING)
abort ();
@@ -438,12 +498,12 @@ paste_all_tokens (pfile, lhs)
{
_cpp_backup_tokens (pfile, 1);
- /* Mandatory warning for all apart from assembler. */
+ /* Mandatory error for all apart from assembler. */
if (CPP_OPTION (pfile, lang) != CLK_ASM)
- cpp_warning (pfile,
+ cpp_error (pfile, DL_ERROR,
"pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
- cpp_token_as_text (pfile, lhs),
- cpp_token_as_text (pfile, rhs));
+ cpp_token_as_text (pfile, lhs),
+ cpp_token_as_text (pfile, rhs));
break;
}
}
@@ -453,6 +513,52 @@ paste_all_tokens (pfile, lhs)
push_token_context (pfile, NULL, lhs, 1);
}
+/* Returns TRUE if the number of arguments ARGC supplied in an
+ invocation of the MACRO referenced by NODE is valid. An empty
+ invocation to a macro with no parameters should pass ARGC as zero.
+
+ Note that MACRO cannot necessarily be deduced from NODE, in case
+ NODE was redefined whilst collecting arguments. */
+bool
+_cpp_arguments_ok (pfile, macro, node, argc)
+ cpp_reader *pfile;
+ cpp_macro *macro;
+ const cpp_hashnode *node;
+ unsigned int argc;
+{
+ if (argc == macro->paramc)
+ return true;
+
+ if (argc < macro->paramc)
+ {
+ /* As an extension, a rest argument is allowed to not appear in
+ the invocation at all.
+ e.g. #define debug(format, args...) something
+ debug("string");
+
+ This is exactly the same as if there had been an empty rest
+ argument - debug("string", ). */
+
+ if (argc + 1 == macro->paramc && macro->variadic)
+ {
+ if (CPP_PEDANTIC (pfile) && ! macro->syshdr)
+ cpp_error (pfile, DL_PEDWARN,
+ "ISO C99 requires rest arguments to be used");
+ return true;
+ }
+
+ cpp_error (pfile, DL_ERROR,
+ "macro \"%s\" requires %u arguments, but only %u given",
+ NODE_NAME (node), macro->paramc, argc);
+ }
+ else
+ cpp_error (pfile, DL_ERROR,
+ "macro \"%s\" passed %u arguments, but takes just %u",
+ NODE_NAME (node), argc, macro->paramc);
+
+ return false;
+}
+
/* Reads and returns the arguments to a function-like macro
invocation. Assumes the opening parenthesis has been processed.
If there is an error, emits an appropriate diagnostic and returns
@@ -468,7 +574,6 @@ collect_args (pfile, node)
macro_arg *args, *arg;
const cpp_token *token;
unsigned int argc;
- bool error = false;
macro = node->value.macro;
if (macro->paramc)
@@ -550,90 +655,43 @@ collect_args (pfile, node)
arg++;
}
}
- while (token->type != CPP_CLOSE_PAREN
- && token->type != CPP_EOF
- && token->type != CPP_HASH);
+ while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF);
- if (token->type == CPP_EOF || token->type == CPP_HASH)
+ if (token->type == CPP_EOF)
{
- bool step_back = false;
-
- /* 6.10.3 paragraph 11: If there are sequences of preprocessing
- tokens within the list of arguments that would otherwise act
- as preprocessing directives, the behavior is undefined.
-
- This implementation will report a hard error, terminate the
- macro invocation, and proceed to process the directive. */
- if (token->type == CPP_HASH)
- {
- cpp_error (pfile,
- "directives may not be used inside a macro argument");
- step_back = true;
- }
- else
- step_back = (pfile->context->prev || pfile->state.in_directive);
-
/* We still need the CPP_EOF to end directives, and to end
pre-expansion of a macro argument. Step back is not
unconditional, since we don't want to return a CPP_EOF to our
callers at the end of an -include-d file. */
- if (step_back)
+ if (pfile->context->prev || pfile->state.in_directive)
_cpp_backup_tokens (pfile, 1);
- cpp_error (pfile, "unterminated argument list invoking macro \"%s\"",
+ cpp_error (pfile, DL_ERROR,
+ "unterminated argument list invoking macro \"%s\"",
NODE_NAME (node));
- error = true;
- }
- else if (argc < macro->paramc)
- {
- /* As an extension, a rest argument is allowed to not appear in
- the invocation at all.
- e.g. #define debug(format, args...) something
- debug("string");
-
- This is exactly the same as if there had been an empty rest
- argument - debug("string", ). */
-
- if (argc + 1 == macro->paramc && macro->variadic)
- {
- if (CPP_PEDANTIC (pfile) && ! macro->syshdr)
- cpp_pedwarn (pfile, "ISO C99 requires rest arguments to be used");
- }
- else
- {
- cpp_error (pfile,
- "macro \"%s\" requires %u arguments, but only %u given",
- NODE_NAME (node), macro->paramc, argc);
- error = true;
- }
}
- else if (argc > macro->paramc)
+ else
{
- /* Empty argument to a macro taking no arguments is OK. */
- if (argc != 1 || arg->count)
+ /* A single empty argument is counted as no argument. */
+ if (argc == 1 && macro->paramc == 0 && args[0].count == 0)
+ argc = 0;
+ if (_cpp_arguments_ok (pfile, macro, node, argc))
{
- cpp_error (pfile,
- "macro \"%s\" passed %u arguments, but takes just %u",
- NODE_NAME (node), argc, macro->paramc);
- error = true;
+ /* GCC has special semantics for , ## b where b is a varargs
+ parameter: we remove the comma if b was omitted entirely.
+ If b was merely an empty argument, the comma is retained.
+ If the macro takes just one (varargs) parameter, then we
+ retain the comma only if we are standards conforming.
+
+ If FIRST is NULL replace_args () swallows the comma. */
+ if (macro->variadic && (argc < macro->paramc
+ || (argc == 1 && args[0].count == 0
+ && !CPP_OPTION (pfile, std))))
+ args[macro->paramc - 1].first = NULL;
+ return base_buff;
}
}
- if (!error)
- {
- /* GCC has special semantics for , ## b where b is a varargs
- parameter: we remove the comma if b was omitted entirely.
- If b was merely an empty argument, the comma is retained.
- If the macro takes just one (varargs) parameter, then we
- retain the comma only if we are standards conforming.
-
- If FIRST is NULL replace_args () swallows the comma. */
- if (macro->variadic && (argc < macro->paramc
- || (argc == 1 && args[0].count == 0
- && !CPP_OPTION (pfile, std))))
- args[macro->paramc - 1].first = NULL;
- return base_buff;
- }
-
+ /* An error occurred. */
_cpp_release_buff (pfile, base_buff);
return NULL;
}
@@ -714,23 +772,25 @@ enter_macro_context (pfile, node)
if (buff == NULL)
{
if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
- cpp_warning (pfile,
+ cpp_error (pfile, DL_WARNING,
"function-like macro \"%s\" must be used with arguments in traditional C",
- NODE_NAME (node));
+ NODE_NAME (node));
return 0;
}
- if (node->value.macro->paramc > 0)
- replace_args (pfile, node, (macro_arg *) buff->base);
+ if (macro->paramc > 0)
+ replace_args (pfile, node, macro, (macro_arg *) buff->base);
_cpp_release_buff (pfile, buff);
}
/* Disable the macro within its expansion. */
node->flags |= NODE_DISABLED;
+ macro->used = 1;
+
if (macro->paramc == 0)
- push_token_context (pfile, node, macro->expansion, macro->count);
+ push_token_context (pfile, node, macro->exp.tokens, macro->count);
return 1;
}
@@ -744,9 +804,10 @@ enter_macro_context (pfile, node)
Expand each argument before replacing, unless it is operated upon
by the # or ## operators. */
static void
-replace_args (pfile, node, args)
+replace_args (pfile, node, macro, args)
cpp_reader *pfile;
cpp_hashnode *node;
+ cpp_macro *macro;
macro_arg *args;
{
unsigned int i, total;
@@ -754,17 +815,15 @@ replace_args (pfile, node, args)
const cpp_token **dest, **first;
macro_arg *arg;
_cpp_buff *buff;
- cpp_macro *macro;
/* First, fully macro-expand arguments, calculating the number of
tokens in the final expansion as we go. The ordering of the if
statements below is subtle; we must handle stringification before
pasting. */
- macro = node->value.macro;
total = macro->count;
- limit = macro->expansion + macro->count;
+ limit = macro->exp.tokens + macro->count;
- for (src = macro->expansion; src < limit; src++)
+ for (src = macro->exp.tokens; src < limit; src++)
if (src->type == CPP_MACRO_ARG)
{
/* Leading and trailing padding tokens. */
@@ -780,7 +839,7 @@ replace_args (pfile, node, args)
arg->stringified = stringify_arg (pfile, arg);
}
else if ((src->flags & PASTE_LEFT)
- || (src > macro->expansion && (src[-1].flags & PASTE_LEFT)))
+ || (src > macro->exp.tokens && (src[-1].flags & PASTE_LEFT)))
total += arg->count - 1;
else
{
@@ -796,7 +855,7 @@ replace_args (pfile, node, args)
first = (const cpp_token **) buff->base;
dest = first;
- for (src = macro->expansion; src < limit; src++)
+ for (src = macro->exp.tokens; src < limit; src++)
{
unsigned int count;
const cpp_token **from, **paste_flag;
@@ -813,7 +872,7 @@ replace_args (pfile, node, args)
count = 1, from = &arg->stringified;
else if (src->flags & PASTE_LEFT)
count = arg->count, from = arg->first;
- else if (src != macro->expansion && (src[-1].flags & PASTE_LEFT))
+ else if (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))
{
count = arg->count, from = arg->first;
if (dest != first)
@@ -838,8 +897,8 @@ replace_args (pfile, node, args)
count = arg->expanded_count, from = arg->expanded;
/* Padding on the left of an argument (unless RHS of ##). */
- if (!pfile->state.in_directive
- && src != macro->expansion && !(src[-1].flags & PASTE_LEFT))
+ if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
+ && src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT))
*dest++ = padding_token (pfile, src);
if (count)
@@ -927,8 +986,8 @@ push_ptoken_context (pfile, macro, buff, first, count)
context->direct_p = false;
context->macro = macro;
context->buff = buff;
- context->first.ptoken = first;
- context->last.ptoken = first + count;
+ FIRST (context).ptoken = first;
+ LAST (context).ptoken = first + count;
}
/* Push a list of tokens. */
@@ -944,8 +1003,26 @@ push_token_context (pfile, macro, first, count)
context->direct_p = true;
context->macro = macro;
context->buff = NULL;
- context->first.token = first;
- context->last.token = first + count;
+ FIRST (context).token = first;
+ LAST (context).token = first + count;
+}
+
+/* Push a traditional macro's replacement text. */
+void
+_cpp_push_text_context (pfile, macro, start, len)
+ cpp_reader *pfile;
+ cpp_hashnode *macro;
+ const uchar *start;
+ size_t len;
+{
+ cpp_context *context = next_context (pfile);
+
+ context->direct_p = true;
+ context->macro = macro;
+ context->buff = NULL;
+ CUR (context) = start;
+ RLIMIT (context) = start + len;
+ macro->flags |= NODE_DISABLED;
}
/* Expand an argument ARG before replacing parameters in a
@@ -960,10 +1037,15 @@ expand_arg (pfile, arg)
macro_arg *arg;
{
unsigned int capacity;
+ bool saved_warn_trad;
if (arg->count == 0)
return;
+ /* Don't warn about funlike macros when pre-expanding. */
+ saved_warn_trad = CPP_WTRADITIONAL (pfile);
+ CPP_WTRADITIONAL (pfile) = 0;
+
/* Loop, reading in the arguments. */
capacity = 256;
arg->expanded = (const cpp_token **)
@@ -990,6 +1072,8 @@ expand_arg (pfile, arg)
}
_cpp_pop_context (pfile);
+
+ CPP_WTRADITIONAL (pfile) = saved_warn_trad;
}
/* Pop the current context off the stack, re-enabling the macro if the
@@ -1035,12 +1119,12 @@ cpp_get_token (pfile)
/* Context->prev == 0 <=> base context. */
if (!context->prev)
result = _cpp_lex_token (pfile);
- else if (context->first.token != context->last.token)
+ else if (FIRST (context).token != LAST (context).token)
{
if (context->direct_p)
- result = context->first.token++;
+ result = FIRST (context).token++;
else
- result = *context->first.ptoken++;
+ result = *FIRST (context).ptoken++;
if (result->flags & PASTE_LEFT)
{
@@ -1058,6 +1142,9 @@ cpp_get_token (pfile)
return &pfile->avoid_paste;
}
+ if (pfile->state.in_directive && result->type == CPP_COMMENT)
+ continue;
+
if (result->type != CPP_NAME)
break;
@@ -1065,7 +1152,7 @@ cpp_get_token (pfile)
if (node->type != NT_MACRO || (result->flags & NO_EXPAND))
break;
-
+
if (!(node->flags & NODE_DISABLED))
{
if (!pfile->state.prevent_expansion
@@ -1105,14 +1192,22 @@ cpp_sys_macro_p (pfile)
return node && node->value.macro && node->value.macro->syshdr;
}
-/* Read each token in, until EOF. Directives are transparently
- processed. */
+/* Read each token in, until end of the current file. Directives are
+ transparently processed. */
void
cpp_scan_nooutput (pfile)
cpp_reader *pfile;
{
- while (cpp_get_token (pfile)->type != CPP_EOF)
- ;
+ /* Request a CPP_EOF token at the end of this file, rather than
+ transparently continuing with the including file. */
+ pfile->buffer->return_at_eof = true;
+
+ if (CPP_OPTION (pfile, traditional))
+ while (_cpp_read_logical_line_trad (pfile))
+ ;
+ else
+ while (cpp_get_token (pfile)->type != CPP_EOF)
+ ;
}
/* Step back one (or more) tokens. Can only step mack more than 1 if
@@ -1142,17 +1237,18 @@ _cpp_backup_tokens (pfile, count)
if (count != 1)
abort ();
if (pfile->context->direct_p)
- pfile->context->first.token--;
+ FIRST (pfile->context).token--;
else
- pfile->context->first.ptoken--;
+ FIRST (pfile->context).ptoken--;
}
}
/* #define directive parsing and handling. */
-/* Returns non-zero if a macro redefinition warning is required. */
-static int
-warn_of_redefinition (node, macro2)
+/* Returns nonzero if a macro redefinition warning is required. */
+static bool
+warn_of_redefinition (pfile, node, macro2)
+ cpp_reader *pfile;
const cpp_hashnode *node;
const cpp_macro *macro2;
{
@@ -1161,30 +1257,36 @@ warn_of_redefinition (node, macro2)
/* Some redefinitions need to be warned about regardless. */
if (node->flags & NODE_WARN)
- return 1;
+ return true;
/* Redefinition of a macro is allowed if and only if the old and new
definitions are the same. (6.10.3 paragraph 2). */
macro1 = node->value.macro;
- /* The quick failures. */
- if (macro1->count != macro2->count
- || macro1->paramc != macro2->paramc
+ /* Don't check count here as it can be different in valid
+ traditional redefinitions with just whitespace differences. */
+ if (macro1->paramc != macro2->paramc
|| macro1->fun_like != macro2->fun_like
|| macro1->variadic != macro2->variadic)
- return 1;
-
- /* Check each token. */
- for (i = 0; i < macro1->count; i++)
- if (! _cpp_equiv_tokens (&macro1->expansion[i], &macro2->expansion[i]))
- return 1;
+ return true;
/* Check parameter spellings. */
for (i = 0; i < macro1->paramc; i++)
if (macro1->params[i] != macro2->params[i])
- return 1;
+ return true;
+
+ /* Check the replacement text or tokens. */
+ if (CPP_OPTION (pfile, traditional))
+ return _cpp_expansions_different_trad (macro1, macro2);
+
+ if (macro1->count != macro2->count)
+ return true;
+
+ for (i = 0; i < macro1->count; i++)
+ if (!_cpp_equiv_tokens (&macro1->exp.tokens[i], &macro2->exp.tokens[i]))
+ return true;
- return 0;
+ return false;
}
/* Free the definition of hashnode H. */
@@ -1199,9 +1301,9 @@ _cpp_free_definition (h)
}
/* Save parameter NODE to the parameter list of macro MACRO. Returns
- zero on success, non-zero if the parameter is a duplicate. */
-static int
-save_parameter (pfile, macro, node)
+ zero on success, nonzero if the parameter is a duplicate. */
+bool
+_cpp_save_parameter (pfile, macro, node)
cpp_reader *pfile;
cpp_macro *macro;
cpp_hashnode *node;
@@ -1209,8 +1311,9 @@ save_parameter (pfile, macro, node)
/* Constraint 6.10.3.6 - duplicate parameter names. */
if (node->arg_index)
{
- cpp_error (pfile, "duplicate macro parameter \"%s\"", NODE_NAME (node));
- return 1;
+ cpp_error (pfile, DL_ERROR, "duplicate macro parameter \"%s\"",
+ NODE_NAME (node));
+ return true;
}
if (BUFF_ROOM (pfile->a_buff)
@@ -1219,11 +1322,12 @@ save_parameter (pfile, macro, node)
((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node;
node->arg_index = macro->paramc;
- return 0;
+ return false;
}
-/* Check the syntax of the parameters in a MACRO definition. */
-static int
+/* Check the syntax of the parameters in a MACRO definition. Returns
+ false if an error occurs. */
+static bool
parse_params (pfile, macro)
cpp_reader *pfile;
cpp_macro *macro;
@@ -1237,32 +1341,40 @@ parse_params (pfile, macro)
switch (token->type)
{
default:
- cpp_error (pfile, "\"%s\" may not appear in macro parameter list",
+ /* Allow/ignore comments in parameter lists if we are
+ preserving comments in macro expansions. */
+ if (token->type == CPP_COMMENT
+ && ! CPP_OPTION (pfile, discard_comments_in_macro_exp))
+ continue;
+
+ cpp_error (pfile, DL_ERROR,
+ "\"%s\" may not appear in macro parameter list",
cpp_token_as_text (pfile, token));
- return 0;
+ return false;
case CPP_NAME:
if (prev_ident)
{
- cpp_error (pfile, "macro parameters must be comma-separated");
- return 0;
+ cpp_error (pfile, DL_ERROR,
+ "macro parameters must be comma-separated");
+ return false;
}
prev_ident = 1;
- if (save_parameter (pfile, macro, token->val.node))
- return 0;
+ if (_cpp_save_parameter (pfile, macro, token->val.node))
+ return false;
continue;
case CPP_CLOSE_PAREN:
if (prev_ident || macro->paramc == 0)
- return 1;
+ return true;
/* Fall through to pick up the error. */
case CPP_COMMA:
if (!prev_ident)
{
- cpp_error (pfile, "parameter name missing");
- return 0;
+ cpp_error (pfile, DL_ERROR, "parameter name missing");
+ return false;
}
prev_ident = 0;
continue;
@@ -1271,24 +1383,26 @@ parse_params (pfile, macro)
macro->variadic = 1;
if (!prev_ident)
{
- save_parameter (pfile, macro, pfile->spec_nodes.n__VA_ARGS__);
+ _cpp_save_parameter (pfile, macro,
+ pfile->spec_nodes.n__VA_ARGS__);
pfile->state.va_args_ok = 1;
if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, pedantic))
- cpp_pedwarn (pfile,
- "anonymous variadic macros were introduced in C99");
+ cpp_error (pfile, DL_PEDWARN,
+ "anonymous variadic macros were introduced in C99");
}
else if (CPP_OPTION (pfile, pedantic))
- cpp_pedwarn (pfile, "ISO C does not permit named variadic macros");
+ cpp_error (pfile, DL_PEDWARN,
+ "ISO C does not permit named variadic macros");
/* We're at the end, and just expect a closing parenthesis. */
token = _cpp_lex_token (pfile);
if (token->type == CPP_CLOSE_PAREN)
- return 1;
+ return true;
/* Fall through. */
case CPP_EOF:
- cpp_error (pfile, "missing ')' in macro parameter list");
- return 0;
+ cpp_error (pfile, DL_ERROR, "missing ')' in macro parameter list");
+ return false;
}
}
}
@@ -1330,24 +1444,13 @@ lex_expansion_token (pfile, macro)
return token;
}
-/* Parse a macro and save its expansion. Returns non-zero on success. */
-int
-_cpp_create_definition (pfile, node)
+static bool
+create_iso_definition (pfile, macro)
cpp_reader *pfile;
- cpp_hashnode *node;
+ cpp_macro *macro;
{
- cpp_macro *macro;
- cpp_token *token, *saved_cur_token;
+ cpp_token *token;
const cpp_token *ctoken;
- unsigned int i, ok = 1;
-
- macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
- macro->line = pfile->directive_line;
- macro->params = 0;
- macro->paramc = 0;
- macro->variadic = 0;
- macro->count = 0;
- macro->fun_like = 0;
/* Get the first token of the expansion (or the '(' of a
function-like macro). */
@@ -1355,19 +1458,18 @@ _cpp_create_definition (pfile, node)
if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
{
- ok = parse_params (pfile, macro);
+ bool ok = parse_params (pfile, macro);
macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
if (!ok)
- goto cleanup2;
+ return false;
/* Success. Commit the parameter array. */
- BUFF_FRONT (pfile->a_buff) = (U_CHAR *) &macro->params[macro->paramc];
+ BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->params[macro->paramc];
macro->fun_like = 1;
}
else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
- cpp_pedwarn (pfile, "ISO C requires whitespace after the macro name");
-
- saved_cur_token = pfile->cur_token;
+ cpp_error (pfile, DL_PEDWARN,
+ "ISO C requires whitespace after the macro name");
if (macro->fun_like)
token = lex_expansion_token (pfile, macro);
@@ -1394,9 +1496,9 @@ _cpp_create_definition (pfile, node)
/* Let assembler get away with murder. */
else if (CPP_OPTION (pfile, lang) != CLK_ASM)
{
- ok = 0;
- cpp_error (pfile, "'#' is not followed by a macro parameter");
- goto cleanup1;
+ cpp_error (pfile, DL_ERROR,
+ "'#' is not followed by a macro parameter");
+ return false;
}
}
@@ -1413,10 +1515,9 @@ _cpp_create_definition (pfile, node)
if (macro->count == 0 || token->type == CPP_EOF)
{
- ok = 0;
- cpp_error (pfile,
+ cpp_error (pfile, DL_ERROR,
"'##' cannot appear at either end of a macro expansion");
- goto cleanup1;
+ return false;
}
token[-1].flags |= PASTE_LEFT;
@@ -1425,62 +1526,96 @@ _cpp_create_definition (pfile, node)
token = lex_expansion_token (pfile, macro);
}
- macro->expansion = (cpp_token *) BUFF_FRONT (pfile->a_buff);
+ macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff);
/* Don't count the CPP_EOF. */
macro->count--;
/* Clear whitespace on first token for warn_of_redefinition(). */
if (macro->count)
- macro->expansion[0].flags &= ~PREV_WHITE;
+ macro->exp.tokens[0].flags &= ~PREV_WHITE;
/* Commit the memory. */
- BUFF_FRONT (pfile->a_buff) = (U_CHAR *) &macro->expansion[macro->count];
+ BUFF_FRONT (pfile->a_buff) = (uchar *) &macro->exp.tokens[macro->count];
- /* Implement the macro-defined-to-itself optimisation. */
- if (macro->count == 1 && !macro->fun_like
- && macro->expansion[0].type == CPP_NAME
- && macro->expansion[0].val.node == node)
- node->flags |= NODE_DISABLED;
+ return true;
+}
+
+/* Parse a macro and save its expansion. Returns nonzero on success. */
+bool
+_cpp_create_definition (pfile, node)
+ cpp_reader *pfile;
+ cpp_hashnode *node;
+{
+ cpp_macro *macro;
+ unsigned int i;
+ bool ok;
+ macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
+ macro->line = pfile->directive_line;
+ macro->params = 0;
+ macro->paramc = 0;
+ macro->variadic = 0;
+ macro->used = 0;
+ macro->count = 0;
+ macro->fun_like = 0;
/* To suppress some diagnostics. */
macro->syshdr = pfile->map->sysp != 0;
- if (node->type != NT_VOID)
+ if (CPP_OPTION (pfile, traditional))
+ ok = _cpp_create_trad_definition (pfile, macro);
+ else
+ {
+ cpp_token *saved_cur_token = pfile->cur_token;
+
+ ok = create_iso_definition (pfile, macro);
+
+ /* Restore lexer position because of games lex_expansion_token()
+ plays lexing the macro. We set the type for SEEN_EOL() in
+ cpplib.c.
+
+ Longer term we should lex the whole line before coming here,
+ and just copy the expansion. */
+ saved_cur_token[-1].type = pfile->cur_token[-1].type;
+ pfile->cur_token = saved_cur_token;
+
+ /* Stop the lexer accepting __VA_ARGS__. */
+ pfile->state.va_args_ok = 0;
+ }
+
+ /* Clear the fast argument lookup indices. */
+ for (i = macro->paramc; i-- > 0; )
+ macro->params[i]->arg_index = 0;
+
+ if (!ok)
+ return ok;
+
+ if (node->type == NT_MACRO)
{
- if (warn_of_redefinition (node, macro))
+ if (CPP_OPTION (pfile, warn_unused_macros))
+ _cpp_warn_if_unused_macro (pfile, node, NULL);
+
+ if (warn_of_redefinition (pfile, node, macro))
{
- cpp_pedwarn_with_line (pfile, pfile->directive_line, 0,
- "\"%s\" redefined", NODE_NAME (node));
+ cpp_error_with_line (pfile, DL_PEDWARN, pfile->directive_line, 0,
+ "\"%s\" redefined", NODE_NAME (node));
if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
- cpp_pedwarn_with_line (pfile, node->value.macro->line, 0,
- "this is the location of the previous definition");
+ cpp_error_with_line (pfile, DL_PEDWARN,
+ node->value.macro->line, 0,
+ "this is the location of the previous definition");
}
- _cpp_free_definition (node);
}
+ if (node->type != NT_VOID)
+ _cpp_free_definition (node);
+
/* Enter definition in hash table. */
node->type = NT_MACRO;
node->value.macro = macro;
if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")))
node->flags |= NODE_WARN;
- cleanup1:
-
- /* Set type for SEEN_EOL() in cpplib.c, restore the lexer position. */
- saved_cur_token[-1].type = pfile->cur_token[-1].type;
- pfile->cur_token = saved_cur_token;
-
- cleanup2:
-
- /* Stop the lexer accepting __VA_ARGS__. */
- pfile->state.va_args_ok = 0;
-
- /* Clear the fast argument lookup indices. */
- for (i = macro->paramc; i-- > 0; )
- macro->params[i]->arg_index = 0;
-
return ok;
}
@@ -1493,8 +1628,8 @@ check_trad_stringification (pfile, macro, string)
const cpp_string *string;
{
unsigned int i, len;
- const U_CHAR *p, *q, *limit = string->text + string->len;
-
+ const uchar *p, *q, *limit = string->text + string->len;
+
/* Loop over the string. */
for (p = string->text; p < limit; p = q)
{
@@ -1518,9 +1653,9 @@ check_trad_stringification (pfile, macro, string)
if (NODE_LEN (node) == len
&& !memcmp (p, NODE_NAME (node), len))
{
- cpp_warning (pfile,
- "macro argument \"%s\" would be stringified with -traditional",
- NODE_NAME (node));
+ cpp_error (pfile, DL_WARNING,
+ "macro argument \"%s\" would be stringified in traditional C",
+ NODE_NAME (node));
break;
}
}
@@ -1543,7 +1678,8 @@ cpp_macro_definition (pfile, node)
if (node->type != NT_MACRO || (node->flags & NODE_BUILTIN))
{
- cpp_ice (pfile, "invalid hash type %d in cpp_macro_definition", node->type);
+ cpp_error (pfile, DL_ICE,
+ "invalid hash type %d in cpp_macro_definition", node->type);
return 0;
}
@@ -1557,23 +1693,28 @@ cpp_macro_definition (pfile, node)
len += NODE_LEN (macro->params[i]) + 1; /* "," */
}
- for (i = 0; i < macro->count; i++)
+ if (CPP_OPTION (pfile, traditional))
+ len += _cpp_replacement_text_len (macro);
+ else
{
- cpp_token *token = &macro->expansion[i];
+ for (i = 0; i < macro->count; i++)
+ {
+ cpp_token *token = &macro->exp.tokens[i];
- if (token->type == CPP_MACRO_ARG)
- len += NODE_LEN (macro->params[token->val.arg_no - 1]);
- else
- len += cpp_token_len (token); /* Includes room for ' '. */
- if (token->flags & STRINGIFY_ARG)
- len++; /* "#" */
- if (token->flags & PASTE_LEFT)
- len += 3; /* " ##" */
+ if (token->type == CPP_MACRO_ARG)
+ len += NODE_LEN (macro->params[token->val.arg_no - 1]);
+ else
+ len += cpp_token_len (token); /* Includes room for ' '. */
+ if (token->flags & STRINGIFY_ARG)
+ len++; /* "#" */
+ if (token->flags & PASTE_LEFT)
+ len += 3; /* " ##" */
+ }
}
if (len > pfile->macro_buffer_len)
{
- pfile->macro_buffer = (U_CHAR *) xrealloc (pfile->macro_buffer, len);
+ pfile->macro_buffer = (uchar *) xrealloc (pfile->macro_buffer, len);
pfile->macro_buffer_len = len;
}
@@ -1597,9 +1738,9 @@ cpp_macro_definition (pfile, node)
}
if (i + 1 < macro->paramc)
- /* Don't emit a space after the comma here; we're trying
- to emit a Dwarf-friendly definition, and the Dwarf spec
- forbids spaces in the argument list. */
+ /* Don't emit a space after the comma here; we're trying
+ to emit a Dwarf-friendly definition, and the Dwarf spec
+ forbids spaces in the argument list. */
*buffer++ = ',';
else if (macro->variadic)
*buffer++ = '.', *buffer++ = '.', *buffer++ = '.';
@@ -1611,12 +1752,14 @@ cpp_macro_definition (pfile, node)
definition is the empty string. */
*buffer++ = ' ';
+ if (CPP_OPTION (pfile, traditional))
+ buffer = _cpp_copy_replacement_text (macro, buffer);
+ else if (macro->count)
/* Expansion tokens. */
- if (macro->count)
{
for (i = 0; i < macro->count; i++)
{
- cpp_token *token = &macro->expansion[i];
+ cpp_token *token = &macro->exp.tokens[i];
if (token->flags & PREV_WHITE)
*buffer++ = ' ';
OpenPOWER on IntegriCloud