diff options
author | Jakub Jelinek <jakub@redhat.com> | 2022-01-03 11:21:00 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2022-01-03 11:21:00 +0100 |
commit | 134442b2178a164ed4580255a0de007dda19b855 (patch) | |
tree | 6f048a33ed9afc59b39ffea97635723568cd5747 /gcc/symtab.c | |
parent | cd83fd98a7e769ac7ded28377984f68238812a26 (diff) | |
download | gcc-134442b2178a164ed4580255a0de007dda19b855.zip gcc-134442b2178a164ed4580255a0de007dda19b855.tar.gz gcc-134442b2178a164ed4580255a0de007dda19b855.tar.bz2 |
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.
Diffstat (limited to 'gcc/symtab.c')
-rw-r--r-- | gcc/symtab.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/gcc/symtab.c b/gcc/symtab.c index d037fe6..f9e4571 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. |