C++ Logo

std-proposals

Advanced search

Unify '.' and '->' operator behavior

From: J Decker <d3ck0r_at_[hidden]>
Date: Sat, 15 Feb 2020 12:34:47 -0800
I would like to see the operators '.' and '->' inspect their left hand
value's type and generate the appropriate base address from it added to C.
Since I use C++ compiler often to compile C code as a strongly typed C
compiler, this should be suggested here too.

See end for additional C++ comments
---
My proposal is to make the operator '.' consider the type of the left hand
value and behave as '.' or '->' appropriately. I could say, make '.' and
'->' equivalent, however, the desire would be to migrate to just using '.'
operators and dropping the -> altogether(sometime, in the far future,
removal/deprecation is not part of this proposal), since it would become
redundant.  Maybe it becomes a styling mechanism.
This change could be shared with C++ to make sure that c2x(and later) code
could still be compiled with C++.  C++ Does have operator overloading, but
the compiler should be able to determine if the compiler is operating on a
structure/union/(class) or a pointer to(array of) struct/union/(class);(see
end)
In C, in order for either '.' or '->' to be used, the left hand value must
be a completely defined structure or union, or a pointer to a structure or
union.  A pointer to a pointer cannot be used with either of those,
requiring some other dereference operation to get down to 1(->) or 0(.)
levels of indirection.
In either case, the compiler (GCC for instance) has the complete type
information of the left hand value, and can inspect whether the value is a
reference to a instance of a structure or union, or a pointer to a
structure or union. In the first case(instance) the address comes from the
local function address space (stack pointer) or some other memory location
computed by the compiler, in the second case, the address is given by the
value of the left hand value instead of computed by the compiler/linker,
and in both cases, the right hand value is a name of a field in a
structure/union, which is the additional offset to apply to the base
address.
The modification to the GCC C compiler (9.x) is nearly trivial.  The
modification to make '.' and '->' work the same, and to inspect the type of
the left hand value and use the 'get variable location' or 'get value of
pointer' appropriately.  Because of the requirement of a complete type
(incomplete types used with '.' or '->' generate an error in all C
compilers), every compiler must know the type and it's definition of the
left value to use the right hand name in.  (the right hand value must be a
name within a(the?) structure/union, and cannot be a computed value, ie
`ptr->(1+3)` is not valid)
This change would have no impact on existing code.  Everything that used to
compile with a C compiler would continue to compile with a C compiler.
Code written against the new standard would potentially not be compatible
with previous standards.
---
My reasoning for approaching this, or even thinking about it, was from
having taken C code which I ported to JS by replacing `TYPE name` with `val
name` and '->' to '.', and it was 95% done; other than the function
signatures.  Taking this code and bringing it back to C becomes and issue
because of the loss of -> operators; so I began considering why the implied
type information form Javascript wouldn't already exist in the C compiler,
since everything must be 'pre-typed', or defined ahead of time with its
full type information, that the compiler couldn't also do the 'smart' thing
based on the type of the value of the left hand expression.
I asked on IRC in ##C and ##programming about this idea, and someone
mentioned that the usage of '.' and '->' to programmers just learning the
language is very often a stumbling block... since to they do 'the same
thing' it's hard to understand why '.' and '->' are even different...
Eventually, you understand that they are different because you declared
either a 'static' instance of a thing ( FILE a ) vs creating a pointer to a
thing ( FILE* pa ).
There is the `*` that can dereference a pointer, so you can still use '.'
everywhere and never use `->',  `(*thing).` ; or `thing[0].` ; however that
coding style doesn't improve the ability to back-port C ported to JS back
to C.  Those mechanisms would still work, since they result in a reference
to a structure or union instance instead of the pointer to the same
instance.
Conversely, it was suggested that losing the distinction of  '.' or '->'
operators loses information about the types of a thing you are working on.
'pointer->struc.member.something->name' you just 'know' that there is a
pointer to a structure that is a single (large) of other structures that
has a pointer to a name... so you 'know' it's only 2 memory locations
you're dealing with.
---
===
C++ notes.
This would only apply for the builtin/default handlers for the '.' and '->'
operators.  Those operator overrides that have been defined by a
class/struct should still expect to do their same function.  The function
of '.' and '->' should still be overloadable with separate handlers;
although the C++ code doesn't interact at a compiler level here, and would
have no way (?) of generating, 'use base address of structure instance' or
'read value from variable and use as base address of structure'.
I've not followed the development and growth of C++ with all the safe
pointer extensions... I am far from a deep C++ guru.
Jim B
https://github.com/d3x0r ( it's pronouced Decker)

Received on 2020-02-15 14:37:41