aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeoff Keating <geoffk@cygnus.com>1999-09-09 04:00:37 +0000
committerGeoffrey Keating <geoffk@gcc.gnu.org>1999-09-09 04:00:37 +0000
commitfc009f966c98317401b51127f59de4ad37bb7d19 (patch)
treeadfb849ae0813b5bacab43fb7a7ab5ec23bc7fb6
parentd60f72aec57414b8339eecb25c33b423af7e6946 (diff)
downloadgcc-fc009f966c98317401b51127f59de4ad37bb7d19.zip
gcc-fc009f966c98317401b51127f59de4ad37bb7d19.tar.gz
gcc-fc009f966c98317401b51127f59de4ad37bb7d19.tar.bz2
Makefile.in (cppexp.o): Depend on cpphash.h.
* Makefile.in (cppexp.o): Depend on cpphash.h. * cppexp.c (cpp_lex): Handle `defined (xxx)' for poisoned xxx. Include cpphash.h. * cpphash.c (special_symbol): Handle plain `xxx' for poisoned xxx. * cpplib.c (do_define): Generalise to handle poisoned definitions, redefining poisoned identifiers, etc. (do_undef): Don't allow poisoned identifiers to be undefined. (do_pragma): Add #pragma poison. (do_xifdef): Handle `#ifdef xxx' for poisoned xxx. * cccp.c: Add T_POISON node type. (special_symbol): Handle `defined(xxx)' and plain `xxx' for poisoned xxx. (do_define): Generalise to handle poisoned definitions, redefining poisoned identifiers, etc. (do_undef): Don't allow poisoned identifiers to be undefined. (do_pragma): Add #pragma poison. (do_xifdef): Handle `#ifdef xxx' for poisoned xxx. * c-pragma.c (handle_pragma_token): Ignore #pragma poison. * c-pragma.h: Add ps_poison state. We now always have generic pragmas. From-SVN: r29224
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/c-pragma.c17
-rw-r--r--gcc/c-pragma.h6
-rw-r--r--gcc/cccp.c108
-rw-r--r--gcc/cpp.texi26
-rw-r--r--gcc/cppexp.c13
-rw-r--r--gcc/cpphash.c7
-rw-r--r--gcc/cpplib.c112
-rw-r--r--gcc/cpplib.h1
-rw-r--r--gcc/testsuite/gcc.c-torture/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/noncompile/noncompile.exp10
-rw-r--r--gcc/testsuite/gcc.c-torture/noncompile/poison-1.c22
13 files changed, 304 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bdd4753..ffd9ae5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@
+Thu Sep 9 13:46:06 1999 Geoffrey Keating <geoffk@cygnus.com>
+
+ * Makefile.in (cppexp.o): Depend on cpphash.h.
+ * cppexp.c (cpp_lex): Handle `defined (xxx)' for poisoned xxx.
+ Include cpphash.h.
+ * cpphash.c (special_symbol): Handle plain `xxx' for poisoned xxx.
+ * cpplib.c (do_define): Generalise to handle poisoned definitions,
+ redefining poisoned identifiers, etc.
+ (do_undef): Don't allow poisoned identifiers to be undefined.
+ (do_pragma): Add #pragma poison.
+ (do_xifdef): Handle `#ifdef xxx' for poisoned xxx.
+
+ * cccp.c: Add T_POISON node type.
+ (special_symbol): Handle `defined(xxx)' and plain `xxx' for
+ poisoned xxx.
+ (do_define): Generalise to handle poisoned definitions,
+ redefining poisoned identifiers, etc.
+ (do_undef): Don't allow poisoned identifiers to be undefined.
+ (do_pragma): Add #pragma poison.
+ (do_xifdef): Handle `#ifdef xxx' for poisoned xxx.
+
+ * c-pragma.c (handle_pragma_token): Ignore #pragma poison.
+ * c-pragma.h: Add ps_poison state. We now always have generic
+ pragmas.
+
Wed Sep 8 20:30:42 1999 Mark Mitchell <mark@codesourcery.com>
* ggc.h (ggc_alloc): New function.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 3f44714..a5a87ee 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2019,7 +2019,7 @@ cpplib.o: cpplib.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h
cpphash.o: cpphash.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h
cppalloc.o: cppalloc.c $(CONFIG_H) cpplib.h intl.h system.h
cpperror.o: cpperror.c $(CONFIG_H) cpplib.h intl.h system.h
-cppexp.o: cppexp.c $(CONFIG_H) cpplib.h intl.h system.h
+cppexp.o: cppexp.c $(CONFIG_H) cpplib.h intl.h system.h cpphash.h
cppfiles.o: cppfiles.c $(CONFIG_H) cpplib.h intl.h system.h
cppinit.o: cppinit.c $(CONFIG_H) cpplib.h intl.h system.h \
diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c
index 017bdef..bfb6bdc 100644
--- a/gcc/c-pragma.c
+++ b/gcc/c-pragma.c
@@ -300,6 +300,10 @@ handle_pragma_token (string, token)
ret_val = 1; /* Ignore the pragma. */
break;
#endif /* HANDLE_PRAGMA_WEAK */
+
+ case ps_poison:
+ ret_val = 1;
+ break;
}
type = state = ps_start;
@@ -338,9 +342,11 @@ handle_pragma_token (string, token)
#ifdef HANDLE_PRAGMA_WEAK
if (strcmp (string, "weak") == 0)
type = state = ps_weak;
-#endif
+#endif
+ if (strcmp (string, "poison") == 0)
+ type = state = ps_poison;
break;
-
+
#ifdef HANDLE_PRAGMA_WEAK
case ps_weak:
name = permalloc (strlen (string) + 1);
@@ -485,7 +491,12 @@ handle_pragma_token (string, token)
state = ps_bad;
break;
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
-
+
+ case ps_poison:
+ if (token && TREE_CODE (token) != IDENTIFIER_NODE)
+ state = ps_bad;
+ break;
+
case ps_bad:
case ps_done:
break;
diff --git a/gcc/c-pragma.h b/gcc/c-pragma.h
index f94ee9f..bfe7c1fe 100644
--- a/gcc/c-pragma.h
+++ b/gcc/c-pragma.h
@@ -61,13 +61,12 @@ extern int add_weak PROTO((char *, char *));
#endif /* HANDLE_PRAGMA_WEAK */
-#if defined HANDLE_PRAGMA_PACK || defined HANDLE_PRAGMA_WEAK
/* Define HANDLE_GENERIC_PRAGMAS if any kind of front-end pragma
parsing is to be done. The code in GCC's generic C source files
will only look for the definition of this constant. They will
- ignore definitions of HANDLE_PRAGMA_PACK and so on. */
+ ignore definitions of HANDLE_PRAGMA_PACK and so on.
+ With #pragma poison, this is always set. */
#define HANDLE_GENERIC_PRAGMAS 1
-#endif
#ifdef HANDLE_GENERIC_PRAGMAS
@@ -91,6 +90,7 @@ enum pragma_state
ps_push, ps_pushcomma, ps_pushid, ps_pushcomma2,
ps_pop, ps_popcomma,
#endif
+ ps_poison,
ps_bad
};
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);
diff --git a/gcc/cpp.texi b/gcc/cpp.texi
index e9a9095..5751722 100644
--- a/gcc/cpp.texi
+++ b/gcc/cpp.texi
@@ -551,6 +551,7 @@ in the C preprocessor.
* Concatenation:: Building tokens from parts taken from macro arguments.
* Undefining:: Cancelling a macro's definition.
* Redefining:: Changing a macro's definition.
+* Poisoning:: Ensuring a macro is never defined or used.
* Macro Pitfalls:: Macros can confuse the unwary. Here we explain
several common problems and strange features.
@end menu
@@ -1370,7 +1371,7 @@ The same form of @samp{#undef} directive will cancel definitions with
arguments or definitions that don't expect arguments. The @samp{#undef}
directive has no effect when used on a name not currently defined as a macro.
-@node Redefining, Macro Pitfalls, Undefining, Macros
+@node Redefining, Poisoning, Undefining, Macros
@subsection Redefining Macros
@cindex redefining macros
@@ -1404,7 +1405,28 @@ where there was no whitespace at all.
Recall that a comment counts as whitespace.
-@node Macro Pitfalls,, Redefining, Macros
+@node Poisoning, Macro Pitfalls, Redefining, Macros
+@subsection Poisoning Macros
+@cindex poisoning macros
+
+Sometimes, there is an identifier that you want to remove completely
+from your program, and make sure that it never creeps back in. To
+enforce this, the @samp{#pragma poison} directive can be used.
+@samp{#pragma poison} is followed by a list of identifiers to poison,
+and takes effect for the rest of the source. You cannot @samp{#undef} a
+poisoned identifier or test to see if it's defined with @samp{#ifdef}.
+
+For example,
+
+@example
+#pragma poison printf sprintf fprintf
+sprintf(some_string, "hello");
+@end example
+
+@noindent
+will produce an error.
+
+@node Macro Pitfalls,, Poisoning, Macros
@subsection Pitfalls and Subtleties of Macros
@cindex problems with macros
@cindex pitfalls of macros
diff --git a/gcc/cppexp.c b/gcc/cppexp.c
index 330236e..f037924 100644
--- a/gcc/cppexp.c
+++ b/gcc/cppexp.c
@@ -27,6 +27,7 @@ Written by Per Bothner 1994. */
#include "config.h"
#include "system.h"
#include "cpplib.h"
+#include "cpphash.h"
#ifdef MULTIBYTE_CHARS
#include <locale.h>
@@ -445,6 +446,7 @@ cpp_lex (pfile, skip_evaluation)
int paren = 0, len;
cpp_buffer *ip = CPP_BUFFER (pfile);
U_CHAR *tok;
+ HASHNODE *hp;
cpp_skip_hspace (pfile);
if (*ip->cur == '(')
@@ -469,9 +471,14 @@ cpp_lex (pfile, skip_evaluation)
goto oops;
++ip->cur;
}
- if (cpp_lookup (pfile, tok, len, -1))
- op.value = 1;
-
+ hp = cpp_lookup (pfile, tok, len, -1);
+ if (hp != NULL)
+ {
+ if (hp->type == T_POISON)
+ cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
+ else
+ op.value = 1;
+ }
}
return op;
diff --git a/gcc/cpphash.c b/gcc/cpphash.c
index c75cad1..c7da2b3 100644
--- a/gcc/cpphash.c
+++ b/gcc/cpphash.c
@@ -1020,6 +1020,13 @@ special_symbol (hp, pfile)
return;
}
+ case T_POISON:
+ cpp_error (pfile, "attempt to use poisoned `%s'.", hp->name);
+ CPP_RESERVE (pfile, 1);
+ CPP_PUTC_Q (pfile, '0');
+ CPP_NUL_TERMINATE_Q (pfile);
+ break;
+
default:
cpp_fatal (pfile, "cpplib internal error: invalid special hash type");
return;
diff --git a/gcc/cpplib.c b/gcc/cpplib.c
index 4ac7f51..e274df9 100644
--- a/gcc/cpplib.c
+++ b/gcc/cpplib.c
@@ -625,8 +625,9 @@ check_macro_name (pfile, symname, assertion)
}
/* Process a #define command.
-KEYWORD is the keyword-table entry for #define,
-or NULL for a "predefined" macro. */
+ KEYWORD is the keyword-table entry for #define,
+ or NULL for a "predefined" macro,
+ or the keyword-table entry for #pragma in the case of a #pragma poison. */
static int
do_define (pfile, keyword)
@@ -638,10 +639,16 @@ do_define (pfile, keyword)
HASHNODE *hp;
long here;
U_CHAR *macro, *buf, *end;
+ enum node_type new_type;
here = CPP_WRITTEN (pfile);
copy_rest_of_line (pfile);
+ if (keyword == NULL || keyword->type == T_DEFINE)
+ new_type = T_MACRO;
+ else
+ new_type = T_POISON;
+
/* Copy out the line so we can pop the token buffer. */
buf = pfile->token_buffer + here;
end = CPP_PWRITTEN (pfile);
@@ -663,30 +670,40 @@ do_define (pfile, 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;
/* Redefining a macro is ok if the definitions are the same. */
else if (hp->type == T_MACRO)
ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
/* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST || hp->type == T_STDC)
ok = ! CPP_OPTIONS (pfile)->done_initializing;
- /* Print the warning if it's not ok. */
- if (!ok)
+ /* Print the warning or error if it's not ok. */
+ if (ok <= 0)
{
- cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam);
+ if (hp->type == T_POISON)
+ cpp_error (pfile, "redefining poisoned `%.*s'",
+ mdef.symlen, mdef.symnam);
+ else
+ cpp_pedwarn (pfile, "`%.*s' redefined", mdef.symlen, mdef.symnam);
if (hp->type == T_MACRO)
cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file,
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;
+ if (hp->type != T_POISON)
+ {
+ /* Replace the old definition. */
+ hp->type = new_type;
+ hp->value.defn = mdef.defn;
+ }
}
else
- cpp_install (pfile, mdef.symnam, mdef.symlen, T_MACRO,
+ cpp_install (pfile, mdef.symnam, mdef.symlen, new_type,
(char *) mdef.defn, hashcode);
- if (keyword)
+ if (keyword != NULL && keyword->type == T_DEFINE)
{
if (CPP_OPTIONS (pfile)->debug_output
|| CPP_OPTIONS (pfile)->dump_macros == dump_definitions)
@@ -1425,9 +1442,14 @@ do_undef (pfile, keyword)
need to pass through all effective #undef commands. */
if (CPP_OPTIONS (pfile)->debug_output && keyword)
pass_thru_directive (name, sym_length, pfile, keyword);
- if (hp->type != T_MACRO)
- cpp_warning (pfile, "undefining `%s'", hp->name);
- delete_macro (hp);
+ if (hp->type == T_POISON)
+ cpp_error (pfile, "cannot undefine poisoned `%s'", hp->name);
+ else
+ {
+ if (hp->type != T_MACRO)
+ cpp_warning (pfile, "undefining `%s'", hp->name);
+ delete_macro (hp);
+ }
}
return 0;
@@ -1579,6 +1601,65 @@ do_pragma (pfile, keyword)
"`#pragma implementation' for `%s' appears after file is included",
fcopy);
}
+ else if (!strncmp (buf, "poison", 6))
+ {
+ /* Poison these symbols so that all subsequent usage produces an
+ error message. */
+ U_CHAR *p = buf + 6;
+ size_t plen;
+ U_CHAR *syms;
+ int writeit;
+
+ SKIP_WHITE_SPACE (p);
+ plen = strlen(p) + 1;
+
+ syms = (U_CHAR *) alloca (plen);
+ memcpy (syms, p, plen);
+
+ /* As a rule, don't include #pragma poison commands in output,
+ unless the user asks for them. */
+ writeit = (CPP_OPTIONS (pfile)->debug_output
+ || CPP_OPTIONS (pfile)->dump_macros == dump_definitions
+ || CPP_OPTIONS (pfile)->dump_macros == dump_names);
+
+ if (writeit)
+ CPP_SET_WRITTEN (pfile, here);
+ else
+ CPP_SET_WRITTEN (pfile, here-8);
+
+ if (writeit)
+ {
+ CPP_RESERVE (pfile, plen + 7);
+ CPP_PUTS_Q (pfile, "poison", 7);
+ }
+
+ while (*syms != '\0')
+ {
+ U_CHAR *end = syms;
+
+ while (is_idchar[*end])
+ end++;
+
+ if (!is_hor_space[*end] && *end != '\0')
+ {
+ cpp_error (pfile, "invalid #pragma poison directive");
+ return 1;
+ }
+
+ if (cpp_push_buffer (pfile, syms, end - syms) != NULL)
+ {
+ do_define (pfile, keyword);
+ cpp_pop_buffer (pfile);
+ }
+ if (writeit)
+ {
+ CPP_PUTC_Q (pfile, ' ');
+ CPP_PUTS_Q (pfile, syms, end - syms);
+ }
+ syms = end;
+ SKIP_WHITE_SPACE (syms);
+ }
+ }
return 0;
}
@@ -1807,6 +1888,11 @@ do_xifdef (pfile, keyword)
control_macro = (U_CHAR *) xmalloc (ident_length + 1);
bcopy (ident, control_macro, ident_length + 1);
}
+ if (hp != NULL && hp->type == T_POISON)
+ {
+ cpp_error (pfile, "attempt to use poisoned `%s'", hp->name);
+ skip = !skip;
+ }
}
else
{
diff --git a/gcc/cpplib.h b/gcc/cpplib.h
index 619645f..daff0c63 100644
--- a/gcc/cpplib.h
+++ b/gcc/cpplib.h
@@ -600,6 +600,7 @@ enum node_type {
T_MACRO, /* macro defined by `#define' */
T_DISABLED, /* macro temporarily turned off for rescan */
T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */
+ T_POISON, /* defined with `#pragma poison' */
T_UNUSED /* Used for something not defined. */
};
diff --git a/gcc/testsuite/gcc.c-torture/ChangeLog b/gcc/testsuite/gcc.c-torture/ChangeLog
index a805615..9252ab3 100644
--- a/gcc/testsuite/gcc.c-torture/ChangeLog
+++ b/gcc/testsuite/gcc.c-torture/ChangeLog
@@ -1,3 +1,8 @@
+1999-09-08 Geoffrey Keating <geoffk@cygnus.com>
+
+ * noncompile/noncompile.exp: Add poison-1.c.
+ * noncompile/poison-1.c: New file.
+
1999-09-06 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
* execute/va-arg-9.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/noncompile/noncompile.exp b/gcc/testsuite/gcc.c-torture/noncompile/noncompile.exp
index 901aca9..80a5487 100644
--- a/gcc/testsuite/gcc.c-torture/noncompile/noncompile.exp
+++ b/gcc/testsuite/gcc.c-torture/noncompile/noncompile.exp
@@ -323,3 +323,13 @@ set compiler_output ".*:6:"
set groups {passed gcc-noncompile}
postbase_with_opts $src_code $run $groups
+
+# Test poison-1.c
+prebase
+
+set src_code poison-1.c
+set compiler_output ".*c:2:.*c:4:.*c:5:.*c:7:.*c:8:.*c:9:.*c:11:.*c:12:.*c:13:.*c:14:.*c:17:.*c:20:"
+
+set groups {passed gcc-noncompile}
+
+postbase $src_code $run $groups
diff --git a/gcc/testsuite/gcc.c-torture/noncompile/poison-1.c b/gcc/testsuite/gcc.c-torture/noncompile/poison-1.c
new file mode 100644
index 0000000..1cb275e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/noncompile/poison-1.c
@@ -0,0 +1,22 @@
+#pragma poison foo
+foo
+#pragma poison foo2 foo3
+foo2
+foo3
+#pragma poison foo4 foo5
+foo4
+foo5
+#pragma poison +++
+#define foo6 123
+#pragma poison foo6
+#define foo6 345
+#define foo6 456
+#ifdef foo6
+#error hey! foo6 poisoned!
+#endif
+#if defined(foo6)
+#error no, foo6 still poisoned!
+#else
+foo6
+#endif
+#pragma poison