Patchwork Make C++ use TRANSLATION_UNIT_DECL for global entities

login
register
mail settings
Submitter Richard Guenther
Date Sept. 28, 2010, 3:21 p.m.
Message ID <alpine.LNX.2.00.1009281720180.8982@zhemvz.fhfr.qr>
Download mbox | patch
Permalink /patch/65980/
State New
Headers show

Comments

Richard Guenther - Sept. 28, 2010, 3:21 p.m.
On Tue, 28 Sep 2010, Jason Merrill wrote:

> On 09/28/2010 10:23 AM, Richard Guenther wrote:
> > then we'd push global_namespace where we previously didn't.
> > Or maybe I misunderstood you?
> 
> Right, that is what I meant.  I think that pushing global_namespace there
> shouldn't hurt, but it would also be fine to test against global_namespace and
> just not push in that case.

Ok, I'll test


then.

> > > > + /* Nonzero for a scope which is equal to file scope.  */
> > > > + #define SCOPE_FILE_SCOPE_P(EXP)	\
> > > > +   (! (EXP) || TREE_CODE (EXP) == TRANSLATION_UNIT_DECL)
> > > 
> > > Hmm, I wonder if it will be confusing that this is not true for
> > > global_namespace as well.
> > 
> > Well, these are middle-end macros supposed to be applied to
> > {TYPE,DECL}_CONTEXT, not CP_{TYPE,DECL}_CONTEXT.  I can
> > introduce CP_ variants of them and avoid using the middle-end
> > variants in the frontend if you prefer that.
> 
> Don't bother, it isn't used enough to worry about.

Ok.  I'll post an updated patch after testing finished.

Thanks,
Richard.
Richard Guenther - Sept. 29, 2010, 9:20 a.m.
On Tue, 28 Sep 2010, Richard Guenther wrote:

> On Tue, 28 Sep 2010, Jason Merrill wrote:
> 
> > On 09/28/2010 10:23 AM, Richard Guenther wrote:
> > > then we'd push global_namespace where we previously didn't.
> > > Or maybe I misunderstood you?
> > 
> > Right, that is what I meant.  I think that pushing global_namespace there
> > shouldn't hurt, but it would also be fine to test against global_namespace and
> > just not push in that case.

Here is an updated patch.  Pushing global_namespace doesn't bootstrap
so I test against it.

Bootstrapped and tested on x86_64-unknown-linux-gnu, ok?

Thanks,
Richard.

