[PATCHv2 2/2] gdb/fortran: Access elements of a structure with dynamic type

Andrew Burgess andrew.burgess@embecosm.com
Thu Aug 6 15:38:37 GMT 2020


* Tom Tromey <tromey@adacore.com> [2020-08-04 13:19:39 -0600]:

> Andrew> The behaviour of this flag seems like it should be don't access the
> Andrew> target unless it's required to correctly do the task we're trying to
> Andrew> do.  But it seems like a working lazy value system should give the
> Andrew> same result.....
> 
> Andrew> .... but I'm probably missing something.
> 
> Tom> I've never been completely clear on the intended semantics of
> Tom> EVAL_AVOID_SIDE_EFFECTS.  It refrains from reading inferior memory,
> Tom> usually (?) -- but is that really needed?
> 
> Tom> One argument would be that ptype should just evaluate the expression,
> Tom> and that for 'ptype x++', well, you got what you asked for.  
> 
> Tom> A plus side is that scenarios like the one you present wouldn't be
> Tom> possible.
> 
> Tom> A minus is that things like "ptype variable" would maybe no longer show
> Tom> the declared type, but rather the dynamic type.
> 
> Tom> Speaking of, your scenario seems a lot like the C++ "set print object on"
> Tom> scenario.  There, the dynamic type is pretty much only used when
> Tom> printing.  I wonder if that makes sense for Fortran.
> 
> This issue has also come up in my work to make the Ada support in gdb
> work with DWARF debug info (rather than the "gnat encodings" which are
> normally used).  Here, many Ada types now use dynamic properties and are
> resolved to concrete types using resolve_dynamic_type.
> 
> One thing I was thinking about is that with the "do not evaluate"
> approach, there is a difference between:
> 
>     (gdb) print x
>     (gdb) ptype x
> 
> and
> 
>     (gdb) print x
>     (gdb) ptype $
> 
> Here, only the second evaluation would show the dynamic type.
> 
> This seemed unnecessarily obscure to me, and I started leaning toward
> the view that ptype ought to evaluate.  However, I found that the
> current behavior is explicitly documented:
> 
>      If ARG is an expression (*note Expressions: Expressions.), it is
>      not actually evaluated, and any side-effecting operations (such as
>      assignments or function calls) inside it do not take place.
> 
> Now, Joel pointed out to me that the Ada expression evaluator already
> does something like what is in the patch up-thread.  See "case
> OP_VAR_VALUE" in ada_evaluate_subexp:
> 
>       if (noside == EVAL_AVOID_SIDE_EFFECTS)
> [...]
> 	      /* Tagged types are a little special in the fact that the real
> 		 type is dynamic and can only be determined by inspecting the
> 		 object's tag.  This means that we need to get the object's
> 		 value first (EVAL_NORMAL) and then extract the actual object
> 		 type from its tag.
> 
> 		 Note that we cannot skip the final step where we extract
> 		 the object type from its tag, because the EVAL_NORMAL phase
> 		 results in dynamic components being resolved into fixed ones.
> 		 This can cause problems when trying to print the type
> 		 description of tagged types whose parent has a dynamic size:
> 		 We use the type name of the "_parent" component in order
> 		 to print the name of the ancestor type in the type description.
> 		 If that component had a dynamic size, the resolution into
> 		 a fixed type would result in the loss of that type name,
> 		 thus preventing us from printing the name of the ancestor
> 		 type in the type description.  */
> 	      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
> 
> So, this is a bit of a funny situation, where on the one hand the code
> respects the "avoid side effects" rule (assuming the target isn't using
> memory-mapped I/O that is overlaid by some Ada data structure ;), while
> also avoiding the spirit of the thing ("not actually evaluated" -- here
> in some cases it is).
> 
> My understanding is that this particular tweak came from a user request.
> You can see here that it was definitely intentional:
> 
>     https://sourceware.org/pipermail/gdb-patches/2008-September/060193.html
> 
> 
> One idea that came up on irc was to use a flag to ptype to select the
> mode.  I think that would be fine -- though it still leaves the question
> of which mode ought to be the default; and the question of whether we
> ought to remove cases like the above from the code.
> 
> Perhaps a related question (mentioned above as well) is whether "set
> print object on" ought to be ignored in favor of this flag.
> 
> Maybe one final weirdness is that if ptype evaluates, since the value
> isn't entered into the value history, there's no way to refer to it
> again without re-evaluating.
> 
> 
> I am not completely certain but my current proposal would be:
> 
> 1. ptype should evaluate its argument by default, and should show the
>    runtime type.  I'm not concerned about the value history thing,
>    because I think I tend not to use ptype on side-effecting expressions
>    anyhow.
> 
> 2. We should add a flag to ptype, say "/s" (for "static type"?), to have
>    it not try to evaluate, but instead print the static type.
> 
> 3. We should remove any special cases for EVAL_AVOID_SIDE_EFFECTS, since
>    presumably they won't be needed any more.
> 
> 4. For "ptype/s $", I guess we will need to have a back-link from the
>    resolved type to the dynamic type.  (FWIW I have a patch I wrote to
>    experiment with this...)
> 
> 5. We should ignore the "set print object on" problem entirely.  For
>    ptype/s, we should differentiate between "runtime type" and "concrete
>    instance of dynamic type", and only try to use back-links for the
>    latter.
> 
> 
> What do you think?

FWIW, I think this would be a good direction to move in.

Thanks,
Andrew


More information about the Gdb-patches mailing list