Patchwork [C++] Move FINAL flag to middle-end trees.

login
register
mail settings
Submitter Jan Hubicka
Date Aug. 23, 2013, 2:36 p.m.
Message ID <20130823143616.GA27462@kam.mff.cuni.cz>
Download mbox | patch
Permalink /patch/269472/
State New
Headers show

Comments

Jan Hubicka - Aug. 23, 2013, 2:36 p.m.
> On 08/23/2013 09:57 AM, Jan Hubicka wrote:
> >Ok, I will prepare variant using public_flag of BINFO that seeems unused.
> >I.e. having BINFO_FINAL_P and C++ specific macro
> >CLASSTYPE_FINAL(t) as BINFO_FINAL_P (TYPE_BINFO (t)).
> 
> Sounds good.

Hi,
this is patch I am testing.  Does it look OK?

I have run across the following testcase:
namespace {
class A {
public:
  virtual int foo(void)
{
  return 0;
}
};
}
class A *b;
main()
{
  return b->foo();
}

here I now can devirtualize b->foo into A because A is in anonymous namespace.
We however won't remove b because it is externally visible.  Is it valid to
bring b local based on fact that A is anonymous and thus no valid C++ program
can read it?

The pointer type probably isn't anonymous anymore?

Honza

	* cp-tree.h (struct lang_type_class): Free is_final bit.
	 (CLASSTYPE_FINAL): Define using BINFO_FINAL_P.
	(DECL_FINAL_P): Remove.
	* pt.c (instantiate_class_template_1): Guard CLASSTYPE_FINAL
	by CLASS_TYPE_P
	* tree.h (tree_base): Add BINFO_FINAL_P docs
	(BINFO_FINAL_P): Define.
	(tree_decl_with_vis): One bit is taken for FINAL.
	(DECL_FINAL_P): New.
Jan Hubicka - Aug. 23, 2013, 2:51 p.m.
> Hi,
> this is patch I am testing.  Does it look OK?
> Index: cp/pt.c
> ===================================================================
> --- cp/pt.c	(revision 201910)
> +++ cp/pt.c	(working copy)
> @@ -8730,7 +8730,8 @@ instantiate_class_template_1 (tree type)
>        /* Adjust visibility for template arguments.  */
>        determine_visibility (TYPE_MAIN_DECL (type));
>      }
> -  CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
> +  if (CLASS_TYPE_P (type))
> +    CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);

Sadly we ICE here because BINFO of type is not built yet.
I tried to move the code after xref_binfos and it does seem to lead to errors
while building libstdc++ PCH.  Any idea what to do here?

Honza
Jason Merrill - Aug. 24, 2013, 6:15 a.m.
On 08/23/2013 10:51 AM, Jan Hubicka wrote:
> Sadly we ICE here because BINFO of type is not built yet.
> I tried to move the code after xref_binfos and it does seem to lead to errors
> while building libstdc++ PCH.  Any idea what to do here?

If it's causing trouble, let's just put the flag on the type.

> here I now can devirtualize b->foo into A because A is in anonymous namespace.
> We however won't remove b because it is externally visible.  Is it valid to
> bring b local based on fact that A is anonymous and thus no valid C++ program
> can read it?

Hmm, determine_visibility ought to be doing that already.

Jason
Jan Hubicka - Aug. 24, 2013, 9:18 a.m.
> On 08/23/2013 10:51 AM, Jan Hubicka wrote:
> >Sadly we ICE here because BINFO of type is not built yet.
> >I tried to move the code after xref_binfos and it does seem to lead to errors
> >while building libstdc++ PCH.  Any idea what to do here?
> 
> If it's causing trouble, let's just put the flag on the type.

OK, I mostly need the flag on type anyway, so it will save some indirection.  I will
re-test and commit the variant using default_def flag of type.

In the next step I would like to introduce the DECL_CPP_CONSTRUCTOR/DESTRUCTOR macro.
The catch I run into is that these flags are tested on TEMPLATE_DECL so the middle-end
macro bombs on type checking.  I wonder what is best approach here.

I guess I can just disable FUNCTION_DECL checking on this macro in middle-end,
but I do not like it much.  Or I can have same C++ FE macros using the same
flag that also allow templates, but then we can get them out of sync.  Or I can
update 100+ places in C++ FE to use different macro on template or I can
introduce SET variant that will care about decl type or I can just have two
flags and make C++ FE to mirror DECL_CONSTRUCTOR_P into the middle end flag?

Any more resonable options?
> 
> >here I now can devirtualize b->foo into A because A is in anonymous namespace.
> >We however won't remove b because it is externally visible.  Is it valid to
> >bring b local based on fact that A is anonymous and thus no valid C++ program
> >can read it?
> 
> Hmm, determine_visibility ought to be doing that already.

You are right.  I simplified the testcase from code I looked at but probably I
overlooked something.  Sorry for the noise!

