On Thu, Jul 12, 2018 at 8:02 PM Pedro Alves <pal...@redhat.com> wrote:
>
> On 07/12/2018 05:17 PM, Richard Sandiford wrote:
> > Pedro Alves <pal...@redhat.com> writes:
>
> >> (an
> >>> alternative to pointers is to return a struct with the wide int result
> >>> and the overflow flag),
> >>
> >> +1.  I've been pushing GDB in that direction whenever possible.
> >
> > I agree that can sometimes be better.  I guess it depends on the
> > context.  If a function returns a bool and some other data that has no
> > obvious "failure" value, it can be easier to write chained conditions if
> > the function returns the bool and provides the other data via an output
> > parameter.
>
> I agree it depends on context, though your example sounds like a
> case for std::optional<T>.  (We have gdb::optional<T> in gdb, since
> std::optional is C++17 and gdb requires C++11.  LLVM has a similar
> type, I believe.)
>
> >
> >>> but ...
> >>>
> >>>> +int *elt = &amp;array[i];  // OK
> >>>> +int &amp;elt = array[i];   // Please avoid
> >>>
> >>> ... this seems unnecessary. If the function is so long that the fact
> >>> elt is a reference can easily get lost, the problem is the length of
> >>> the function, not the use of a reference.
> >>>
> >>
> >> +1000.  This seems really unnecessary.  References have the advantage
> >> of implicit never-null semantics, for instance.
> >
> > The nonnullness is there either way in the above example though.
> >
> > I don't feel as strongly about the non-const-reference variables, but for:
> >
> >      int &elt = array[i];
> >      ...
> >      elt = 1;
> >
> > it can be easy to misread that "elt = 1" is changing more than just
> > a local variable.
>
> I think that might be just the case for people who haven't used
> references before, and once you get some exposure, the effect
> goes away.  See examples below.

Agreed.

>
> >
> > I take Jonathan's point that it shouldn't be much of a problem if
> > functions are a reasonable size, but we've not tended to be very
> > good at keeping function sizes down.  I guess part of the problem
> > is that even functions that start off small tend to grow over time.
> >
> > We have been better at enforcing more specific rules like the ones
> > in the patch.  And that's easier to do because a patch either adds
> > references or it doesn't.  It's harder to force (or remember to force)
> > someone to split up a function if they're adding 5 lines to one that is
> > already 20 lines long.  Then for the next person it's 25 lines long, etc.
> >
>
> > Also, the "int *elt" approach copes with cases in which "elt" might
> > have to be redirected later, so we're going to need to use it in some
> > cases.
>
> Sure, if you need to reseat, certainly use a pointer.  That actually
> highlights an advantage of references -- the fact that you are sure
> nothing could reseat it.  With a local pointer, you need to be mindful
> of that.  "Does this loop change the pointer?"  Etc.  If the semantics
> of the function call for having a variable that is not meant to be
> reseated, why not allow expressing it with a reference.
> "Write what you mean."  Of course, just like all code, there's going
> to be a judgment call.
>
> A place where references frequently appear is in C++11 range-for loops.
> Like, random example from gdb's codebase:
>
>  for (const symbol_search &p : symbols)
>
> GCC doesn't yet require C++11, but it should be a matter
> of time, one would hope.
>
> Other places references appear often is in coming up with
> an alias to avoid repeating long expressions, like
> for example (again from gdb):
>
>       auto &vec = objfile->per_bfd->demangled_hash_languages;
>       auto it = std::lower_bound (vec.begin (), vec.end (),
>                                   MSYMBOL_LANGUAGE (sym));
>       if (it == vec.end () || *it != MSYMBOL_LANGUAGE (sym))
>         vec.insert (it, MSYMBOL_LANGUAGE (sym));
>
> I don't think the fact that "vec" is a reference here confuses
> anyone.
>
> That was literally a random sample (grepped for "&[a-z]* = ") so
> I ended up picking one with C++11 "auto", but here's another
> random example, spelling out the type name, similarly using
> a reference as a shorthand alias:
>
>   osdata_item &item = osdata->items.back ();
>
>   item.columns.emplace_back (std::move (data->property_name),
>                              std::string (body_text));
>
> > It's then a question of whether "int &elt" is useful enough that
> > it's worth accepting it too, and having a mixture of styles in the codebase.
> I don't see it as a mixture of styles, as I don't see
> pointers and references the exact same thing, but rather
> see references as another tool in the box.

Agreed, agreed, agreed :).

Seriously folks, I really think we should concentrate on cleaning up
GCC, and making it more readable, not nitpicking over style issues.
Look at our wide int implementation for instance-- it adheres
perfectly to our coding guidelines, and yet it's a mess mess to read
(*).

(*) I'm not singling out wide int because Richard worked on it.  I
believe it was Zadeck after all.  It's just one of many examples
(ahem, vec.h, tree-vrp.c, etc etc).

Reply via email to