On Sun, Jan 22, 2017 at 6:06 PM, Alexandre Oliva <[email protected]> wrote:
> On Jan 13, 2017, Jason Merrill <[email protected]> wrote:
>
>> On 09/23/2016 08:41 PM, Alexandre Oliva wrote:
>>> +static tree global_friend_list;
>
>> This should be a hash_set rather than a TREE_LIST.
>
> You sure? At least in the libcc1 use scenario, this is going to have a
> single entry. I didn't even have to make it a list, but I made it one
> because, well, I could :-) A hash_set seems excessive, unless you
> envision other uses for it.
Well, in general TREE_LISTs are discouraged nowadays in favor of
hash_sets or VECs. If it's a single entry, putting it there alone is
fine too.
>>> + // FIXME: we need a more space-efficient representation for
>>> + // oracle_looked_up.
>
>> A hash_set would work for that, too.
>
> I was hoping for an unused bit in IDENTIFIERs, but I guess that will do.
> I'm a bit concerned about the performance impact of this in all name
> lookups, though. Just computing the hash for every lookup seems
> excessive, compared with testing a bit. Unless... I guess making it a
> hash_set*, NULL unless there is an Oracle, would alleviate this concern,
> making it cost only when it's in use.
Sounds good.
>>> +/* Exported wrapper for cp_literal_operator_id. */
>>> +
>>> +tree
>>> +ansi_litopname (const char *name)
>>> +{
>>> + return cp_literal_operator_id (name);
>>> +}
>
>> Why not export cp_literal_operator_id itself?
>
> My sense of aesthetics demanded a uniform set of exported names along
> with ansi_opname and ansi_assopname ;-)
Heh. But I'd prefer to unify them in the other direction; use of
"ansi" is obsolete.
>>> + If the newly-created namespace is to be an inline namespace, after
>>> + push_namespace, get the nested namespace decl with
>>> + get_current_binding_level, pop back to the enclosing namespace,
>>> + call using_namespace with INLINE_P, and then push to the inline
>>> + namespace again. */
>
>> This seems like unnecessary contortions to expect of the caller
>> (i.e. GDB). Let's add a new front end function to handle this.
>
> Heh, it's really nothing compared with some other contortions required
> to navigate binding levels, e.g. to reenter a function scope.
>
> I didn't want to add redundant functionality to the libcc1 API, and we'd
> need the ability to separate the introduction or reentry in a namespace,
> from a using directive with attribute strong. And since inline
> namespaces use the same implementation as that, I figured it made sense
> to use the same interface for both.
> Besides, push_namespace is called a lot more often than using_namespace,
> so it makes sense to keep it simpler, and leave the extra parameter for
> the less common operation.
>
> Another argument to keep things as they are is that the inline-ness of a
> namespace is not a property related with entering the namespace, but
> rather with how names from it are brought into the other namespace.
Well, it's a property of the namespace. But I guess I won't insist on this.
>>> + As a general rule, before we can declare or define any local name
>>> + with a discriminator, we have to at least declare any other
>>> + occurrences of the same name in the same enclosing entity with
>>> + lower or absent discriminator.
>
>> This seems unfortunate, wouldn't it be better to allow the plugin to
>> specify the discriminator directly?
>
> That would have required a major reworking of the internal handling of
> such discriminators, and it didn't seem worth the effort and risk of
> pushback, considering that libcc1 already requires all occurrences of a
> name to be defined at once.
Fair enough.
>>> + Just entering the scope of the class containing member function f
>>> + reactivates the names of its members, including the class name
>>> + itself. */
>
>> Does it reactivate the names of other declarations in scope in the
>> enclosing function, e.g. static local variables?
>
> My understanding is that anything local needs explicit reactivation when
> reentering a function scope. That makes sense and is helpful for us,
> given that a local scope is not always a single scope; unlike namespace
> and class scopes, there could be multiple scopes within a function
> scope, and each would have a different set of active names. The client
> has to select the active names upon function reentry.
OK.
>>> +/* Pop the namespace last entered with push_namespace, or class last
>>> + entered with push_class, or function last entered with
>>> + push_function, restoring the binding level in effect before the
>>> + matching push_* call. */
>>> +
>>> +GCC_METHOD0 (int /* bool */, pop_namespace)
>
>> This should have a different name, perhaps pop_last_entered_scope?
>
> It was introduced very early on, long before the need for exposing
> function scopes was realized and implemented. GDB (branch) already had
> plenty of code using this primitive, so I didn't want to rename it, but
> if you insist in such spelling changes, I won't mind, and I guess GDB
> folks won't even. It's not too late yet ;-)
Please.
>>> +/* Return the NAMESPACE_DECL, TYPE_DECL or FUNCTION_DECL of the
>>> + binding level that would be popped by pop_namespace. */
>>> +
>>> +GCC_METHOD0 (gcc_decl, get_current_binding_level)
>
>> Perhaps get_current_binding_level_decl?
>
> Ditto, except I'm not sure GDB already uses this one, so it's probably a
> much easier sell.
Please.
>>> + The TARGET decl names the qualifying scope (foo:: above) and the
>>> + identifier (bar), but that does not mean that only TARGET will be
>>> + brought into the current scope: all bindings of TARGET's identifier
>>> + in the qualifying scope will be brought in.
>
>> This seems wrong; for namespace-scope using-declarations, only the
>> declarations in scope at the point of the using-declaration are
>> imported. Since DWARF represents each imported declaration
>> individually, I would think that we would want the plugin to import
>> them one at a time.
>
> What you say is true, but GCC doesn't offer functionality for that
> AFAICT, and the caller can always arrange for only the bindings that
> should be brought in by the using declarations to be defined at the time
> the using declaration is introduced, so I left it at that so as to
> minimize the changes to GCC proper.
Fair enough, but then why pass a decl? Passing scope and identifier
would seem cleaner if that's what you mean.
>>> For operator functions, set GCC_CP_FLAG_SPECIAL_FUNCTION in
>>> + SYM_KIND, in addition to any other applicable flags, and pass as
>>> + NAME a string starting with the two-character mangling for operator
>>> + name
>
>> Perhaps the compiler side should handle this transparently?
>
> Sorry, I don't understand what you're suggesting. Can you please
> elaborate?
I mean have the compiler recognize that the name is magic and infer
that it's a special function.
>>> +/* Supply the ADDRESS of one of the multiple clones of constructor or
>>> + destructor CDTOR. The clone is selected using the following
>>> + name mangling conventions:
>
>> The comment doesn't say what argument NAME should be.
>
> Fixed thusly:
>
> The clone is The clone is specified by NAME, using the following name
> mangling conventions
Without the duplicate "The clone is", I hope? :)
>>> + The [CD]4 manglings (and symbol definitions) are non-standard, but
>>> + GCC uses them in some cases: rather than assuming they are
>>> + in-charge or not-in-charge, they test the implicit argument that
>>> + the others ignore to tell how to behave. These are defined in very
>>> + rare cases of virtual inheritance and cdtor prototypes. */
>
>> These are used instead of cloning when we can't just use aliases.
>
> You mean this should go in instead of 'These are defined in ...', right?
Yes.
>>> +GCC_METHOD5 (gcc_type, new_template_typename_parm,
>
>> s/typename/type/
>
> The purpose behind this choice was to avoid the unwanted "template type"
> grouping. I figured "typename" would convey the correct concept, even
> before the "new_template_*_parm" pattern could be formed. Hmm... I
> wonder if I should have made it new_*_template_parm instead...
Sure, that would be even better.
>>> +GCC_METHOD2 (gcc_type, new_dependent_typespec,
>
>> "typespec" usually means type-specifier.
>
> Oops ;-)
>
>> How about new_dependent_type_template_id?
>
> Or new_dependent[_template]_specialization? I think I'd rather use the
> term 'specialization' because I've used it in other primitives and in
> the documentation, whereas it would be the only use of 'id'.
Well, a template-id is the syntactic term for combining a template
name and some template arguments, which seems like what this function
is doing. A template-id names a specialization, but isn't quite the
same.
>>> +GCC_METHOD5 (gcc_expr, new_dependent_value_expr,
>
>> I don't think you need "value" here. Nor in the other *_value_expr names.
>
> That was to distinguish it from type expressions. I was concerned it
> could be misused to construct
I don't know what you mean by "type expressions".
>>> +/* Build a gcc_expr that denotes the conversion of an expression list
>>> + VALUES to TYPE, with ("tl") or without ("cv") braces, or a braced
>>> + initializer list of unspecified type (e.g., a component of another
>>> + braced initializer list; pass "il" for CONV_OP, and NULL for
>>> + TYPE). */
>
>>> +GCC_METHOD3 (gcc_expr, values_expr,
>
>> Hmm, it seems like you're conflating two things here: the expressions,
>> and the conversions. I'd suggest functional_cast_expr, but handling a
>> plain braced-init-list through the same interface is surprising.
>
> The reason they ended up in the same spot is that I grouped the various
> kinds of expressions according to the meta-types of the operands, so all
> of the expressions that took a list of expressions (values), with or
> without a type, ended up in the same API entry point.
Hmm, OK. Maybe expression_list_expr?
>>> +GCC_METHOD4 (gcc_expr, alloc_expr,
>
>> new_expr?
>
> new_ would be confusing, for it was used as a prefix for entry points
> that introduce new classes, new fields, etc.
>
>> This leads me to notice that some of the entry points start with
>> "new_", some start with "build_", and some have no prefix. Is this
>> intentional?
>
> The 'build_' ones were inherited from the libcc1 API for C. The major
> API departure from C's build_decl made me rename it to new_decl, and
> then I followed the new_ pattern when introducing other names. IOW, no
> strong reasons, just ones that offer insights into the development
> history of the API. I guess we could change them all to build_, and use
> new_ for alloc_expr, but I'm hesitant, because of the inconvenience this
> might cause to the GDB folks that may have already got used to this
> admittedly inconsistent convention.
Better to fix an inconsistent API now than leave it to confuse future
developers, I would think.
Jason