2010-09-29  Richard Guenther  <rguenther@suse.de>

	* tree.h (SCOPE_FILE_SCOPE_P): New macro.
	(DECL_FILE_SCOPE_P): Use it.
	(TYPE_FILE_SCOPE_P): New macro.

	* cp-tree.h (CP_DECL_CONTEXT): Check DECL_FILE_SCOPE_P.
	(CP_TYPE_CONTEXT): Similar.
	(FROB_CONTEXT): Frob global_namespace to the global
	TRANSLATION_UNIT_DECL.
	* decl.c (cxx_init_decl_processing): Build a TRANSLATION_UNIT_DECL,
	set DECL_CONTEXT of global_namespace to it.

	* decl.c (start_decl): Use CP_DECL_CONTEXT and test TYPE_P
	instead of zeroing context.
	(cp_finish_decl): Use DECL_FILE_SCOPE_P.
	(grokfndecl): Likewise.
	(start_preparsed_function): Likewise.
	* name-lookup.c (maybe_push_decl): Use CP_DECL_CONTEXT.
	(namespace_binding): Use SCOPE_FILE_SCOPE_P.
	* pt.c (template_class_depth): Use CP_TYPE_CONTEXT.
	(is_specialization_of_friend): Use CP_DECL_CONTEXT.
	(push_template_decl_real): Likewise.
	(tsubst_friend_class): Likewise.  Adjust context comparisons.
	(instantiate_class_template): Use CP_TYPE_CONTEXT.
	(tsubst): Do not substitute into TRANSLATION_UNIT_DECL.
	* cxx-pretty-print.c (pp_cxx_nested_name_specifier): Use
	SCOPE_FILE_SCOPE_P.

Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h.orig	2010-09-28 12:29:24.000000000 +0200
--- gcc/cp/cp-tree.h	2010-09-28 16:15:47.000000000 +0200
*************** struct GTY((variable_size)) lang_decl {
*** 2361,2372 ****
  #define SET_DECL_FRIEND_CONTEXT(NODE, CONTEXT) \
    (LANG_DECL_FN_CHECK (NODE)->context = (CONTEXT))
  
- /* NULL_TREE in DECL_CONTEXT represents the global namespace.  */
  #define CP_DECL_CONTEXT(NODE) \
!   (DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
  #define CP_TYPE_CONTEXT(NODE) \
!   (TYPE_CONTEXT (NODE) ? TYPE_CONTEXT (NODE) : global_namespace)
! #define FROB_CONTEXT(NODE)   ((NODE) == global_namespace ? NULL_TREE : (NODE))
  
  /* 1 iff NODE has namespace scope, including the global namespace.  */
  #define DECL_NAMESPACE_SCOPE_P(NODE)				\
--- 2361,2372 ----
  #define SET_DECL_FRIEND_CONTEXT(NODE, CONTEXT) \
    (LANG_DECL_FN_CHECK (NODE)->context = (CONTEXT))
  
  #define CP_DECL_CONTEXT(NODE) \
!   (!DECL_FILE_SCOPE_P (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
  #define CP_TYPE_CONTEXT(NODE) \
!   (!TYPE_FILE_SCOPE_P (NODE) ? TYPE_CONTEXT (NODE) : global_namespace)
! #define FROB_CONTEXT(NODE) \
!   ((NODE) == global_namespace ? DECL_CONTEXT (NODE) : (NODE))
  
  /* 1 iff NODE has namespace scope, including the global namespace.  */
  #define DECL_NAMESPACE_SCOPE_P(NODE)				\
Index: gcc/cp/decl.c
===================================================================
*** gcc/cp/decl.c.orig	2010-09-28 12:29:24.000000000 +0200
--- gcc/cp/decl.c	2010-09-28 17:56:12.000000000 +0200
*************** cxx_init_decl_processing (void)
*** 3417,3422 ****
--- 3417,3423 ----
    gcc_assert (global_namespace == NULL_TREE);
    global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
  				      void_type_node);
+   DECL_CONTEXT (global_namespace) = build_translation_unit_decl (NULL_TREE);
    TREE_PUBLIC (global_namespace) = 1;
    begin_scope (sk_namespace, global_namespace);
  
*************** start_decl (const cp_declarator *declara
*** 4163,4178 ****
        || decl == error_mark_node)
      return error_mark_node;
  
!   context = DECL_CONTEXT (decl);
! 
!   if (context)
!     {
!       *pushed_scope_p = push_scope (context);
! 
!       /* We are only interested in class contexts, later.  */
!       if (TREE_CODE (context) == NAMESPACE_DECL)
! 	context = NULL_TREE;
!     }
  
    if (initialized)
      /* Is it valid for this decl to have an initializer at all?
--- 4164,4172 ----
        || decl == error_mark_node)
      return error_mark_node;
  
!   context = CP_DECL_CONTEXT (decl);
!   if (context != global_namespace)
!     *pushed_scope_p = push_scope (context);
  
    if (initialized)
      /* Is it valid for this decl to have an initializer at all?
*************** start_decl (const cp_declarator *declara
*** 4241,4247 ****
        && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
      warning (0, "inline function %q+D given attribute noinline", decl);
  
!   if (context && COMPLETE_TYPE_P (complete_type (context)))
      {
        if (TREE_CODE (decl) == VAR_DECL)
  	{
--- 4235,4241 ----
        && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
      warning (0, "inline function %q+D given attribute noinline", decl);
  
!   if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
      {
        if (TREE_CODE (decl) == VAR_DECL)
  	{
*************** cp_finish_decl (tree decl, tree init, bo
*** 5802,5808 ****
  	  && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
  	TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
  
!       rest_of_decl_compilation (decl, DECL_CONTEXT (decl) == NULL_TREE,
  				at_eof);
        goto finish_end;
      }
--- 5796,5802 ----
  	  && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
  	TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
  
!       rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl),
  				at_eof);
        goto finish_end;
      }
*************** grokfndecl (tree ctype,
*** 6888,6895 ****
  	   && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
        && current_lang_name == lang_name_cplusplus
        && ctype == NULL_TREE
!       /* NULL_TREE means global namespace.  */
!       && DECL_CONTEXT (decl) == NULL_TREE)
      SET_DECL_LANGUAGE (decl, lang_c);
  
    /* Should probably propagate const out from type to decl I bet (mrs).  */
--- 6882,6888 ----
  	   && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
        && current_lang_name == lang_name_cplusplus
        && ctype == NULL_TREE
!       && DECL_FILE_SCOPE_P (decl))
      SET_DECL_LANGUAGE (decl, lang_c);
  
    /* Should probably propagate const out from type to decl I bet (mrs).  */
*************** start_preparsed_function (tree decl1, tr
*** 12068,12074 ****
  	 with any previous declarations; if the original declaration
  	 has a linkage specification, that specification applies to
  	 the definition as well, and may affect the mangled name.  */
!       if (!DECL_CONTEXT (decl1))
  	maybe_apply_pragma_weak (decl1);
      }
  
--- 12061,12067 ----
  	 with any previous declarations; if the original declaration
  	 has a linkage specification, that specification applies to
  	 the definition as well, and may affect the mangled name.  */
!       if (DECL_FILE_SCOPE_P (decl1))
  	maybe_apply_pragma_weak (decl1);
      }
  
