public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-6183] c++: Support &typeid(x) == &typeid(y) and typeid(x) == typeid(y) in constant evaluation [PR103600]
@ 2022-01-03 10:24 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2022-01-03 10:24 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:134442b2178a164ed4580255a0de007dda19b855

commit r12-6183-g134442b2178a164ed4580255a0de007dda19b855
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Mon Jan 3 11:21:00 2022 +0100

    c++: Support &typeid(x) == &typeid(y) and typeid(x) == typeid(y) in constant evaluation [PR103600]
    
    If the tinfo vars are emitted in the current TU, they are emitted at the end
    of the compilation, and for some types they are exported from
    libstdc++/libsupc++ and not emitted in the current TU at all.
    
    The following patch allows constant folding of comparisons of typeid
    addresses and makes it possible to implement P1328R1 - making type_info
    operator== constexpr (Jonathan has a patch for that).
    
    As mentioned in the PR, the varpool/middle-end code is trying to be
    conservative with address comparisons of different vars if those vars
    don't bind locally, because of possible aliases in other TUs etc.
    and so while match.pd folds &typeid(int) == &typeid(int) because
    it is equality comparison with the same operands, for different typeids
    it doesn't fold it.
    
    On Wed, Dec 08, 2021 at 08:53:03AM -0500, Jason Merrill wrote:
    > Would it make sense to assume that DECL_ARTIFICIAL variables can't be
    > aliases?  If not, could we have some way of marking a variable as
    > non-aliasing, perhaps an attribute?
    
    I think DECL_ARTIFICIAL vars generally can overlap.
    
    The following patch adds a GCC internal attribute "non overlapping"
    and uses it in symtab_node::equal_address_to.
    Not sure what plans has Honza in that area and whether it would be useful
    to make the attribute public and let users assert that some variable will
    never overlap with other variables, won't have aliases etc.
    
    > During constant evaluation, the operator== could compare the type_info
    > address instead of the __name address, reducing this to the previous
    > problem.
    
    Ah, indeed, good idea.  FYI, clang++ seems to constant fold
    &typeid(x) != &typeid(y) already, so Jonathan could use it even for
    clang++ in the constexpr operator==.  But it folds even
    extern int &a, &b;
    constexpr bool c = &a != &b;
    regardless of whether some other TU has
    int a;
    int b __attribute__((alias (a));
    or not.
    
    2022-01-03  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/103600
    gcc/
            * symtab.c (symtab_node::equal_address_to): Return 0 if one of
            VAR_DECLs has "non overlapping" attribute and rs1 != rs2.
    gcc/c-family/
            * c-attribs.c (handle_non_overlapping_attribute): New function.
            (c_common_attribute_table): Add "non overlapping" attribute.
    gcc/cp/
            * rtti.c (get_tinfo_decl_direct): Add "non overlapping" attribute
            to DECL_TINFO_P VAR_DECLs.
    gcc/testsuite/
            * g++.dg/cpp0x/constexpr-typeid2.C: New test.

Diff:
---
 gcc/c-family/c-attribs.c                       | 12 ++++++++++++
 gcc/cp/rtti.c                                  |  9 +++++++++
 gcc/symtab.c                                   |  8 ++++++++
 gcc/testsuite/g++.dg/cpp0x/constexpr-typeid2.C | 14 ++++++++++++++
 4 files changed, 43 insertions(+)

diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index bd420369a91..dbb892e0ec6 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -159,6 +159,7 @@ static tree handle_omp_declare_variant_attribute (tree *, tree, tree, int,
 static tree handle_simd_attribute (tree *, tree, tree, int, bool *);
 static tree handle_omp_declare_target_attribute (tree *, tree, tree, int,
 						 bool *);
+static tree handle_non_overlapping_attribute (tree *, tree, tree, int, bool *);
 static tree handle_designated_init_attribute (tree *, tree, tree, int, bool *);
 static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
 						       int, bool *);
@@ -512,6 +513,8 @@ const struct attribute_spec c_common_attribute_table[] =
 			      handle_omp_declare_target_attribute, NULL },
   { "omp declare target block", 0, 0, true, false, false, false,
 			      handle_omp_declare_target_attribute, NULL },
+  { "non overlapping",	      0, 0, true, false, false, false,
+			      handle_non_overlapping_attribute, NULL },
   { "alloc_align",	      1, 1, false, true, true, false,
 			      handle_alloc_align_attribute,
 	                      attr_alloc_exclusions },
@@ -3765,6 +3768,15 @@ handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
   return NULL_TREE;
 }
 
+/* Handle an "non overlapping" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_non_overlapping_attribute (tree *, tree, tree, int, bool *)
+{
+  return NULL_TREE;
+}
+
 /* Handle a "returns_twice" attribute; arguments as in
    struct attribute_spec.handler.  */
 
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 30ae18a0e5f..a4dedc31f0a 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -475,6 +475,15 @@ get_tinfo_decl_direct (tree type, tree name, int pseudo_ix)
       DECL_IGNORED_P (d) = 1;
       TREE_READONLY (d) = 1;
       TREE_STATIC (d) = 1;
+      /* Tell equal_address_to that different tinfo decls never
+	 overlap.  */
+      if (vec_safe_is_empty (unemitted_tinfo_decls))
+	DECL_ATTRIBUTES (d)
+	  = build_tree_list (get_identifier ("non overlapping"),
+			     NULL_TREE);
+      else
+	DECL_ATTRIBUTES (d)
+	  = DECL_ATTRIBUTES ((*unemitted_tinfo_decls)[0]);
 
       /* Mark the variable as undefined -- but remember that we can
 	 define it later if we need to do so.  */
diff --git a/gcc/symtab.c b/gcc/symtab.c
index d037fe68e7e..f9e4571d396 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -2276,6 +2276,14 @@ symtab_node::equal_address_to (symtab_node *s2, bool memory_accessed)
       return 0;
     }
 
+  /* If the FE tells us at least one of the decls will never be aliased nor
+     overlapping with other vars in some other way, return 0.  */
+  if (VAR_P (decl)
+      && rs1 != rs2
+      && (lookup_attribute ("non overlapping", DECL_ATTRIBUTES (decl))
+	  || lookup_attribute ("non overlapping", DECL_ATTRIBUTES (s2->decl))))
+    return 0;
+
   /* TODO: Alias oracle basically assume that addresses of global variables
      are different unless they are declared as alias of one to another while
      the code folding comparisons doesn't.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid2.C
new file mode 100644
index 00000000000..78c6b8e9a2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid2.C
@@ -0,0 +1,14 @@
+// PR c++/103600
+// { dg-do compile { target c++11 } }
+
+#include <typeinfo>
+
+struct S { int i; };
+namespace {
+  struct T { int i; };
+};
+constexpr bool a = &typeid (int) == &typeid (int);
+constexpr bool b = &typeid (int) == &typeid (long);
+constexpr bool c = &typeid (double) != &typeid (int);
+constexpr bool d = &typeid (S) != &typeid (T);
+static_assert (a && !b && c && d, "");


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-01-03 10:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-03 10:24 [gcc r12-6183] c++: Support &typeid(x) == &typeid(y) and typeid(x) == typeid(y) in constant evaluation [PR103600] Jakub Jelinek

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).