public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* C++: Anticipated declaration of builtins
@ 2003-05-25 22:13 gcc
  0 siblings, 0 replies; 5+ messages in thread
From: gcc @ 2003-05-25 22:13 UTC (permalink / raw)
  To: gcc; +Cc: jason


Hi,

Currently, anticipated declarations of builtin functions whose names do
not begin with underscores are done as follows:

  * a pre-declaration at the standard namespace scope std::
  * a pre-declaration at the global scope.

The actual code reads:

  /* All builtins that don't begin with an '_' should additionally
     go in the 'std' namespace.  */
  if (name[0] != '_')
    {
      push_namespace (std_identifier);
      builtin_function_1 (name, type, std_node, code, class, libname, attrs);
      pop_namespace ();
    }

  return builtin_function_1 (name, type, NULL_TREE, code,
			     class, libname, attrs);

I have two questions:

  1) Shouldn't we pre-declare the function at global scope, then do a
     using-declaration at the standard scope?

  2) Why doesn't the second call to builtin_function_1() specify
     global_namespace instead of NULL_TREE?  I think specifying
     global_namespace should be the way to go.  What I am missing?

Thanks,

-- Gaby

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: C++: Anticipated declaration of builtins.
  2003-05-26  2:44   ` Roger Sayle
@ 2003-05-26  4:26     ` Gabriel Dos Reis
  0 siblings, 0 replies; 5+ messages in thread
From: Gabriel Dos Reis @ 2003-05-26  4:26 UTC (permalink / raw)
  To: Roger Sayle; +Cc: jason, gcc

Roger Sayle <roger@eyesopen.com> writes:

| > | > 1) Shouldn't we pre-declare the function at global scope, then
| > | >    do a using-declaration at the standard scope?
| > |
| > | The problem here is that they need to be treated as two independent
| > | pre-declarations.  If a prototype or declaration is given for
| > | one, it does not automatically anticipate/declare the other.  Hence,
| > | we require separate DECLs with independent DECL_ANTICIPATED flags.
| >
| > Hmm, why do we need to have two independent declarations for the same
| > builtin?
| 
| Because of the way that duplicate_decls overwrites the original
| decl when redeclaring a declaration, such as when an anticipated
| built-in function is prototyped.
| 
| If a single decl was shared between ::strlen and std::strlen, then
| the destructive modification of the first decl would side-effect
| the second.  I'd hoped this was clear from my reference to the
| DECL_ANTICIPATED flag.  Setting it to true for the decl in the
| first namespace should not automatically set the DECL_ANTICIPATED
| field of the pre-declaration in the second namespace.

I understood your original statement with the reference to
DECL_ANTICIPATED flag.  What I still do not understand is why one
would want to keep ::strlen separate from std::strlen for example.
The point I'm trying to understand is why we should not have both
behave as if

    <antitpated declaration for strlen>
     namesapce std
     {
       using ::strlen;
     }

(note that, that is, for example, the way "C" functions are malassed by
the C++ library if #include <xxx.h> -- although we would have preferred
the other way around)

My question is why do we want to mess up with duplicate declares in
situation like this

   using namespace std;

    // use strlen;

if we keep two separate declarations then we run into ambiguous use,
which should not be the case.

| I believe/hope that the DECLs themselves take up very little space,
| they don't contain any RTL, they share their types and other major
| fields.  So the DECL itself just acts a place holder, associating
| the namespace/identifier, with its types, flags and attributes.

At this point, I'm more concerned with name lookup than with RTL stuff.

| > If we have the same builtin declared twice with possibly two
| > incompatible declarations, it occurs to me that we're calling for
| > trouble.  Is there any case where that could be useful?
| 
| The DECL_BUILT_IN and similar attributes are only preserved if
| the declarations are compatible.  If the type of the redeclaration
| doesn't match the anticipated/pre-declared type, the old decl is
| just completely overwritten.
| 
| Consider:
| 
| // Global namespace declaration matches anticipated type.
| extern "C" size_t strlen(const char *);
| 
| // std namespace declaration doesn't match anticipated type.
| namespace std {
| double strlen;
| }

This is precisely a situation we should not tolerate.  ::strlen and
std::strlen should be synomous.  Is there any real example from the
standard library (GNU-extended) where the above scenario could happen
or would be useful?

| We end up modifying or overwritting the anticipated decls for each
| redeclaration, but clearly with very different information in each.

That cannot happen if we have a using-declaration.  No?