Index: gcc/cp/name-lookup.c
===================================================================
*** gcc/cp/name-lookup.c.orig	2010-09-28 12:29:24.000000000 +0200
--- gcc/cp/name-lookup.c	2010-09-28 16:21:45.000000000 +0200
*************** maybe_push_decl (tree decl)
*** 1169,1175 ****
  	  && DECL_CONTEXT (decl) != NULL_TREE
  	  /* Definitions of namespace members outside their namespace are
  	     possible.  */
! 	  && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
        || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
        || type == unknown_type_node
        /* The declaration of a template specialization does not affect
--- 1169,1175 ----
  	  && DECL_CONTEXT (decl) != NULL_TREE
  	  /* Definitions of namespace members outside their namespace are
  	     possible.  */
! 	  && TREE_CODE (CP_DECL_CONTEXT (decl)) != NAMESPACE_DECL)
        || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
        || type == unknown_type_node
        /* The declaration of a template specialization does not affect
*************** namespace_binding (tree name, tree scope
*** 3068,3074 ****
  {
    cxx_binding *binding;
  
!   if (scope == NULL)
      scope = global_namespace;
    else
      /* Unnecessary for the global namespace because it can't be an alias. */
--- 3068,3074 ----
  {
    cxx_binding *binding;
  
!   if (SCOPE_FILE_SCOPE_P (scope))
      scope = global_namespace;
    else
      /* Unnecessary for the global namespace because it can't be an alias. */
Index: gcc/cp/pt.c
===================================================================
*** gcc/cp/pt.c.orig	2010-09-28 12:29:24.000000000 +0200
--- gcc/cp/pt.c	2010-09-28 16:15:47.000000000 +0200
*************** template_class_depth (tree type)
*** 344,350 ****
    for (depth = 0;
         type && TREE_CODE (type) != NAMESPACE_DECL;
         type = (TREE_CODE (type) == FUNCTION_DECL)
! 	 ? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type))
      {
        tree tinfo = get_template_info (type);
  
--- 344,350 ----
    for (depth = 0;
         type && TREE_CODE (type) != NAMESPACE_DECL;
         type = (TREE_CODE (type) == FUNCTION_DECL)
! 	 ? CP_DECL_CONTEXT (type) : CP_TYPE_CONTEXT (type))
      {
        tree tinfo = get_template_info (type);
  
*************** is_specialization_of_friend (tree decl,
*** 1130,1136 ****
       nonzero.  To determine if DECL is a friend of FRIEND, we first
       check if the enclosing class is a specialization of another.  */
  
!   template_depth = template_class_depth (DECL_CONTEXT (friend_decl));
    if (template_depth
        && DECL_CLASS_SCOPE_P (decl)
        && is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
--- 1130,1136 ----
       nonzero.  To determine if DECL is a friend of FRIEND, we first
       check if the enclosing class is a specialization of another.  */
  
!   template_depth = template_class_depth (CP_DECL_CONTEXT (friend_decl));
    if (template_depth
        && DECL_CLASS_SCOPE_P (decl)
        && is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
*************** push_template_decl_real (tree decl, bool
*** 4346,4352 ****
    if (is_friend)
      /* For a friend, we want the context of the friend function, not
         the type of which it is a friend.  */
!     ctx = DECL_CONTEXT (decl);
    else if (CP_DECL_CONTEXT (decl)
  	   && TREE_CODE (CP_DECL_CONTEXT (decl)) != NAMESPACE_DECL)
      /* In the case of a virtual function, we want the class in which
--- 4346,4352 ----
    if (is_friend)
      /* For a friend, we want the context of the friend function, not
         the type of which it is a friend.  */
!     ctx = CP_DECL_CONTEXT (decl);
    else if (CP_DECL_CONTEXT (decl)
  	   && TREE_CODE (CP_DECL_CONTEXT (decl)) != NAMESPACE_DECL)
      /* In the case of a virtual function, we want the class in which
*************** tsubst_friend_class (tree friend_tmpl, t
*** 7530,7538 ****
    tree tmpl;
    tree context;
  
!   context = DECL_CONTEXT (friend_tmpl);
  
!   if (context)
      {
        if (TREE_CODE (context) == NAMESPACE_DECL)
  	push_nested_namespace (context);
--- 7530,7538 ----
    tree tmpl;
    tree context;
  
!   context = CP_DECL_CONTEXT (friend_tmpl);
  
!   if (context != global_namespace)
      {
        if (TREE_CODE (context) == NAMESPACE_DECL)
  	push_nested_namespace (context);
*************** tsubst_friend_class (tree friend_tmpl, t
*** 7621,7627 ****
        friend_type = TREE_TYPE (pushdecl_top_level_maybe_friend (tmpl, true));
      }
  
!   if (context)
      {
        if (TREE_CODE (context) == NAMESPACE_DECL)
  	pop_nested_namespace (context);
--- 7621,7627 ----
        friend_type = TREE_TYPE (pushdecl_top_level_maybe_friend (tmpl, true));
      }
  
!   if (context != global_namespace)
      {
        if (TREE_CODE (context) == NAMESPACE_DECL)
  	pop_nested_namespace (context);
*************** instantiate_class_template (tree type)
*** 7883,7896 ****
    if (BINFO_N_BASE_BINFOS (pbinfo))
      {
        tree pbase_binfo;
-       tree context = TYPE_CONTEXT (type);
        tree pushed_scope;
        int i;
  
        /* We must enter the scope containing the type, as that is where
  	 the accessibility of types named in dependent bases are
  	 looked up from.  */
!       pushed_scope = push_scope (context ? context : global_namespace);
  
        /* Substitute into each of the bases to determine the actual
  	 basetypes.  */
--- 7883,7895 ----
    if (BINFO_N_BASE_BINFOS (pbinfo))
      {
        tree pbase_binfo;
        tree pushed_scope;
        int i;
  
        /* We must enter the scope containing the type, as that is where
  	 the accessibility of types named in dependent bases are
  	 looked up from.  */
!       pushed_scope = push_scope (CP_TYPE_CONTEXT (type));
  
        /* Substitute into each of the bases to determine the actual
  	 basetypes.  */
*************** tsubst (tree t, tree args, tsubst_flags_
*** 10012,10018 ****
        || t == void_type_node
        || t == char_type_node
        || t == unknown_type_node
!       || TREE_CODE (t) == NAMESPACE_DECL)
      return t;
  
    if (DECL_P (t))
--- 10011,10018 ----
        || t == void_type_node
        || t == char_type_node
        || t == unknown_type_node
!       || TREE_CODE (t) == NAMESPACE_DECL
!       || TREE_CODE (t) == TRANSLATION_UNIT_DECL)
      return t;
  
    if (DECL_P (t))
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2010-09-28 12:29:24.000000000 +0200
--- gcc/tree.h	2010-09-28 16:15:47.000000000 +0200
*************** struct GTY(()) tree_decl_minimal {
*** 2687,2696 ****
  #define DECL_LANG_FLAG_8(NODE) \
    (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_8)
  
  /* Nonzero for a decl which is at file scope.  */
! #define DECL_FILE_SCOPE_P(EXP) 					\
!   (! DECL_CONTEXT (EXP)						\
!    || TREE_CODE (DECL_CONTEXT (EXP)) == TRANSLATION_UNIT_DECL)
  
  /* Nonzero for a decl that is decorated using attribute used.
     This indicates to compiler tools that this decl needs to be preserved.  */
--- 2687,2699 ----
  #define DECL_LANG_FLAG_8(NODE) \
    (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_8)
  
+ /* Nonzero for a scope which is equal to file scope.  */
+ #define SCOPE_FILE_SCOPE_P(EXP)	\
+   (! (EXP) || TREE_CODE (EXP) == TRANSLATION_UNIT_DECL)
  /* Nonzero for a decl which is at file scope.  */
! #define DECL_FILE_SCOPE_P(EXP) SCOPE_FILE_SCOPE_P (DECL_CONTEXT (EXP))
! /* Nonzero for a type which is at file scope.  */
! #define TYPE_FILE_SCOPE_P(EXP) SCOPE_FILE_SCOPE_P (TYPE_CONTEXT (EXP))
  
  /* Nonzero for a decl that is decorated using attribute used.
     This indicates to compiler tools that this decl needs to be preserved.  */
Index: gcc/cp/cxx-pretty-print.c
===================================================================
*** gcc/cp/cxx-pretty-print.c.orig	2010-09-28 12:29:24.000000000 +0200
--- gcc/cp/cxx-pretty-print.c	2010-09-28 16:15:47.000000000 +0200
*************** pp_cxx_template_keyword_if_needed (cxx_p
*** 260,266 ****
  static void
  pp_cxx_nested_name_specifier (cxx_pretty_printer *pp, tree t)
  {
!   if (t != NULL && t != pp->enclosing_scope)
      {
        tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t);
        pp_cxx_nested_name_specifier (pp, scope);
--- 260,266 ----
  static void
  pp_cxx_nested_name_specifier (cxx_pretty_printer *pp, tree t)
  {
!   if (!SCOPE_FILE_SCOPE_P (t) && t != pp->enclosing_scope)
      {
        tree scope = TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT (t);
        pp_cxx_nested_name_specifier (pp, scope);
Jason Merrill - Sept. 29, 2010, 12:52 p.m.
On 09/29/2010 05:20 AM, Richard Guenther wrote:
> ! 	&&  TREE_CODE (CP_DECL_CONTEXT (decl)) != NAMESPACE_DECL)

It occurs to me that this is !DECL_NAMESPACE_SCOPE_P.  OK with that change.

Jason
H.J. Lu - Oct. 30, 2010, 2:15 p.m.
On Wed, Sep 29, 2010 at 2:20 AM, Richard Guenther <rguenther@suse.de> wrote:
> On Tue, 28 Sep 2010, Richard Guenther wrote:
>
>> On Tue, 28 Sep 2010, Jason Merrill wrote:
>>
>> > On 09/28/2010 10:23 AM, Richard Guenther wrote:
>> > > then we'd push global_namespace where we previously didn't.
>> > > Or maybe I misunderstood you?
>> >
>> > Right, that is what I meant.  I think that pushing global_namespace there
>> > shouldn't hurt, but it would also be fine to test against global_namespace and
>> > just not push in that case.
>
> Here is an updated patch.  Pushing global_namespace doesn't bootstrap
> so I test against it.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, ok?
>
> Thanks,
> Richard.
>
> 2010-09-29  Richard Guenther  <rguenther@suse.de>
>
>        * tree.h (SCOPE_FILE_SCOPE_P): New macro.
>        (DECL_FILE_SCOPE_P): Use it.
>        (TYPE_FILE_SCOPE_P): New macro.
>
>        * cp-tree.h (CP_DECL_CONTEXT): Check DECL_FILE_SCOPE_P.
>        (CP_TYPE_CONTEXT): Similar.
>        (FROB_CONTEXT): Frob global_namespace to the global
>        TRANSLATION_UNIT_DECL.
>        * decl.c (cxx_init_decl_processing): Build a TRANSLATION_UNIT_DECL,
>        set DECL_CONTEXT of global_namespace to it.
>
>        * decl.c (start_decl): Use CP_DECL_CONTEXT and test TYPE_P
>        instead of zeroing context.
>        (cp_finish_decl): Use DECL_FILE_SCOPE_P.
>        (grokfndecl): Likewise.
>        (start_preparsed_function): Likewise.
>        * name-lookup.c (maybe_push_decl): Use CP_DECL_CONTEXT.
>        (namespace_binding): Use SCOPE_FILE_SCOPE_P.
>        * pt.c (template_class_depth): Use CP_TYPE_CONTEXT.
>        (is_specialization_of_friend): Use CP_DECL_CONTEXT.
>        (push_template_decl_real): Likewise.
>        (tsubst_friend_class): Likewise.  Adjust context comparisons.
>        (instantiate_class_template): Use CP_TYPE_CONTEXT.
>        (tsubst): Do not substitute into TRANSLATION_UNIT_DECL.
>        * cxx-pretty-print.c (pp_cxx_nested_name_specifier): Use
>        SCOPE_FILE_SCOPE_P.
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46241

Patch

Index: decl.c
===================================================================
--- decl.c      (revision 164681)
+++ decl.c      (working copy)
@@ -4163,16 +4164,8 @@  start_decl (const cp_declarator *declara
       || decl == error_mark_node)
     return error_mark_node;
 
-  context = DECL_CONTEXT (decl);
-
-  if (context)
-    {
-      *pushed_scope_p = push_scope (context);
-
-      /* We are only interested in class contexts, later.  */
-      if (TREE_CODE (context) == NAMESPACE_DECL)
-       context = NULL_TREE;
-    }
+  context = CP_DECL_CONTEXT (decl);
+  *pushed_scope_p = push_scope (context);
 
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
@@ -4241,7 +4234,7 @@  start_decl (const cp_declarator *declara
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
     warning (0, "inline function %q+D given attribute noinline", decl);
 
-  if (context && COMPLETE_TYPE_P (complete_type (context)))
+  if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
     {
       if (TREE_CODE (decl) == VAR_DECL)
        {