aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-gimplify.c26
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/decl2.c25
-rw-r--r--gcc/cp/name-lookup.c186
-rw-r--r--gcc/cp/name-lookup.h1
-rw-r--r--gcc/cp/parser.c14
-rw-r--r--gcc/cp/pt.c14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-sfinae1.C2
-rw-r--r--gcc/testsuite/g++.dg/init/pr42844.C2
-rw-r--r--gcc/testsuite/g++.dg/lookup/extern-redecl1.C10
-rw-r--r--gcc/testsuite/g++.dg/lookup/koenig15.C6
-rw-r--r--gcc/testsuite/g++.dg/lto/pr95677.C19
-rw-r--r--gcc/testsuite/g++.dg/other/nested-extern-1.C16
-rw-r--r--gcc/testsuite/g++.dg/other/nested-extern-1.cc3
-rw-r--r--gcc/testsuite/g++.dg/other/nested-extern-2.C27
-rw-r--r--gcc/testsuite/g++.dg/other/nested-extern-2.cc3
-rw-r--r--gcc/testsuite/g++.dg/other/nested-extern.cc1
-rw-r--r--gcc/testsuite/g++.dg/template/scope5.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/missed-error2.C7
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash3.C5
21 files changed, 206 insertions, 178 deletions
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 0754982..44c9d24 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -980,21 +980,17 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
/* Map block scope extern declarations to visible declarations with the
same name and type in outer scopes if any. */
- if (cp_function_chain->extern_decl_map
- && VAR_OR_FUNCTION_DECL_P (stmt)
- && DECL_EXTERNAL (stmt))
- {
- struct cxx_int_tree_map *h, in;
- in.uid = DECL_UID (stmt);
- h = cp_function_chain->extern_decl_map->find_with_hash (&in, in.uid);
- if (h)
- {
- *stmt_p = h->to;
- TREE_USED (h->to) |= TREE_USED (stmt);
- *walk_subtrees = 0;
- return NULL;
- }
- }
+ if (VAR_OR_FUNCTION_DECL_P (stmt) && DECL_LOCAL_DECL_P (stmt))
+ if (tree alias = DECL_LOCAL_DECL_ALIAS (stmt))
+ {
+ if (alias != error_mark_node)
+ {
+ *stmt_p = alias;
+ TREE_USED (alias) |= TREE_USED (stmt);
+ }
+ *walk_subtrees = 0;
+ return NULL;
+ }
if (TREE_CODE (stmt) == INTEGER_CST
&& TYPE_REF_P (TREE_TYPE (stmt))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e5a2ff2..4672561 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1926,7 +1926,6 @@ struct GTY(()) language_function {
/* Tracking possibly infinite loops. This is a vec<tree> only because
vec<bool> doesn't work with gtype. */
vec<tree, va_gc> *infinite_loops;
- hash_table<cxx_int_tree_map_hasher> *extern_decl_map;
};
/* The current C++-specific per-function global variables. */
@@ -2697,6 +2696,7 @@ struct GTY(()) lang_decl_min {
In a lambda-capture proxy VAR_DECL, this is DECL_CAPTURED_VARIABLE.
In a function-scope TREE_STATIC VAR_DECL or IMPLICIT_TYPEDEF_P TYPE_DECL,
this is DECL_DISCRIMINATOR.
+ In a DECL_LOCAL_DECL_P decl, this is the namespace decl it aliases.
Otherwise, in a class-scope DECL, this is DECL_ACCESS. */
tree access;
};
@@ -4023,6 +4023,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define DECL_LOCAL_DECL_P(NODE) \
DECL_LANG_FLAG_0 (VAR_OR_FUNCTION_DECL_CHECK (NODE))
+/* The namespace-scope decl a DECL_LOCAL_DECL_P aliases. */
+#define DECL_LOCAL_DECL_ALIAS(NODE) \
+ DECL_ACCESS ((gcc_checking_assert (DECL_LOCAL_DECL_P (NODE)), NODE))
+
/* Nonzero if NODE is the target for genericization of 'return' stmts
in constructors/destructors of targetm.cxx.cdtor_returns_this targets. */
#define LABEL_DECL_CDTOR(NODE) \
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
{
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fd48a21..db3035d 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -5567,6 +5567,22 @@ mark_used (tree decl, tsubst_flags_t complain)
return false;
}
+ if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_LOCAL_DECL_P (decl))
+ {
+ if (!DECL_LANG_SPECIFIC (decl))
+ /* An unresolved dependent local extern. */
+ return true;
+
+ DECL_ODR_USED (decl) = 1;
+ auto alias = DECL_LOCAL_DECL_ALIAS (decl);
+ if (!alias || alias == error_mark_node)
+ return true;
+
+ /* Process the underlying decl. */
+ decl = alias;
+ TREE_USED (decl) = true;
+ }
+
cp_warn_deprecated_use (decl, complain);
/* We can only check DECL_ODR_USED on variables or functions with
@@ -5650,14 +5666,7 @@ mark_used (tree decl, tsubst_flags_t complain)
&& !DECL_ARTIFICIAL (decl)
&& !decl_defined_p (decl)
&& no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
- {
- if (is_local_extern (decl))
- /* There's no way to define a local extern, and adding it to
- the vector interferes with GC, so give an error now. */
- no_linkage_error (decl);
- else
- vec_safe_push (no_linkage_decls, decl);
- }
+ vec_safe_push (no_linkage_decls, decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index ea0bfdc..e3f3712 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
static cxx_binding *cxx_binding_make (tree value, tree type);
static cp_binding_level *innermost_nonclass_level (void);
+static tree do_pushdecl_with_scope (tree x, cp_binding_level *, bool hiding);
static void set_identifier_type_value_with_scope (tree id, tree decl,
cp_binding_level *b);
static name_hint maybe_suggest_missing_std_header (location_t location,
@@ -2921,108 +2922,66 @@ set_decl_context_in_fn (tree ctx, tree decl)
DECL_CONTEXT (decl) = ctx;
}
-/* DECL is a local-scope decl with linkage. SHADOWED is true if the
- name is already bound at the current level.
-
- [basic.link] If there is a visible declaration of an entity with
- linkage having the same name and type, ignoring entities declared
- outside the innermost enclosing namespace scope, the block scope
- declaration declares that same entity and receives the linkage of
- the previous declaration.
-
- Also, make sure that this decl matches any existing external decl
- in the enclosing namespace. */
+/* DECL is a local extern decl. Find or create the namespace-scope
+ decl that it aliases. Also, determines the linkage of DECL. */
static void
-set_local_extern_decl_linkage (tree decl, bool shadowed)
+push_local_extern_decl_alias (tree decl)
{
- tree ns_value = decl; /* Unique marker. */
-
- if (!shadowed)
- {
- tree loc_value = innermost_non_namespace_value (DECL_NAME (decl));
- if (!loc_value)
- {
- ns_value
- = find_namespace_value (current_namespace, DECL_NAME (decl));
- loc_value = ns_value;
- }
- if (loc_value == error_mark_node
- /* An ambiguous lookup. */
- || (loc_value && TREE_CODE (loc_value) == TREE_LIST))
- loc_value = NULL_TREE;
-
- for (ovl_iterator iter (loc_value); iter; ++iter)
- if (!iter.hidden_p ()
- && (TREE_STATIC (*iter) || DECL_EXTERNAL (*iter))
- && decls_match (*iter, decl))
- {
- /* The standard only says that the local extern inherits
- linkage from the previous decl; in particular, default
- args are not shared. Add the decl into a hash table to
- make sure only the previous decl in this case is seen
- by the middle end. */
- struct cxx_int_tree_map *h;
-
- /* We inherit the outer decl's linkage. But we're a
- different decl. */
- TREE_PUBLIC (decl) = TREE_PUBLIC (*iter);
-
- if (cp_function_chain->extern_decl_map == NULL)
- cp_function_chain->extern_decl_map
- = hash_table<cxx_int_tree_map_hasher>::create_ggc (20);
-
- h = ggc_alloc<cxx_int_tree_map> ();
- h->uid = DECL_UID (decl);
- h->to = *iter;
- cxx_int_tree_map **loc = cp_function_chain->extern_decl_map
- ->find_slot (h, INSERT);
- *loc = h;
- break;
- }
- }
+ if (dependent_type_p (TREE_TYPE (decl)))
+ return;
+ /* EH specs were not part of the function type prior to c++17, but
+ we still can't go pushing dependent eh specs into the namespace. */
+ if (cxx_dialect < cxx17
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && (value_dependent_expression_p
+ (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)))))
+ return;
- if (TREE_PUBLIC (decl))
- {
- /* DECL is externally visible. Make sure it matches a matching
- decl in the namespace scope. We only really need to check
- this when inserting the decl, not when we find an existing
- match in the current scope. However, in practice we're
- going to be inserting a new decl in the majority of cases --
- who writes multiple extern decls for the same thing in the
- same local scope? Doing it here often avoids a duplicate
- namespace lookup. */
+ gcc_checking_assert (!DECL_LANG_SPECIFIC (decl)
+ || !DECL_TEMPLATE_INFO (decl));
+ if (DECL_LANG_SPECIFIC (decl) && DECL_LOCAL_DECL_ALIAS (decl))
+ /* We're instantiating a non-dependent local decl, it already
+ knows the alias. */
+ return;
- /* Avoid repeating a lookup. */
- if (ns_value == decl)
- ns_value = find_namespace_value (current_namespace, DECL_NAME (decl));
+ tree alias = NULL_TREE;
- if (ns_value == error_mark_node
- || (ns_value && TREE_CODE (ns_value) == TREE_LIST))
- ns_value = NULL_TREE;
+ if (DECL_SIZE (decl) && !TREE_CONSTANT (DECL_SIZE (decl)))
+ /* Do not let a VLA creep into a namespace. Diagnostic will be
+ emitted in layout_var_decl later. */
+ alias = error_mark_node;
+ else
+ {
+ /* First look for a decl that matches. */
+ tree ns = CP_DECL_CONTEXT (decl);
+ tree binding = find_namespace_value (ns, DECL_NAME (decl));
- for (ovl_iterator iter (ns_value); iter; ++iter)
- {
- tree other = *iter;
-
- if (!(TREE_PUBLIC (other) || DECL_EXTERNAL (other)))
- ; /* Not externally visible. */
- else if (DECL_EXTERN_C_P (decl) && DECL_EXTERN_C_P (other))
- ; /* Both are extern "C", we'll check via that mechanism. */
- else if (TREE_CODE (other) != TREE_CODE (decl)
- || ((VAR_P (decl) || matching_fn_p (other, decl))
- && !comptypes (TREE_TYPE (decl), TREE_TYPE (other),
- COMPARE_REDECLARATION)))
+ if (binding && TREE_CODE (binding) != TREE_LIST)
+ for (ovl_iterator iter (binding); iter; ++iter)
+ if (decls_match (*iter, decl))
{
- auto_diagnostic_group d;
- if (permerror (DECL_SOURCE_LOCATION (decl),
- "local external declaration %q#D", decl))
- inform (DECL_SOURCE_LOCATION (other),
- "does not match previous declaration %q#D", other);
+ alias = *iter;
break;
}
+
+ if (!alias)
+ {
+ /* No existing namespace-scope decl. Make one. */
+ alias = copy_decl (decl);
+
+ /* This is the real thing. */
+ DECL_LOCAL_DECL_P (alias) = false;
+
+ /* Expected default linkage is from the namespace. */
+ TREE_PUBLIC (alias) = TREE_PUBLIC (ns);
+ alias = do_pushdecl_with_scope (alias, NAMESPACE_LEVEL (ns),
+ /* hiding= */true);
}
}
+
+ retrofit_lang_decl (decl);
+ DECL_LOCAL_DECL_ALIAS (decl) = alias;
}
/* Record DECL as belonging to the current lexical scope. Check for
@@ -3080,10 +3039,6 @@ do_pushdecl (tree decl, bool hiding)
old = binding->value;
}
- if (current_function_decl && VAR_OR_FUNCTION_DECL_P (decl)
- && DECL_EXTERNAL (decl))
- set_local_extern_decl_linkage (decl, old != NULL_TREE);
-
if (old == error_mark_node)
old = NULL_TREE;
@@ -3115,6 +3070,16 @@ do_pushdecl (tree decl, bool hiding)
/* We need to check and register the decl now. */
check_extern_c_conflict (match);
}
+ else if (slot && !hiding
+ && STAT_HACK_P (*slot) && STAT_DECL_HIDDEN_P (*slot))
+ {
+ /* Unhide the non-function. */
+ gcc_checking_assert (old == match);
+ if (!STAT_TYPE (*slot))
+ *slot = match;
+ else
+ STAT_DECL (*slot) = match;
+ }
return match;
}
@@ -3190,12 +3155,21 @@ do_pushdecl (tree decl, bool hiding)
if (!instantiating_current_function_p ())
record_locally_defined_typedef (decl);
}
- else if (VAR_P (decl))
- maybe_register_incomplete_var (decl);
+ else
+ {
+ if (VAR_P (decl) && !DECL_LOCAL_DECL_P (decl))
+ maybe_register_incomplete_var (decl);
+
+ if (VAR_OR_FUNCTION_DECL_P (decl))
+ {
+ if (DECL_LOCAL_DECL_P (decl)
+ && TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+ push_local_extern_decl_alias (decl);
- if ((VAR_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
- && DECL_EXTERN_C_P (decl))
- check_extern_c_conflict (decl);
+ if (DECL_EXTERN_C_P (decl))
+ check_extern_c_conflict (decl);
+ }
+ }
}
else
add_decl_to_level (level, decl);
@@ -6871,20 +6845,6 @@ lookup_elaborated_type (tree name, TAG_how how)
return ret;
}
-/* Returns true iff DECL is a block-scope extern declaration of a function
- or variable. We will already have determined validity of the decl
- when pushing it. So we do not have to redo that lookup. */
-
-bool
-is_local_extern (tree decl)
-{
- if ((TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL))
- return DECL_LOCAL_DECL_P (decl);
-
- return false;
-}
-
/* The type TYPE is being declared. If it is a class template, or a
specialization of a class template, do any processing required and
perform error-checking. If IS_FRIEND is nonzero, this TYPE is
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 01643fb..d63ff10 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -342,7 +342,6 @@ extern tree lookup_qualified_name (tree scope, tree name,
extern tree lookup_qualified_name (tree scope, const char *name,
LOOK_want = LOOK_want::NORMAL,
bool = true);
-extern bool is_local_extern (tree);
extern bool pushdecl_class_level (tree);
extern tree pushdecl_namespace_level (tree, bool hiding = false);
extern bool push_class_level_binding (tree, tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 2002c05..7a61abf 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -41176,6 +41176,10 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
}
if (!found_in_scope)
+ /* This seems to ignore the existence of cleanup scopes?
+ What is the meaning for local extern decls? The local
+ extern is in this scope, but it is referring to a decl that
+ is namespace scope. */
for (tree d = current_binding_level->names; d; d = TREE_CHAIN (d))
if (d == decl)
{
@@ -41205,6 +41209,16 @@ cp_parser_oacc_declare (cp_parser *parser, cp_token *pragma_tok)
{
tree id;
+ if (DECL_LOCAL_DECL_P (decl))
+ /* We need to mark the aliased decl, as that is the entity
+ that is being referred to. This won't work for
+ dependent variables, but it didn't work for them before
+ DECL_LOCAL_DECL_P was a thing either. But then
+ dependent local extern variable decls are as rare as
+ hen's teeth. */
+ if (auto alias = DECL_LOCAL_DECL_ALIAS (decl))
+ decl = alias;
+
if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
id = get_identifier ("omp declare target link");
else
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1ab5435..3755aab 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -18104,13 +18104,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
}
else if (DECL_IMPLICIT_TYPEDEF_P (t))
/* We already did a pushtag. */;
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_LOCAL_DECL_P (decl)
- && DECL_OMP_DECLARE_REDUCTION_P (decl))
+ else if (VAR_OR_FUNCTION_DECL_P (decl)
+ && DECL_LOCAL_DECL_P (decl))
{
- DECL_CONTEXT (decl) = current_function_decl;
- pushdecl (decl);
- if (cp_check_omp_declare_reduction (decl))
+ if (TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ DECL_CONTEXT (decl) = NULL_TREE;
+ decl = pushdecl (decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (decl)
+ && cp_check_omp_declare_reduction (decl))
instantiate_body (pattern_decl, args, decl, true);
}
else
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-sfinae1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-sfinae1.C
index 5928894..a9acc20 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-sfinae1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-sfinae1.C
@@ -9,7 +9,7 @@ struct AddRvalueReferenceImpl { typedef T type; };
template <typename T>
struct AddRvalueReferenceImpl<T, typename BoolSink<false &&
[] { // { dg-error "lambda" "" { target c++17_down } }
- extern T &&tref;
+ extern void tref(T&&);
}>::type> {
typedef T &&type;
};
diff --git a/gcc/testsuite/g++.dg/init/pr42844.C b/gcc/testsuite/g++.dg/init/pr42844.C
index 9b7ed05..d616f45 100644
--- a/gcc/testsuite/g++.dg/init/pr42844.C
+++ b/gcc/testsuite/g++.dg/init/pr42844.C
@@ -49,7 +49,7 @@ template <class T>
void g ()
{
T const t; // { dg-error "uninitialized 'const" }
- extern T const text;
+ extern T const text; // { dg-error "conflicting declaration" }
}
template void g<H> ();
diff --git a/gcc/testsuite/g++.dg/lookup/extern-redecl1.C b/gcc/testsuite/g++.dg/lookup/extern-redecl1.C
index 18e675b..f3e9b69 100644
--- a/gcc/testsuite/g++.dg/lookup/extern-redecl1.C
+++ b/gcc/testsuite/g++.dg/lookup/extern-redecl1.C
@@ -1,18 +1,18 @@
extern int X; // { dg-message "previous declaration" }
-extern int Y (int); // { dg-message "previous declaration" }
+extern int Y (int); // { dg-message "old declaration" }
extern int Y (float);
-static int Z (int s)
+static int Z (int s) // { dg-message "old declaration" }
{
return s;
}
void Foo ()
{
- extern char X; // { dg-error "local external declaration" }
- extern char Y (int); // { dg-error "local external declaration" }
+ extern char X; // { dg-error "conflicting declaration" }
+ extern char Y (int); // { dg-error "ambiguating new declaration" }
extern int Y (float);
extern void Y (double);
- extern char Z (int);
+ extern char Z (int); // { dg-error "ambiguating new declaration" }
}
diff --git a/gcc/testsuite/g++.dg/lookup/koenig15.C b/gcc/testsuite/g++.dg/lookup/koenig15.C
index f317c01..6bf916a 100644
--- a/gcc/testsuite/g++.dg/lookup/koenig15.C
+++ b/gcc/testsuite/g++.dg/lookup/koenig15.C
@@ -4,10 +4,12 @@
namespace N {
struct S { };
void f(S);
+ void g(S);
}
namespace M {
void f(int);
+ void g(int);
}
void
@@ -40,6 +42,6 @@ void
fn3 ()
{
N::S s;
- extern void (*f)(char);
- f (s); // { dg-error "cannot convert" }
+ extern void (*g)(char);
+ g (s); // { dg-error "cannot convert" }
}
diff --git a/gcc/testsuite/g++.dg/lto/pr95677.C b/gcc/testsuite/g++.dg/lto/pr95677.C
new file mode 100644
index 0000000..520ef04
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr95677.C
@@ -0,0 +1,19 @@
+// PR c++/95677
+
+// { dg-do link }
+// { dg-require-effective-target lto }
+// { dg-options "-flto" }
+
+
+
+namespace {
+ void foo() {
+ extern int xx; // injects a *static*
+ xx = 0;
+ }
+ int xx = 1;
+}
+
+int main() {
+ xx = 2;
+}
diff --git a/gcc/testsuite/g++.dg/other/nested-extern-1.C b/gcc/testsuite/g++.dg/other/nested-extern-1.C
index 6533a2a..6c879e5 100644
--- a/gcc/testsuite/g++.dg/other/nested-extern-1.C
+++ b/gcc/testsuite/g++.dg/other/nested-extern-1.C
@@ -1,17 +1,21 @@
/* { dg-do run } */
-// { dg-additional-sources "nested-extern.cc" }
+// { dg-additional-options "-fpermissive" }
+// { dg-additional-sources "nested-extern-1.cc" }
/* PR 31775 */
-extern "C" void abort();
+extern int *p_otheri;
extern int *p;
int main()
{
- extern int i;
+ extern int i; // { dg-message "previous declaration" }
i = 1;
*p = 2;
- if (i == 2)
- abort ();
+ if (i != 2)
+ return 1;
+ if (p_otheri != p)
+ return 2;
return 0;
}
-static int i;
+// This is extern because of the injection above.
+static int i; // { dg-warning ".extern. and later .static" }
int *p = &i;
diff --git a/gcc/testsuite/g++.dg/other/nested-extern-1.cc b/gcc/testsuite/g++.dg/other/nested-extern-1.cc
new file mode 100644
index 0000000..7d70072
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/nested-extern-1.cc
@@ -0,0 +1,3 @@
+extern int i;
+
+int *p_otheri = &i;
diff --git a/gcc/testsuite/g++.dg/other/nested-extern-2.C b/gcc/testsuite/g++.dg/other/nested-extern-2.C
index 58f53e0..acd78ff 100644
--- a/gcc/testsuite/g++.dg/other/nested-extern-2.C
+++ b/gcc/testsuite/g++.dg/other/nested-extern-2.C
@@ -1,18 +1,27 @@
/* { dg-do run } */
-// { dg-additional-sources "nested-extern.cc" }
/* PR 31775 */
-extern "C" void abort();
-static int i;
-int *p = &i;
+// { dg-additional-sources "nested-extern-2.cc" }
+extern int *p_otheri;
+static int i; // #1
+int *p_si = &i;
int main()
{
int i;
- {
+ int *p_ai = &i;
+ {
+ // This is an alias of #1, not a different object
extern int i;
- i = 1;
- *p = 2;
- if (i == 2)
- abort ();
+ int *p_ei = &i;
+
+ *p_si = 1;
+ *p_ai = 2;
+ *p_ei = 3;
+ if (*p_si != 3)
+ return 1;
+ if (*p_ai != 2)
+ return 2;
+ if (*p_otheri != 17)
+ return 3;
}
return 0;
}
diff --git a/gcc/testsuite/g++.dg/other/nested-extern-2.cc b/gcc/testsuite/g++.dg/other/nested-extern-2.cc
new file mode 100644
index 0000000..da43380
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/nested-extern-2.cc
@@ -0,0 +1,3 @@
+int i = 17; // never touched
+
+int *p_otheri = &i;
diff --git a/gcc/testsuite/g++.dg/other/nested-extern.cc b/gcc/testsuite/g++.dg/other/nested-extern.cc
deleted file mode 100644
index 048f715..0000000
--- a/gcc/testsuite/g++.dg/other/nested-extern.cc
+++ /dev/null
@@ -1 +0,0 @@
-int i;
diff --git a/gcc/testsuite/g++.dg/template/scope5.C b/gcc/testsuite/g++.dg/template/scope5.C
index 629225c..cf23a08 100644
--- a/gcc/testsuite/g++.dg/template/scope5.C
+++ b/gcc/testsuite/g++.dg/template/scope5.C
@@ -57,10 +57,12 @@ enum { a = b::e<0>::f };
template <typename> class au;
template <typename av> struct ac : ao<av> { typedef c::e<am::an> aq; };
template <typename aw, typename i, typename ax> void ay(aw, i, ax) {
- au<c::e<ap<typename ak<i>::o>::f> > az();
+ // Not sure if this has been creduced from an initialization of a
+ // variable to a block-scope extern function decl
+ au<c::e<ap<typename ak<i>::o>::f> > az2();
}
void v() {
ad a;
- void az();
- ay(az, a, v);
+ void az1();
+ ay(az1, a, v);
}
diff --git a/gcc/testsuite/g++.old-deja/g++.law/missed-error2.C b/gcc/testsuite/g++.old-deja/g++.law/missed-error2.C
index eaf8c01..7ae494b 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/missed-error2.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/missed-error2.C
@@ -1,4 +1,5 @@
// { dg-do assemble }
+// { dg-additional-options -fpermissive }
// GROUPS passed missed-error
// missed-error file
// From: ndc!don@csvax.cs.caltech.edu (Don Erway)
@@ -20,14 +21,14 @@ inline double max(double a, double b) {return a > b ? a : b;}; // { dg-message "
// { dg-error "extra ';'" "extra ;" { target c++98_only } .-1 }
int main() {
+ // we treat this as-if extern
static void foo(int i, int j, double x, double y) ;// { dg-error "" } .*
foo(4, -37, 14.39, 14.38);
}
-// 971006 we no longer give an error for this since we emit a hard error
-// about the declaration above
-static void foo(int i, int j, double x, double y) {
+static void foo(int i, int j, double x, double y) // { dg-warning ".extern." }
+{
std::cout << "Max(int): " << max(i,j) << " Max(double): " <<
max(x,y) << '\n';
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash3.C b/gcc/testsuite/g++.old-deja/g++.pt/crash3.C
index e5b3f25..52701b7 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/crash3.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash3.C
@@ -5,12 +5,13 @@ class CVector {
public:
CVector<int> f() const
{
- CVector<int> v();
+ // local-extern :)
+ CVector<int> v(); // { dg-message "old declaration" }
return v; // { dg-error "convert" }
}
CVector<long> g() const
{
- CVector<long> v();
+ CVector<long> v(); // { dg-error "ambiguating new" }
return v; // { dg-error "convert" }
}
};