| Its not that we use the same "built-in" function with different
| types, but that we may or may not completely overwrite the decls
| based upon different types, i.e. redeclare the DECL associated with
| the identifier differently in different contexts.  The built-in only
| gets used when the types match.

A using-declataion just brings a name into scope with no additional
type or attributes information.  Therefore, I cannot see no oppotunity
for not completely overwriting a decl. With a using declaration, there
is a master source declaration, the used-name just propogates whatever
the master carries.  

| A less ambiguous/confusing example might be:
| 
| int strlen;
| namespace std { double strlen; }
| 
| in which neither declaration matches the pre-declared built-in.

Do we have any concrete example like that in the standard library? 
I'm under the impression that, that is not addressing any real issue
with the standard library functions.  It may be possible that I may be
missing something, then that is a reason why I need to understand why
you did the thing you did.  Right Now, I can see only disavantages.

Actually I would see the following scheme for pre-declaring standard
library functions as builtins:

   namespace std
   {
      foo builtin(bar);
   } 

   using std::builting;

| > The point is that I have been reworking some part of th name lookup
| > machinery, and that particular behaviour crashes the compiler until I
| > realized that declarations (of builtins) in the outer space is no good.
| > If they  are supposed to be pre-declared at the global scope (as the
| > comment indicates), then their DECL_CONTEXT should point to
| > global_namespace.  I'll make that change, once I understand the other
| > issue.
| 
| That sounds very reasonable.  Fortunately, fixing this should be
| independent of the first issue.  

Thank you, I'll make that separate change.

I'll still unclear about the first issue though.