Honza
Jason Merrill - Aug. 24, 2013, 9:22 p.m.
On 08/24/2013 05:18 AM, Jan Hubicka wrote:
> In the next step I would like to introduce the DECL_CPP_CONSTRUCTOR/DESTRUCTOR macro.
> The catch I run into is that these flags are tested on TEMPLATE_DECL so the middle-end
> macro bombs on type checking.  I wonder what is best approach here.

I think fix the front end to use STRIP_TEMPLATE to make sure we're 
checking/setting the flag on a FUNCTION_DECL.

Jason

Patch

Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 201910)
+++ cp/cp-tree.h	(working copy)
@@ -1416,7 +1416,6 @@  struct GTY(()) lang_type_class {
   unsigned has_complex_move_ctor : 1;
   unsigned has_complex_move_assign : 1;
   unsigned has_constexpr_ctor : 1;
-  unsigned is_final : 1;
 
   /* When adding a flag here, consider whether or not it ought to
      apply to a template instance if it applies to the template.  If
@@ -1425,7 +1424,7 @@  struct GTY(()) lang_type_class {
   /* There are some bits left to fill out a 32-bit word.  Keep track
      of this by updating the size of this bitfield whenever you add or
      remove a flag.  */
-  unsigned dummy : 2;
+  unsigned dummy : 3;
 
   tree primary_base;
   vec<tree_pair_s, va_gc> *vcall_indices;
@@ -1535,7 +1534,7 @@  struct GTY((variable_size)) lang_type {
 
 /* Nonzero means that NODE (a class type) is final */
 #define CLASSTYPE_FINAL(NODE) \
-  (LANG_TYPE_CLASS_CHECK (NODE)->is_final)
+  BINFO_FINAL_P (TYPE_BINFO (NODE))
 
 
 /* Nonzero means that this _CLASSTYPE node overloads operator=(X&).  */
@@ -2400,10 +2399,6 @@  struct GTY((variable_size)) lang_decl {
    an override virt-specifier */
 #define DECL_OVERRIDE_P(NODE) (TREE_LANG_FLAG_0 (NODE))
 
-/* True (in a FUNCTION_DECL) if NODE is a function declared with
-   a final virt-specifier */
-#define DECL_FINAL_P(NODE) (TREE_LANG_FLAG_1 (NODE))
-
 /* The thunks associated with NODE, a FUNCTION_DECL.  */
 #define DECL_THUNKS(NODE) \
   (DECL_VIRTUAL_P (NODE) ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE)
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 201910)
+++ cp/pt.c	(working copy)
@@ -8730,7 +8730,8 @@  instantiate_class_template_1 (tree type)
       /* Adjust visibility for template arguments.  */
       determine_visibility (TYPE_MAIN_DECL (type));
     }
-  CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
+  if (CLASS_TYPE_P (type))
+    CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern);
 
   pbinfo = TYPE_BINFO (pattern);
 
Index: tree.h
===================================================================
--- tree.h	(revision 201910)
+++ tree.h	(working copy)
@@ -563,6 +563,9 @@  struct GTY(()) tree_base {
        TRANSACTION_EXPR_RELAXED in
 	   TRANSACTION_EXPR
 
+       BINFO_FINAL_P in
+	   BINFO
+
    private_flag:
 
        TREE_PRIVATE in
@@ -2314,6 +2317,10 @@  enum cv_qualifier
 #define TYPE_CONTAINS_PLACEHOLDER_INTERNAL(NODE) \
   (TYPE_CHECK (NODE)->type_common.contains_placeholder_bits)
 
+/* Nonzero if RECORD_TYPE represents a final derivation of class.  */
+#define BINFO_FINAL_P(NODE) \
+  (TREE_BINFO_CHECK (NODE)->base.public_flag)
+
 /* The debug output functions use the symtab union field to store
    information specific to the debugging format.  The different debug
    output hooks store different types in the union field.  These three
@@ -3224,7 +3231,9 @@  struct GTY(()) tree_decl_with_vis {
  unsigned init_priority_p : 1;
  /* Used by C++ only.  Might become a generic decl flag.  */
  unsigned shadowed_for_var_p : 1;
- /* 14 unused bits. */
+ /* Belong to FUNCTION_DECL exclusively.  */
+ unsigned final : 1;
+ /* 13 unused bits. */
 };
 
 extern tree decl_debug_expr_lookup (tree);
@@ -3474,6 +3483,11 @@  extern vec<tree, va_gc> **decl_debug_arg
 #define DECL_FUNCTION_VERSIONED(NODE)\
    (FUNCTION_DECL_CHECK (NODE)->function_decl.versioned_function)
 
+/* In FUNCTION_DECL that represent an virtual method this is set when
+   the method is final.  */
+#define DECL_FINAL_P(NODE)\
+   (FUNCTION_DECL_CHECK (NODE)->decl_with_vis.final)
+
 /* FUNCTION_DECL inherits from DECL_NON_COMMON because of the use of the
    arguments/result/saved_tree fields by front ends.   It was either inherit
    FUNCTION_DECL from non_common, or inherit non_common from FUNCTION_DECL,