aboutsummaryrefslogtreecommitdiff
path: root/gcc/cccp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cccp.c')
-rw-r--r--gcc/cccp.c108
1 files changed, 83 insertions, 25 deletions
diff --git a/gcc/cccp.c b/gcc/cccp.c
index 5c90cfa..16def7a 100644
--- a/gcc/cccp.c
+++ b/gcc/cccp.c
@@ -640,6 +640,7 @@ enum node_type {
T_DISABLED, /* macro temporarily turned off for rescan */
T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */
T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */
+ T_POISON, /* defined with `#pragma poison' */
T_UNUSED /* Used for something not defined. */
};
@@ -4281,7 +4282,12 @@ special_symbol (hp, op)
|| (hp->type == T_MACRO && hp->value.defn->predefined)))
/* Output a precondition for this macro use. */
fprintf (pcp_outfile, "#define %s\n", hp->name);
- buf = " 1 ";
+ if (hp->type == T_POISON) {
+ error("attempt to use poisoned `%s'.", hp->name);
+ buf = " 0 ";
+ } else {
+ buf = " 1 ";
+ }
}
else
if (pcp_outfile && pcp_inside_if) {
@@ -4302,6 +4308,11 @@ special_symbol (hp, op)
}
break;
+ case T_POISON:
+ error("attempt to use poisoned `%s'.", hp->name);
+ buf = " 0 "; /* Consider poisoned symbol to not be defined */
+ break;
+
oops:
error ("`defined' without an identifier");
@@ -5926,6 +5937,7 @@ do_define (buf, limit, op, keyword)
{
int hashcode;
MACRODEF mdef;
+ enum node_type newtype = keyword->type == T_DEFINE ? T_MACRO : T_POISON;
/* If this is a precompiler run (with -pcp) pass thru #define directives. */
if (pcp_outfile && op)
@@ -5944,35 +5956,50 @@ do_define (buf, limit, op, keyword)
/* Redefining a precompiled key is ok. */
if (hp->type == T_PCSTRING)
ok = 1;
+ /* Redefining a poisoned identifier is even worse than `not ok'. */
+ else if (hp->type == T_POISON)
+ ok = -1;
+ /* Poisoning anything else is not ok.
+ The poison should always come first. */
+ else if (newtype == T_POISON)
+ ok = 0;
/* Redefining a macro is ok if the definitions are the same. */
else if (hp->type == T_MACRO)
ok = ! compare_defs (mdef.defn, hp->value.defn);
/* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST)
ok = ! done_initializing;
- /* Print the warning if it's not ok. */
- if (!ok) {
- /* If we are passing through #define and #undef directives, do
- that for this re-definition now. */
- if (debug_output && op)
- pass_thru_directive (buf, limit, op, keyword);
-
- pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam);
- if (hp->type == T_MACRO)
- pedwarn_with_file_and_line (hp->value.defn->file,
- hp->value.defn->file_len,
- hp->value.defn->line,
- "this is the location of the previous definition");
- }
- /* Replace the old definition. */
- hp->type = T_MACRO;
- hp->value.defn = mdef.defn;
+
+ /* Print the warning or error if it's not ok. */
+ if (ok <= 0)
+ {
+ /* If we are passing through #define and #undef directives, do
+ that for this re-definition now. */
+ if (debug_output && op)
+ pass_thru_directive (buf, limit, op, keyword);
+
+ if (hp->type == T_POISON)
+ error ("redefining poisoned `%.*s'", mdef.symlen, mdef.symnam);
+ else
+ pedwarn ("`%.*s' redefined", mdef.symlen, mdef.symnam);
+ if (hp->type == T_MACRO)
+ pedwarn_with_file_and_line (hp->value.defn->file,
+ hp->value.defn->file_len,
+ hp->value.defn->line,
+ "this is the location of the previous definition");
+ }
+ if (hp->type != T_POISON)
+ {
+ /* Replace the old definition. */
+ hp->type = newtype;
+ hp->value.defn = mdef.defn;
+ }
} else {
/* If we are passing through #define and #undef directives, do
that for this new definition now. */
if (debug_output && op)
pass_thru_directive (buf, limit, op, keyword);
- install (mdef.symnam, mdef.symlen, T_MACRO,
+ install (mdef.symnam, mdef.symlen, newtype,
(char *) mdef.defn, hashcode);
}
}
@@ -6990,9 +7017,13 @@ do_undef (buf, limit, op, keyword)
need to pass through all effective #undef directives. */
if (debug_output && op)
pass_thru_directive (orig_buf, limit, op, keyword);
- if (hp->type != T_MACRO)
- warning ("undefining `%s'", hp->name);
- delete_macro (hp);
+ if (hp->type == T_POISON)
+ error ("cannot undefine poisoned `%s'", hp->name);
+ else {
+ if (hp->type != T_MACRO)
+ warning ("undefining `%s'", hp->name);
+ delete_macro (hp);
+ }
}
if (pedantic) {
@@ -7087,9 +7118,9 @@ do_ident (buf, limit, op, keyword)
static int
do_pragma (buf, limit, op, keyword)
- U_CHAR *buf, *limit ATTRIBUTE_UNUSED;
- FILE_BUF *op ATTRIBUTE_UNUSED;
- struct directive *keyword ATTRIBUTE_UNUSED;
+ U_CHAR *buf, *limit;
+ FILE_BUF *op;
+ struct directive *keyword;
{
SKIP_WHITE_SPACE (buf);
if (!strncmp ((char *) buf, "once", 4)) {
@@ -7100,6 +7131,29 @@ do_pragma (buf, limit, op, keyword)
do_once ();
}
+ if (!strncmp (buf, "poison", 6)) {
+ /* Poison these symbols so that all subsequent usage produces an
+ error message. */
+ U_CHAR *p = buf + 6;
+
+ SKIP_WHITE_SPACE (p);
+ while (p < limit)
+ {
+ U_CHAR *end = p;
+
+ while (end < limit && is_idchar[*end])
+ end++;
+ if (end < limit && !is_space[*end])
+ {
+ error ("invalid #pragma poison");
+ return 0;
+ }
+ do_define(p, end, op, keyword);
+ p = end;
+ SKIP_WHITE_SPACE (p);
+ }
+ }
+
if (!strncmp ((char *) buf, "implementation", 14)) {
/* Be quiet about `#pragma implementation' for a file only if it hasn't
been included yet. */
@@ -7351,6 +7405,10 @@ do_xifdef (buf, limit, op, keyword)
}
}
+ if ((hp != NULL) && (hp->type == T_POISON)) {
+ error("attempt to use poisoned `%s'.", hp->name);
+ hp = NULL;
+ }
skip = (hp == NULL) ^ (keyword->type == T_IFNDEF);
if (start_of_file && !skip) {
control_macro = (U_CHAR *) xmalloc (end - buf + 1);