Skip to content

Commit 6fbf0ce

Browse files
author
nathan
committed
PR c++/80891 (#1,#5)
* cp-tree.h (lookup_maybe_add): Add DEDUPING argument. * name-lookup.c (name_lookup): Add deduping field. (name_lookup::preserve_state, name_lookup::restore_state): Deal with deduping. (name_lookup::add_overload): New. (name_lookup::add_value, name_lookup::add_fns): Call add_overload. (name_lookup::search_adl): Set deduping. Don't unmark here. * pt.c (most_specialized_instantiation): Revert previous change, Assert not given duplicates. * tree.c (lookup_mark): Just mark the underlying decls. (lookup_maybe_add): Dedup using marked decls. PR c++/80891 (#5) * g++.dg/lookup/pr80891-5.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@248578 138bc75d-0d04-0410-961f-82ee72b054a4
1 parent 18eaba0 commit 6fbf0ce

File tree

7 files changed

+200
-105
lines changed

7 files changed

+200
-105
lines changed

gcc/cp/ChangeLog

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
2017-05-29 Nathan Sidwell <[email protected]>
22

3+
PR c++/80891 (#1,#5)
4+
* cp-tree.h (lookup_maybe_add): Add DEDUPING argument.
5+
* name-lookup.c (name_lookup): Add deduping field.
6+
(name_lookup::preserve_state, name_lookup::restore_state): Deal
7+
with deduping.
8+
(name_lookup::add_overload): New.
9+
(name_lookup::add_value, name_lookup::add_fns): Call add_overload.
10+
(name_lookup::search_adl): Set deduping. Don't unmark here.
11+
* pt.c (most_specialized_instantiation): Revert previous change,
12+
Assert not given duplicates.
13+
* tree.c (lookup_mark): Just mark the underlying decls.
14+
(lookup_maybe_add): Dedup using marked decls.
15+
316
PR c++/80891 (#4)
417
* ptree.c (cxx_print_xnode): Show internal OVERLOAD structure.
518
* tree.c (ovl_insert, ovl_iterator_remove_node): Fix copying assert.

gcc/cp/cp-tree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6916,7 +6916,8 @@ extern tree ovl_insert (tree fn, tree maybe_ovl,
69166916
extern tree ovl_skip_hidden (tree) ATTRIBUTE_PURE;
69176917
extern void lookup_mark (tree lookup, bool val);
69186918
extern tree lookup_add (tree fns, tree lookup);
6919-
extern tree lookup_maybe_add (tree fns, tree lookup);
6919+
extern tree lookup_maybe_add (tree fns, tree lookup,
6920+
bool deduping);
69206921
extern void lookup_keep (tree lookup, bool keep);
69216922
extern int is_overloaded_fn (tree) ATTRIBUTE_PURE;
69226923
extern bool really_overloaded_fn (tree) ATTRIBUTE_PURE;

gcc/cp/name-lookup.c

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ static void set_identifier_type_value_with_scope (tree id, tree decl,
4848
#define MAYBE_STAT_DECL(N) (STAT_HACK_P (N) ? STAT_DECL (N) : N)
4949
#define MAYBE_STAT_TYPE(N) (STAT_HACK_P (N) ? STAT_TYPE (N) : NULL_TREE)
5050

51-
static tree stat_hack (tree decl = NULL_TREE, tree type = NULL_TREE)
51+
/* Create a STAT_HACK node with DECL as the value binding and TYPE as
52+
the type binding. */
53+
54+
static tree
55+
stat_hack (tree decl = NULL_TREE, tree type = NULL_TREE)
5256
{
5357
tree result = make_node (OVERLOAD);
5458

@@ -179,6 +183,8 @@ struct name_lookup
179183
tree value; /* A (possibly ambiguous) set of things found. */
180184
tree type; /* A type that has been found. */
181185
int flags; /* Lookup flags. */
186+
bool deduping; /* Full deduping is needed because using declarations
187+
are in play. */
182188
vec<tree, va_heap, vl_embed> *scopes;
183189
name_lookup *previous; /* Previously active lookup. */
184190

@@ -191,7 +197,7 @@ struct name_lookup
191197
public:
192198
name_lookup (tree n, int f = 0)
193199
: name (n), value (NULL_TREE), type (NULL_TREE), flags (f),
194-
scopes (NULL), previous (NULL)
200+
deduping (false), scopes (NULL), previous (NULL)
195201
{
196202
preserve_state ();
197203
}
@@ -235,6 +241,7 @@ struct name_lookup
235241

236242
private:
237243
static tree ambiguous (tree thing, tree current);
244+
void add_overload (tree fns);
238245
void add_value (tree new_val);
239246
void add_type (tree new_type);
240247
bool process_binding (tree val_bind, tree type_bind);
@@ -321,7 +328,8 @@ name_lookup::preserve_state ()
321328
}
322329

323330
/* Unmark the outer partial lookup. */
324-
lookup_mark (previous->value, false);
331+
if (previous->deduping)
332+
lookup_mark (previous->value, false);
325333
}
326334
else
327335
scopes = shared_scopes;
@@ -333,6 +341,9 @@ name_lookup::preserve_state ()
333341
void
334342
name_lookup::restore_state ()
335343
{
344+
if (deduping)
345+
lookup_mark (value, false);
346+
336347
/* Unmark and empty this lookup's scope stack. */
337348
for (unsigned ix = vec_safe_length (scopes); ix--;)
338349
{
@@ -371,7 +382,8 @@ name_lookup::restore_state ()
371382
}
372383

373384
/* Remark the outer partial lookup. */
374-
lookup_mark (previous->value, true);
385+
if (previous->deduping)
386+
lookup_mark (previous->value, true);
375387
}
376388
else
377389
shared_scopes = scopes;
@@ -415,23 +427,53 @@ name_lookup::ambiguous (tree thing, tree current)
415427
return current;
416428
}
417429

430+
/* FNS is a new overload set to add to the exising set. */
431+
432+
void
433+
name_lookup::add_overload (tree fns)
434+
{
435+
if (!deduping && TREE_CODE (fns) == OVERLOAD)
436+
{
437+
tree probe = fns;
438+
if (flags & LOOKUP_HIDDEN)
439+
probe = ovl_skip_hidden (probe);
440+
if (probe && TREE_CODE (probe) == OVERLOAD && OVL_USING_P (probe))
441+
{
442+
/* We're about to add something found by a using
443+
declaration, so need to engage deduping mode. */
444+
lookup_mark (value, true);
445+
deduping = true;
446+
}
447+
}
448+
449+
value = lookup_maybe_add (fns, value, deduping);
450+
}
451+
418452
/* Add a NEW_VAL, a found value binding into the current value binding. */
419453

420454
void
421455
name_lookup::add_value (tree new_val)
422456
{
423-
if (!value)
457+
if (OVL_P (new_val) && (!value || OVL_P (value)))
458+
add_overload (new_val);
459+
else if (!value)
424460
value = new_val;
425461
else if (value == new_val)
426462
;
427463
else if ((TREE_CODE (value) == TYPE_DECL
428464
&& TREE_CODE (new_val) == TYPE_DECL
429465
&& same_type_p (TREE_TYPE (value), TREE_TYPE (new_val))))
430466
;
431-
else if (OVL_P (value) && OVL_P (new_val))
432-
value = lookup_add (new_val, value);
433467
else
434-
value = ambiguous (new_val, value);
468+
{
469+
if (deduping)
470+
{
471+
/* Disengage deduping mode. */
472+
lookup_mark (value, false);
473+
deduping = false;
474+
}
475+
value = ambiguous (new_val, value);
476+
}
435477
}
436478

437479
/* Add a NEW_TYPE, a found type binding into the current type binding. */
@@ -703,8 +745,7 @@ name_lookup::add_fns (tree fns)
703745
else if (!DECL_DECLARES_FUNCTION_P (fns))
704746
return;
705747

706-
/* Only add those that aren't already there. */
707-
value = lookup_maybe_add (fns, value);
748+
add_overload (fns);
708749
}
709750

710751
/* Add functions of a namespace to the lookup structure. */
@@ -1004,7 +1045,11 @@ name_lookup::adl_template_arg (tree arg)
10041045
tree
10051046
name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
10061047
{
1007-
lookup_mark (fns, true);
1048+
if (fns)
1049+
{
1050+
deduping = true;
1051+
lookup_mark (fns, true);
1052+
}
10081053
value = fns;
10091054

10101055
unsigned ix;
@@ -1019,7 +1064,6 @@ name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
10191064
adl_expr (arg);
10201065

10211066
fns = value;
1022-
lookup_mark (fns, false);
10231067

10241068
return fns;
10251069
}

gcc/cp/pt.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21728,32 +21728,32 @@ most_specialized_instantiation (tree templates)
2172821728

2172921729
champ = templates;
2173021730
for (fn = TREE_CHAIN (templates); fn; fn = TREE_CHAIN (fn))
21731-
if (TREE_VALUE (champ) != TREE_VALUE (fn))
21732-
{
21733-
int fate = more_specialized_inst (TREE_VALUE (champ), TREE_VALUE (fn));
21734-
if (fate == -1)
21731+
{
21732+
gcc_assert (TREE_VALUE (champ) != TREE_VALUE (fn));
21733+
int fate = more_specialized_inst (TREE_VALUE (champ), TREE_VALUE (fn));
21734+
if (fate == -1)
21735+
champ = fn;
21736+
else if (!fate)
21737+
{
21738+
/* Equally specialized, move to next function. If there
21739+
is no next function, nothing's most specialized. */
21740+
fn = TREE_CHAIN (fn);
2173521741
champ = fn;
21736-
else if (!fate)
21737-
{
21738-
/* Equally specialized, move to next function. If there
21739-
is no next function, nothing's most specialized. */
21740-
fn = TREE_CHAIN (fn);
21741-
champ = fn;
21742-
if (!fn)
21743-
break;
21744-
}
21745-
}
21742+
if (!fn)
21743+
break;
21744+
}
21745+
}
2174621746

2174721747
if (champ)
2174821748
/* Now verify that champ is better than everything earlier in the
2174921749
instantiation list. */
21750-
for (fn = templates; fn != champ; fn = TREE_CHAIN (fn))
21751-
if (TREE_VALUE (champ) != TREE_VALUE (fn)
21752-
&& more_specialized_inst (TREE_VALUE (champ), TREE_VALUE (fn)) != 1)
21753-
{
21754-
champ = NULL_TREE;
21755-
break;
21756-
}
21750+
for (fn = templates; fn != champ; fn = TREE_CHAIN (fn)) {
21751+
if (more_specialized_inst (TREE_VALUE (champ), TREE_VALUE (fn)) != 1)
21752+
{
21753+
champ = NULL_TREE;
21754+
break;
21755+
}
21756+
}
2175721757

2175821758
processing_template_decl--;
2175921759

gcc/cp/tree.c

Lines changed: 35 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,21 +2293,10 @@ ovl_iterator::remove_node (tree overload, tree node)
22932293
void
22942294
lookup_mark (tree ovl, bool val)
22952295
{
2296-
/* For every node that is a lookup, mark the thing it points to. */
2297-
for (; ovl && TREE_CODE (ovl) == OVERLOAD && OVL_LOOKUP_P (ovl);
2298-
ovl = OVL_CHAIN (ovl))
2299-
{
2300-
tree targ = OVL_FUNCTION (ovl);
2301-
gcc_checking_assert (LOOKUP_SEEN_P (targ) != val);
2302-
LOOKUP_SEEN_P (targ) = val;
2303-
}
2304-
2305-
if (ovl && (TREE_CODE (ovl) == OVERLOAD ||
2306-
TREE_CODE (ovl) == FUNCTION_DECL))
2296+
for (lkp_iterator iter (ovl); iter; ++iter)
23072297
{
2308-
/* Mark the overload itsef. */
2309-
gcc_checking_assert (LOOKUP_SEEN_P (ovl) != val);
2310-
LOOKUP_SEEN_P (ovl) = val;
2298+
gcc_checking_assert (LOOKUP_SEEN_P (*iter) != val);
2299+
LOOKUP_SEEN_P (*iter) = val;
23112300
}
23122301
}
23132302

@@ -2327,73 +2316,48 @@ lookup_add (tree fns, tree lookup)
23272316
return lookup;
23282317
}
23292318

2330-
/* FNS is a new overload set, add it to LOOKUP, if it is not already
2331-
present there. */
2319+
/* FNS is a new overload set, add them to LOOKUP, if they are not
2320+
already present there. */
23322321

23332322
tree
2334-
lookup_maybe_add (tree fns, tree lookup)
2323+
lookup_maybe_add (tree fns, tree lookup, bool deduping)
23352324
{
2336-
if (LOOKUP_SEEN_P (fns))
2337-
return lookup;
2338-
2339-
if (lookup && TREE_CODE (fns) == OVERLOAD)
2340-
{
2341-
/* Determine if we already have some part of this overload in
2342-
the overload set. If so fix things up so we only have the
2343-
overload set once. */
2344-
tree marked = NULL_TREE;
2325+
if (deduping)
2326+
for (tree next, probe = fns; probe; probe = next)
2327+
{
2328+
tree fn = probe;
2329+
next = NULL_TREE;
23452330

2346-
for (tree probe = fns; probe; probe = OVL_CHAIN (probe))
2347-
if (LOOKUP_SEEN_P (probe))
2331+
if (TREE_CODE (probe) == OVERLOAD)
23482332
{
2349-
marked = probe;
2350-
break;
2333+
fn = OVL_FUNCTION (probe);
2334+
next = OVL_CHAIN (probe);
23512335
}
2352-
else if (TREE_CODE (probe) != OVERLOAD)
2353-
break;
23542336

2355-
if (marked)
2356-
{
2357-
/* The tail of this overload is already in the lookup
2358-
set. Stitch out the tail case, which might involve
2359-
copying. */
2360-
bool rewrite = false;
2361-
2362-
LOOKUP_SEEN_P (marked) = false;
2363-
for (tree *prev = &lookup, probe = *prev;
2364-
; prev = &OVL_CHAIN (probe), probe = *prev)
2365-
{
2366-
if (probe == marked)
2367-
{
2368-
*prev = NULL_TREE;
2369-
break;
2370-
}
2371-
gcc_checking_assert (OVL_LOOKUP_P (probe));
2372-
if (marked == OVL_FUNCTION (probe))
2373-
{
2374-
*prev = OVL_CHAIN (probe);
2375-
break;
2376-
}
2337+
if (!LOOKUP_SEEN_P (fn))
2338+
LOOKUP_SEEN_P (fn) = true;
2339+
else
2340+
{
2341+
/* This function was already seen. Insert all the
2342+
predecessors onto the lookup. */
2343+
for (; fns != probe; fns = OVL_CHAIN (fns))
2344+
{
2345+
lookup = lookup_add (OVL_FUNCTION (fns), lookup);
2346+
/* Propagate OVL_USING, but OVL_HIDDEN doesn't matter. */
2347+
if (OVL_USING_P (fns))
2348+
OVL_USING_P (lookup) = true;
2349+
}
23772350

2378-
/* If we're in a used part of the lookup set, copy the
2379-
node, so as to not disturb stored uses. */
2380-
gcc_checking_assert (!rewrite || OVL_USED_P (probe));
2381-
if (OVL_USED_P (probe))
2382-
{
2383-
rewrite = true;
2384-
probe = ovl_copy (probe);
2385-
OVL_LOOKUP_P (probe) = true;
2386-
*prev = probe;
2387-
}
2388-
}
2389-
}
2390-
}
2351+
/* And now skip this function. */
2352+
fns = next;
2353+
}
2354+
}
23912355

2392-
/* Finally mark the new overload and prepend it to the current
2393-
lookup. */
2394-
LOOKUP_SEEN_P (fns) = true;
2356+
if (fns)
2357+
/* We ended in a set of new functions. Add them all in one go. */
2358+
lookup = lookup_add (fns, lookup);
23952359

2396-
return lookup_add (fns, lookup);
2360+
return lookup;
23972361
}
23982362

23992363
/* Regular overload OVL is part of a kept lookup. Mark the nodes on

gcc/testsuite/ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2017-05-29 Nathan Sidwell <[email protected]>
2+
3+
PR c++/80891 (#5)
4+
* g++.dg/lookup/pr80891-5.C: New.
5+
16
2017-05-29 Jerry DeLisle <[email protected]>
27

38
PR libgfortran/53029

0 commit comments

Comments
 (0)