aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-10-07 05:46:24 -0700
committerNathan Sidwell <nathan@acm.org>2020-10-07 06:04:14 -0700
commit4e62aca0e0520e4ed2532f2d8153581190621c1a (patch)
treeb7dc85222f79352e26770977dfcc28a0f5b4bf55 /gcc/cp/decl.c
parente089e43365f7f2a90979e2316aea25d44823f5a3 (diff)
downloadgcc-4e62aca0e0520e4ed2532f2d8153581190621c1a.zip
gcc-4e62aca0e0520e4ed2532f2d8153581190621c1a.tar.gz
gcc-4e62aca0e0520e4ed2532f2d8153581190621c1a.tar.bz2
c++: block-scope externs get an alias [PR95677,PR31775,PR95677]
This patch improves block-scope extern handling by always injecting a hidden copy into the enclosing namespace (or using a match already there). This hidden copy will be revealed if the user explicitly declares it later. We can get from the DECL_LOCAL_DECL_P local extern to the alias via DECL_LOCAL_DECL_ALIAS. This fixes several bugs and removes the kludgy per-function extern_decl_map. We only do this pushing for non-dependent local externs -- dependent ones will be pushed during instantiation. User code that expected to be able to handle incompatible local externs in different block-scopes will no longer work. That code is ill-formed. (always was, despite what 31775 claimed). I had to adjust a number of testcases that fell into this. I tried using DECL_VALUE_EXPR, but that didn't work out. Due to constexpr requirements we have to do the replacement very late (it happens in the gimplifier). Consider: extern int l[]; // #1 constexpr bool foo () { extern int l[3]; // this does not complete the type of decl #1 constexpr int *p = &l[2]; // ok return !p; } This requirement, coupled with our use of the common folding machinery makes pr97306 hard to fix, as we end up with an expression containing the two different decls for 'l', and only the c++ FE knows how to reconcile those. I punted on this. gcc/cp/ * cp-tree.h (struct language_function): Delete extern_decl_map. (DECL_LOCAL_DECL_ALIAS): New. * name-lookup.h (is_local_extern): Delete. * name-lookup.c (set_local_extern_decl_linkage): Replace with ... (push_local_extern_decl): ... this new function. (do_pushdecl): Call new function after pushing new decl. Unhide hidden non-functions. (is_local_extern): Delete. * decl.c (layout_var_decl): Do not allow VLA local externs. * decl2.c (mark_used): Also mark DECL_LOCAL_DECL_ALIAS. Drop old local-extern treatment. * parser.c (cp_parser_oacc_declare): Deal with local extern aliases. * pt.c (tsubst_expr): Adjust local extern instantiation. * cp-gimplify.c (cp_genericize_r): Remap DECL_LOCAL_DECLs. gcc/testsuite/ * g++.dg/cpp0x/lambda/lambda-sfinae1.C: Avoid ill-formed local extern * g++.dg/init/pr42844.C: Add expected error. * g++.dg/lookup/extern-redecl1.C: Likewise. * g++.dg/lookup/koenig15.C: Avoid ill-formed. * g++.dg/lto/pr95677.C: New. * g++.dg/other/nested-extern-1.C: Correct expected behabviour. * g++.dg/other/nested-extern-2.C: Likewise. * g++.dg/other/nested-extern.cc: Split ... * g++.dg/other/nested-extern-1.cc: ... here ... * g++.dg/other/nested-extern-2.cc: ... here. * g++.dg/template/scope5.C: Avoid ill-formed * g++.old-deja/g++.law/missed-error2.C: Allow extension. * g++.old-deja/g++.pt/crash3.C: Add expected error.
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 4ec1f4a..0fe74b2 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5830,7 +5830,8 @@ layout_var_decl (tree decl)
&& DECL_SIZE (decl) != NULL_TREE
&& ! TREE_CONSTANT (DECL_SIZE (decl)))
{
- if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
+ if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST
+ && !DECL_LOCAL_DECL_P (decl))
constant_expression_warning (DECL_SIZE (decl));
else
{