-- Gaby

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: C++: Anticipated declaration of builtins.
  2003-05-26  2:08 ` Gabriel Dos Reis
@ 2003-05-26  2:44   ` Roger Sayle
  2003-05-26  4:26     ` Gabriel Dos Reis
  0 siblings, 1 reply; 5+ messages in thread
From: Roger Sayle @ 2003-05-26  2:44 UTC (permalink / raw)
  To: Gabriel Dos Reis; +Cc: jason, gcc


> | > 1) Shouldn't we pre-declare the function at global scope, then
> | >    do a using-declaration at the standard scope?
> |
> | The problem here is that they need to be treated as two independent
> | pre-declarations.  If a prototype or declaration is given for
> | one, it does not automatically anticipate/declare the other.  Hence,
> | we require separate DECLs with independent DECL_ANTICIPATED flags.
>
> Hmm, why do we need to have two independent declarations for the same
> builtin?

Because of the way that duplicate_decls overwrites the original
decl when redeclaring a declaration, such as when an anticipated
built-in function is prototyped.

If a single decl was shared between ::strlen and std::strlen, then
the destructive modification of the first decl would side-effect
the second.  I'd hoped this was clear from my reference to the
DECL_ANTICIPATED flag.  Setting it to true for the decl in the
first namespace should not automatically set the DECL_ANTICIPATED
field of the pre-declaration in the second namespace.


I believe/hope that the DECLs themselves take up very little space,
they don't contain any RTL, they share their types and other major
fields.  So the DECL itself just acts a place holder, associating
the namespace/identifier, with its types, flags and attributes.


> If we have the same builtin declared twice with possibly two
> incompatible declarations, it occurs to me that we're calling for
> trouble.  Is there any case where that could be useful?

The DECL_BUILT_IN and similar attributes are only preserved if
the declarations are compatible.  If the type of the redeclaration
doesn't match the anticipated/pre-declared type, the old decl is
just completely overwritten.

Consider:

// Global namespace declaration matches anticipated type.
extern "C" size_t strlen(const char *);

// std namespace declaration doesn't match anticipated type.
namespace std {
double strlen;
}

We end up modifying or overwritting the anticipated decls for each
redeclaration, but clearly with very different information in each.
Its not that we use the same "built-in" function with different
types, but that we may or may not completely overwrite the decls
based upon different types, i.e. redeclare the DECL associated with
the identifier differently in different contexts.  The built-in only
gets used when the types match.

A less ambiguous/confusing example might be:

int strlen;
namespace std { double strlen; }

in which neither declaration matches the pre-declared built-in.


> The point is that I have been reworking some part of th name lookup
> machinery, and that particular behaviour crashes the compiler until I
> realized that declarations (of builtins) in the outer space is no good.
> If they  are supposed to be pre-declared at the global scope (as the
> comment indicates), then their DECL_CONTEXT should point to
> global_namespace.  I'll make that change, once I understand the other
> issue.

That sounds very reasonable.  Fortunately, fixing this should be
independent of the first issue.  You can be forgiven for being confused
by the current convoluted scheme.  I'd really like to see reuse of
old DECLs in C/C++'s duplicate_decls removed, but the entire area is
a minefield, and the current implementation has the one redeeming
feature that, for the time being, it works and works efficiently.

I hope this is clearer with a second explanation.

Roger
--

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: C++: Anticipated declaration of builtins.
  2003-05-26  0:33 Roger Sayle
@ 2003-05-26  2:08 ` Gabriel Dos Reis
  2003-05-26  2:44   ` Roger Sayle
  0 siblings, 1 reply; 5+ messages in thread
From: Gabriel Dos Reis @ 2003-05-26  2:08 UTC (permalink / raw)
  To: Roger Sayle; +Cc: gcc, jason, gcc

Roger Sayle <roger@eyesopen.com> writes:

| Hi Gaby,
| 
| > 1) Shouldn't we pre-declare the function at global scope, then
| >    do a using-declaration at the standard scope?
| 
| The problem here is that they need to be treated as two independent
| pre-declarations.  If a prototype or declaration is given for
| one, it does not automatically anticipate/declare the other.  Hence,
| we require separate DECLs with independent DECL_ANTICIPATED flags.

Hmm, why do we need to have two independent declarations for the same
builtin? 

| Similarly, the user-provided declaration/prototype in one namespace
| could be compatible with the predeclared type, and hence use the
| builtin's functionality, but the declaration given in the other
| namespace incompatible, overrides the anticipated functionality
| and providing it's own definition, DECL_RTL, etc...

If we have the same builtin declared twice with possibly two
incompatible declarations, it occurs to me that we're calling for
trouble.  Is there any case where that could be useful?

| > 2) Why doesn't the second call to builtin_function_1() specify
| >    global_namespace instead of NULL_TREE?  I think specifying
| >    global_namespace should be the way to go.  What I am missing?
| 
| For this I have no good answer.  The original code used NULL_TREE
| when I added the additional call to also anticipate the declaration
| in the std:: namespace.  I've no problem with you changing it if
| that's more correct thing to do, and it passes regression checking.

The point is that I have been reworking some part of th name lookup
machinery, and that particular behaviour crashes the compiler until I
realized that declarations (of builtins) in the outer space is no good.
If they  are supposed to be pre-declared at the global scope (as the
comment indicates), then their DECL_CONTEXT should point to
global_namespace.  I'll make that change, once I understand the other
issue.

Thanks,

-- Gaby

^ permalink raw reply	[flat|nested] 5+ messages in thread

* C++: Anticipated declaration of builtins.
@ 2003-05-26  0:33 Roger Sayle
  2003-05-26  2:08 ` Gabriel Dos Reis
  0 siblings, 1 reply; 5+ messages in thread
From: Roger Sayle @ 2003-05-26  0:33 UTC (permalink / raw)
  To: gcc; +Cc: jason, gcc


Hi Gaby,

> 1) Shouldn't we pre-declare the function at global scope, then
>    do a using-declaration at the standard scope?

The problem here is that they need to be treated as two independent
pre-declarations.  If a prototype or declaration is given for
one, it does not automatically anticipate/declare the other.  Hence,
we require separate DECLs with independent DECL_ANTICIPATED flags.

Similarly, the user-provided declaration/prototype in one namespace
could be compatible with the predeclared type, and hence use the
builtin's functionality, but the declaration given in the other
namespace incompatible, overrides the anticipated functionality
and providing it's own definition, DECL_RTL, etc...


> 2) Why doesn't the second call to builtin_function_1() specify
>    global_namespace instead of NULL_TREE?  I think specifying
>    global_namespace should be the way to go.  What I am missing?

For this I have no good answer.  The original code used NULL_TREE
when I added the additional call to also anticipate the declaration
in the std:: namespace.  I've no problem with you changing it if
that's more correct thing to do, and it passes regression checking.


I hope this helps,

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-05-26  2:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-05-25 22:13 C++: Anticipated declaration of builtins gcc
2003-05-26  0:33 Roger Sayle
2003-05-26  2:08 ` Gabriel Dos Reis
2003-05-26  2:44   ` Roger Sayle
2003-05-26  4:26     ` Gabriel Dos Reis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).