
The PR requests an enhancement to the diagnostic issued for the use of a poisoned identifier. Currently, we show the location of the usage, but not the location which requested the poisoning, which would be helpful for the user if the decision to poison an identifier was made externally, such as in a library header. In order to output this information, we need to remember a location_t for each identifier that has been poisoned, and that data needs to be preserved as well in a PCH. One option would be to add a field to struct cpp_hashnode, but there is no convenient place to add it without increasing the size of the struct for all identifiers. Given this facility will be needed rarely, it seemed better to add a second hash map, which is handled PCH-wise the same as the current one in gcc/stringpool.cc. This hash map associates a new struct cpp_hashnode_extra with each identifier that needs one. Currently that struct only contains the new location_t, but it could be extended in the future if there is other ancillary data that may be convenient to put there for other purposes. libcpp/ChangeLog: PR preprocessor/36887 * directives.cc (do_pragma_poison): Store in the extra hash map the location from which an identifier has been poisoned. * lex.cc (identifier_diagnostics_on_lex): When issuing a diagnostic for the use of a poisoned identifier, also add a note indicating the location from which it was poisoned. * identifiers.cc (alloc_node): Convert to template function. (_cpp_init_hashtable): Handle the new extra hash map. (_cpp_destroy_hashtable): Likewise. * include/cpplib.h (struct cpp_hashnode_extra): New struct. (cpp_create_reader): Update prototype to... * init.cc (cpp_create_reader): ...accept an argument for the extra hash table and pass it to _cpp_init_hashtable. * include/symtab.h (ht_lookup): New overload for convenience. * internal.h (struct cpp_reader): Add EXTRA_HASH_TABLE member. (_cpp_init_hashtable): Adjust prototype. gcc/c-family/ChangeLog: PR preprocessor/36887 * c-opts.cc (c_common_init_options): Pass new extra hash map argument to cpp_create_reader(). gcc/ChangeLog: PR preprocessor/36887 * toplev.h (ident_hash_extra): Declare... * stringpool.cc (ident_hash_extra): ...this new global variable. (init_stringpool): Handle ident_hash_extra as well as ident_hash. (ggc_mark_stringpool): Likewise. (ggc_purge_stringpool): Likewise. (struct string_pool_data_extra): New struct. (spd2): New GC root variable. (gt_pch_save_stringpool): Use spd2 to handle ident_hash_extra, analogous to how spd is used to handle ident_hash. (gt_pch_restore_stringpool): Likewise. gcc/testsuite/ChangeLog: PR preprocessor/36887 * c-c++-common/cpp/diagnostic-poison.c: New test. * g++.dg/pch/pr36887.C: New test. * g++.dg/pch/pr36887.Hs: New test.
110 lines
3.7 KiB
C
110 lines
3.7 KiB
C
/* Hash tables.
|
|
Copyright (C) 2000-2023 Free Software Foundation, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation; either version 3, or (at your option) any
|
|
later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef LIBCPP_SYMTAB_H
|
|
#define LIBCPP_SYMTAB_H
|
|
|
|
#include "obstack.h"
|
|
|
|
#ifndef GTY
|
|
#define GTY(x) /* nothing */
|
|
#endif
|
|
|
|
/* This is what each hash table entry points to. It may be embedded
|
|
deeply within another object. */
|
|
typedef struct ht_identifier ht_identifier;
|
|
typedef struct ht_identifier *ht_identifier_ptr;
|
|
struct GTY(()) ht_identifier {
|
|
/* We know the 'len'gth of the 'str'ing; use it in the GTY markup. */
|
|
const unsigned char * GTY((string_length ("1 + %h.len"))) str;
|
|
unsigned int len;
|
|
unsigned int hash_value;
|
|
};
|
|
|
|
#define HT_LEN(NODE) ((NODE)->len)
|
|
#define HT_STR(NODE) ((NODE)->str)
|
|
|
|
typedef struct ht cpp_hash_table;
|
|
typedef struct ht_identifier *hashnode;
|
|
|
|
enum ht_lookup_option {HT_NO_INSERT = 0, HT_ALLOC};
|
|
|
|
/* An identifier hash table for cpplib and the front ends. */
|
|
struct ht
|
|
{
|
|
/* Identifiers are allocated from here. */
|
|
struct obstack stack;
|
|
|
|
hashnode *entries;
|
|
/* Call back, allocate a node. */
|
|
hashnode (*alloc_node) (cpp_hash_table *);
|
|
/* Call back, allocate something that hangs off a node like a cpp_macro.
|
|
NULL means use the usual allocator. */
|
|
void * (*alloc_subobject) (size_t);
|
|
|
|
unsigned int nslots; /* Total slots in the entries array. */
|
|
unsigned int nelements; /* Number of live elements. */
|
|
|
|
/* Link to reader, if any. For the benefit of cpplib. */
|
|
struct cpp_reader *pfile;
|
|
|
|
/* Table usage statistics. */
|
|
unsigned int searches;
|
|
unsigned int collisions;
|
|
|
|
/* Should 'entries' be freed when it is no longer needed? */
|
|
bool entries_owned;
|
|
};
|
|
|
|
/* Initialize the hashtable with 2 ^ order entries. */
|
|
extern cpp_hash_table *ht_create (unsigned int order);
|
|
|
|
/* Frees all memory associated with a hash table. */
|
|
extern void ht_destroy (cpp_hash_table *);
|
|
|
|
extern hashnode ht_lookup (cpp_hash_table *, const unsigned char *,
|
|
size_t, enum ht_lookup_option);
|
|
extern hashnode ht_lookup_with_hash (cpp_hash_table *, const unsigned char *,
|
|
size_t, unsigned int,
|
|
enum ht_lookup_option);
|
|
inline hashnode ht_lookup (cpp_hash_table *ht, const ht_identifier &id,
|
|
ht_lookup_option opt)
|
|
{
|
|
return ht_lookup_with_hash (ht, id.str, id.len, id.hash_value, opt);
|
|
}
|
|
|
|
#define HT_HASHSTEP(r, c) ((r) * 67 + ((c) - 113));
|
|
#define HT_HASHFINISH(r, len) ((r) + (len))
|
|
|
|
/* For all nodes in TABLE, make a callback. The callback takes
|
|
TABLE->PFILE, the node, and a PTR, and the callback sequence stops
|
|
if the callback returns zero. */
|
|
typedef int (*ht_cb) (struct cpp_reader *, hashnode, const void *);
|
|
extern void ht_forall (cpp_hash_table *, ht_cb, const void *);
|
|
|
|
/* For all nodes in TABLE, call the callback. If the callback returns
|
|
a nonzero value, the node is removed from the table. */
|
|
extern void ht_purge (cpp_hash_table *, ht_cb, const void *);
|
|
|
|
/* Restore the hash table. */
|
|
extern void ht_load (cpp_hash_table *ht, hashnode *entries,
|
|
unsigned int nslots, unsigned int nelements, bool own);
|
|
|
|
/* Dump allocation statistics to stderr. */
|
|
extern void ht_dump_statistics (cpp_hash_table *);
|
|
|
|
#endif /* LIBCPP_SYMTAB_H */
|