/* Part of CPP library. (Macro and #define handling.)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006 Free Software Foundation, Inc.
+ 2006, 2007, 2008 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
/* Macro expansion. */
-static int enter_macro_context (cpp_reader *, cpp_hashnode *);
+static int enter_macro_context (cpp_reader *, cpp_hashnode *,
+ const cpp_token *);
static int builtin_macro (cpp_reader *, cpp_hashnode *);
static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
const cpp_token **, unsigned int);
-static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *);
+static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *,
+ _cpp_buff **);
static cpp_context *next_context (cpp_reader *);
static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
static void expand_arg (cpp_reader *, macro_arg *);
static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *);
static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *,
macro_arg *);
-static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *);
+static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *,
+ _cpp_buff **);
static bool create_iso_definition (cpp_reader *, cpp_macro *);
/* #define directive parsing and handling. */
{
cpp_errno (pfile, CPP_DL_WARNING,
"could not determine file timestamp");
- pbuffer->timestamp = U"\"??? ??? ?? ??:??:?? ????\"";
+ pbuffer->timestamp = UC"\"??? ??? ?? ??:??:?? ????\"";
}
}
}
cpp_errno (pfile, CPP_DL_WARNING,
"could not determine date and time");
- pfile->date = U"\"??? ?? ????\"";
- pfile->time = U"\"??:??:??\"";
+ pfile->date = UC"\"??? ?? ????\"";
+ pfile->time = UC"\"??:??:??\"";
}
}
else
result = pfile->time;
break;
+
+ case BT_COUNTER:
+ if (CPP_OPTION (pfile, directives_only) && pfile->state.in_directive)
+ cpp_error (pfile, CPP_DL_ERROR,
+ "__COUNTER__ expanded inside directive with -fdirectives-only");
+ number = pfile->counter++;
+ break;
}
if (result == NULL)
if (pfile->state.in_directive)
return 0;
- _cpp_do__Pragma (pfile);
- return 1;
+ return _cpp_do__Pragma (pfile);
}
buf = _cpp_builtin_macro_text (pfile, node);
continue;
}
- escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING
- || token->type == CPP_CHAR || token->type == CPP_WCHAR);
+ escape_it = (token->type == CPP_STRING || token->type == CPP_CHAR
+ || token->type == CPP_WSTRING || token->type == CPP_STRING
+ || token->type == CPP_STRING32 || token->type == CPP_CHAR32
+ || token->type == CPP_STRING16 || token->type == CPP_CHAR16);
/* Room for each char being written in octal, initial space and
final quote and NUL. */
paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
{
unsigned char *buf, *end, *lhsend;
- const cpp_token *lhs;
+ cpp_token *lhs;
unsigned int len;
- lhs = *plhs;
- len = cpp_token_len (lhs) + cpp_token_len (rhs) + 1;
+ len = cpp_token_len (*plhs) + cpp_token_len (rhs) + 1;
buf = (unsigned char *) alloca (len);
- end = lhsend = cpp_spell_token (pfile, lhs, buf, false);
+ end = lhsend = cpp_spell_token (pfile, *plhs, buf, false);
/* Avoid comment headers, since they are still processed in stage 3.
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_EQ)
+ if ((*plhs)->type == CPP_DIV && rhs->type != CPP_EQ)
*end++ = ' ';
- end = cpp_spell_token (pfile, rhs, end, false);
+ /* In one obscure case we might see padding here. */
+ if (rhs->type != CPP_PADDING)
+ end = cpp_spell_token (pfile, rhs, end, false);
*end = '\n';
cpp_push_buffer (pfile, buf, end - buf, /* from_stage3 */ true);
/* Set pfile->cur_token as required by _cpp_lex_direct. */
pfile->cur_token = _cpp_temp_token (pfile);
- *plhs = _cpp_lex_direct (pfile);
+ lhs = _cpp_lex_direct (pfile);
if (pfile->buffer->cur != pfile->buffer->rlimit)
{
+ source_location saved_loc = lhs->src_loc;
+
_cpp_pop_buffer (pfile);
_cpp_backup_tokens (pfile, 1);
*lhsend = '\0';
+ /* We have to remove the PASTE_LEFT flag from the old lhs, but
+ we want to keep the new location. */
+ *lhs = **plhs;
+ *plhs = lhs;
+ lhs->src_loc = saved_loc;
+ lhs->flags &= ~PASTE_LEFT;
+
/* Mandatory error for all apart from assembler. */
if (CPP_OPTION (pfile, lang) != CLK_ASM)
cpp_error (pfile, CPP_DL_ERROR,
return false;
}
+ *plhs = lhs;
_cpp_pop_buffer (pfile);
return true;
}
rhs = *FIRST (context).ptoken++;
if (rhs->type == CPP_PADDING)
- abort ();
-
+ {
+ if (rhs->flags & PASTE_LEFT)
+ abort ();
+ }
if (!paste_tokens (pfile, &lhs, rhs))
break;
}
invocation. Assumes the opening parenthesis has been processed.
If there is an error, emits an appropriate diagnostic and returns
NULL. Each argument is terminated by a CPP_EOF token, for the
- future benefit of expand_arg(). */
+ future benefit of expand_arg(). If there are any deferred
+ #pragma directives among macro arguments, store pointers to the
+ CPP_PRAGMA ... CPP_PRAGMA_EOL tokens into *PRAGMA_BUFF buffer. */
static _cpp_buff *
-collect_args (cpp_reader *pfile, const cpp_hashnode *node)
+collect_args (cpp_reader *pfile, const cpp_hashnode *node,
+ _cpp_buff **pragma_buff)
{
_cpp_buff *buff, *base_buff;
cpp_macro *macro;
else if (token->type == CPP_EOF
|| (token->type == CPP_HASH && token->flags & BOL))
break;
+ else if (token->type == CPP_PRAGMA)
+ {
+ cpp_token *newtok = _cpp_temp_token (pfile);
+
+ /* CPP_PRAGMA token lives in directive_result, which will
+ be overwritten on the next directive. */
+ *newtok = *token;
+ token = newtok;
+ do
+ {
+ if (*pragma_buff == NULL
+ || BUFF_ROOM (*pragma_buff) < sizeof (cpp_token *))
+ {
+ _cpp_buff *next;
+ if (*pragma_buff == NULL)
+ *pragma_buff
+ = _cpp_get_buff (pfile, 32 * sizeof (cpp_token *));
+ else
+ {
+ next = *pragma_buff;
+ *pragma_buff
+ = _cpp_get_buff (pfile,
+ (BUFF_FRONT (*pragma_buff)
+ - (*pragma_buff)->base) * 2);
+ (*pragma_buff)->next = next;
+ }
+ }
+ *(const cpp_token **) BUFF_FRONT (*pragma_buff) = token;
+ BUFF_FRONT (*pragma_buff) += sizeof (cpp_token *);
+ if (token->type == CPP_PRAGMA_EOL)
+ break;
+ token = cpp_get_token (pfile);
+ }
+ while (token->type != CPP_EOF);
+
+ /* In deferred pragmas parsing_args and prevent_expansion
+ had been changed, reset it. */
+ pfile->state.parsing_args = 2;
+ pfile->state.prevent_expansion = 1;
+
+ if (token->type == CPP_EOF)
+ break;
+ else
+ continue;
+ }
arg->first[ntokens++] = token;
}
/* Search for an opening parenthesis to the macro of NODE, in such a
way that, if none is found, we don't lose the information in any
intervening padding tokens. If we find the parenthesis, collect
- the arguments and return the buffer containing them. */
+ the arguments and return the buffer containing them. PRAGMA_BUFF
+ argument is the same as in collect_args. */
static _cpp_buff *
-funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
+funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
+ _cpp_buff **pragma_buff)
{
const cpp_token *token, *padding = NULL;
if (token->type == CPP_OPEN_PAREN)
{
pfile->state.parsing_args = 2;
- return collect_args (pfile, node);
+ return collect_args (pfile, node, pragma_buff);
}
/* CPP_EOF can be the end of macro arguments, or the end of the
/* Push the context of a macro with hash entry NODE onto the context
stack. If we can successfully expand the macro, we push a context
containing its yet-to-be-rescanned replacement list and return one.
- Otherwise, we don't push a context and return zero. */
+ If there were additionally any unexpanded deferred #pragma directives
+ among macro arguments, push another context containing the
+ pragma tokens before the yet-to-be-rescanned replacement list
+ and return two. Otherwise, we don't push a context and return zero. */
static int
-enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
+enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
+ const cpp_token *result)
{
/* The presence of a macro invalidates a file's controlling macro. */
pfile->mi_valid = false;
pfile->state.angled_headers = false;
+ if ((node->flags & NODE_BUILTIN) && !(node->flags & NODE_USED))
+ {
+ node->flags |= NODE_USED;
+ if (pfile->cb.used_define)
+ pfile->cb.used_define (pfile, pfile->directive_line, node);
+ }
+
/* Handle standard macros. */
if (! (node->flags & NODE_BUILTIN))
{
cpp_macro *macro = node->value.macro;
+ _cpp_buff *pragma_buff = NULL;
if (macro->fun_like)
{
pfile->state.prevent_expansion++;
pfile->keep_tokens++;
pfile->state.parsing_args = 1;
- buff = funlike_invocation_p (pfile, node);
+ buff = funlike_invocation_p (pfile, node, &pragma_buff);
pfile->state.parsing_args = 0;
pfile->keep_tokens--;
pfile->state.prevent_expansion--;
"function-like macro \"%s\" must be used with arguments in traditional C",
NODE_NAME (node));
+ if (pragma_buff)
+ _cpp_release_buff (pfile, pragma_buff);
+
return 0;
}
/* Disable the macro within its expansion. */
node->flags |= NODE_DISABLED;
+ if (!(node->flags & NODE_USED))
+ {
+ node->flags |= NODE_USED;
+ if (pfile->cb.used_define)
+ pfile->cb.used_define (pfile, pfile->directive_line, node);
+ }
+
macro->used = 1;
if (macro->paramc == 0)
_cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count);
+ if (pragma_buff)
+ {
+ if (!pfile->state.in_directive)
+ _cpp_push_token_context (pfile, NULL,
+ padding_token (pfile, result), 1);
+ do
+ {
+ _cpp_buff *tail = pragma_buff->next;
+ pragma_buff->next = NULL;
+ push_ptoken_context (pfile, NULL, pragma_buff,
+ (const cpp_token **) pragma_buff->base,
+ ((const cpp_token **) BUFF_FRONT (pragma_buff)
+ - (const cpp_token **) pragma_buff->base));
+ pragma_buff = tail;
+ }
+ while (pragma_buff != NULL);
+ return 2;
+ }
+
return 1;
}
if (src->flags & PASTE_LEFT)
paste_flag = dest - 1;
}
+ else if (CPP_PEDANTIC (pfile) && ! macro->syshdr
+ && ! CPP_OPTION (pfile, c99)
+ && ! cpp_in_system_header (pfile))
+ {
+ cpp_error (pfile, CPP_DL_PEDWARN,
+ "invoking macro %s argument %d: "
+ "empty macro arguments are undefined"
+ " in ISO C90 and ISO C++98",
+ NODE_NAME (node),
+ src->val.arg_no);
+ }
/* Avoid paste on RHS (even case count == 0). */
if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT))
cpp_get_token (cpp_reader *pfile)
{
const cpp_token *result;
+ bool can_set = pfile->set_invocation_location;
+ pfile->set_invocation_location = false;
for (;;)
{
if (!(node->flags & NODE_DISABLED))
{
- if (!pfile->state.prevent_expansion
- && enter_macro_context (pfile, node))
+ int ret;
+ /* If not in a macro context, and we're going to start an
+ expansion, record the location. */
+ if (can_set && !context->macro)
+ pfile->invocation_location = result->src_loc;
+ if (pfile->state.prevent_expansion)
+ break;
+ ret = enter_macro_context (pfile, node, result);
+ if (ret)
{
- if (pfile->state.in_directive)
+ if (pfile->state.in_directive || ret == 2)
continue;
return padding_token (pfile, result);
}
return result;
}
+/* Like cpp_get_token, but also returns a location separate from the
+ one provided by the returned token. LOC is an out parameter; *LOC
+ is set to the location "as expected by the user". This matters
+ when a token results from macro expansion -- the token's location
+ will indicate where the macro is defined, but *LOC will be the
+ location of the start of the expansion. */
+const cpp_token *
+cpp_get_token_with_location (cpp_reader *pfile, source_location *loc)
+{
+ const cpp_token *result;
+
+ pfile->set_invocation_location = true;
+ result = cpp_get_token (pfile);
+ if (pfile->context->macro)
+ *loc = pfile->invocation_location;
+ else
+ *loc = result->src_loc;
+
+ return result;
+}
+
/* Returns true if we're expanding an object-like macro that was
defined in a system header. Just checks the macro at the top of
the stack. Used for diagnostic suppression. */
/* Macros and assertions no longer have anything to free. */
h->type = NT_VOID;
/* Clear builtin flag in case of redefinition. */
- h->flags &= ~(NODE_BUILTIN | NODE_DISABLED);
+ h->flags &= ~(NODE_BUILTIN | NODE_DISABLED | NODE_USED);
}
/* Save parameter NODE to the parameter list of macro MACRO. Returns
{
cpp_token *token;
const cpp_token *ctoken;
+ bool following_paste_op = false;
+ const char *paste_op_error_msg =
+ N_("'##' cannot appear at either end of a macro expansion");
/* Get the first token of the expansion (or the '(' of a
function-like macro). */
}
if (token->type == CPP_EOF)
- break;
+ {
+ /* Paste operator constraint 6.10.3.3.1:
+ Token-paste ##, can appear in both object-like and
+ function-like macros, but not at the end. */
+ if (following_paste_op)
+ {
+ cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
+ return false;
+ }
+ break;
+ }
/* Paste operator constraint 6.10.3.3.1. */
if (token->type == CPP_PASTE)
{
/* Token-paste ##, can appear in both object-like and
- function-like macros, but not at the ends. */
- if (--macro->count > 0)
- token = lex_expansion_token (pfile, macro);
-
- if (macro->count == 0 || token->type == CPP_EOF)
+ function-like macros, but not at the beginning. */
+ if (macro->count == 1)
{
- cpp_error (pfile, CPP_DL_ERROR,
- "'##' cannot appear at either end of a macro expansion");
+ cpp_error (pfile, CPP_DL_ERROR, paste_op_error_msg);
return false;
}
+ --macro->count;
token[-1].flags |= PASTE_LEFT;
}
+ following_paste_op = (token->type == CPP_PASTE);
token = lex_expansion_token (pfile, macro);
}
/* Enter definition in hash table. */
node->type = NT_MACRO;
node->value.macro = macro;
- if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")))
+ if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_"))
+ && ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_FORMAT_MACROS")
+ /* __STDC_LIMIT_MACROS and __STDC_CONSTANT_MACROS are mentioned
+ in the C standard, as something that one must use in C++.
+ However DR#593 indicates that these aren't actually mentioned
+ in the C++ standard. We special-case them anyway. */
+ && ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_LIMIT_MACROS")
+ && ustrcmp (NODE_NAME (node), (const uchar *) "__STDC_CONSTANT_MACROS"))
node->flags |= NODE_WARN;
return ok;