diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/cp-gimplify.c | 26 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 3 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 25 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 186 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 1 | ||||
-rw-r--r-- | gcc/cp/parser.c | 14 | ||||
-rw-r--r-- | gcc/cp/pt.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-sfinae1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/pr42844.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/extern-redecl1.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/koenig15.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lto/pr95677.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/nested-extern-1.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/nested-extern-1.cc | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/nested-extern-2.C | 27 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/nested-extern-2.cc | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/nested-extern.cc | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/scope5.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.law/missed-error2.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/crash3.C | 5 |
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" } } }; |