aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/decl.c45
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/net46.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/linkage3.C5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/linkage4.C11
4 files changed, 42 insertions, 21 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 789fe4e..cd42511 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2921,8 +2921,7 @@ decls_match (newdecl, olddecl)
}
/* If NEWDECL is `static' and an `extern' was seen previously,
- warn about it. (OLDDECL may be NULL_TREE; NAME contains
- information about previous usage as an `extern'.)
+ warn about it. OLDDECL is the previous declaration.
Note that this does not apply to the C++ case of declaring
a variable `extern const' and then later `const'.
@@ -2934,33 +2933,31 @@ static void
warn_extern_redeclared_static (newdecl, olddecl)
tree newdecl, olddecl;
{
- tree name;
-
static const char *explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
static const char *implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
+ tree name;
+
if (TREE_CODE (newdecl) == TYPE_DECL)
return;
+ /* If the old declaration was `static', or the new one isn't, then
+ then everything is OK. */
+ if (DECL_THIS_STATIC (olddecl) || !DECL_THIS_STATIC (newdecl))
+ return;
+
+ /* It's OK to declare a builtin function as `static'. */
+ if (TREE_CODE (olddecl) == FUNCTION_DECL
+ && DECL_ARTIFICIAL (olddecl))
+ return;
+
name = DECL_ASSEMBLER_NAME (newdecl);
- if (TREE_PUBLIC (name) && DECL_THIS_STATIC (newdecl))
- {
- /* It's okay to redeclare an ANSI built-in function as static,
- or to declare a non-ANSI built-in function as anything. */
- if (! (TREE_CODE (newdecl) == FUNCTION_DECL
- && olddecl != NULL_TREE
- && TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_ARTIFICIAL (olddecl)))
- {
- cp_pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
- ? implicit_extern_static_warning
- : explicit_extern_static_warning, newdecl);
- if (olddecl != NULL_TREE)
- cp_pedwarn_at ("previous declaration of `%D'", olddecl);
- }
- }
+ cp_pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
+ ? implicit_extern_static_warning
+ : explicit_extern_static_warning, newdecl);
+ cp_pedwarn_at ("previous declaration of `%D'", olddecl);
}
/* Handle when a new declaration NEWDECL has the same name as an old
@@ -3047,6 +3044,14 @@ duplicate_decls (newdecl, olddecl)
/* Discard the old built-in function. */
return 0;
}
+
+ if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
+ {
+ /* If a builtin function is redeclared as `static', merge
+ the declarations, but make the original one static. */
+ DECL_THIS_STATIC (olddecl) = 1;
+ TREE_PUBLIC (olddecl) = 0;
+ }
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net46.C b/gcc/testsuite/g++.old-deja/g++.mike/net46.C
index ac79501..8439c34 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/net46.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/net46.C
@@ -4,7 +4,7 @@
int fail = 1;
-static void *operator new(size_t size) throw (std::bad_alloc) {
+void *operator new(size_t size) throw (std::bad_alloc) {
--fail;
return (void*) 0;
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/linkage3.C b/gcc/testsuite/g++.old-deja/g++.other/linkage3.C
new file mode 100644
index 0000000..d32d770
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/linkage3.C
@@ -0,0 +1,5 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+extern "C" void f (); // ERROR - previous declaration
+static void f () {} // ERROR - extern redeclared static
diff --git a/gcc/testsuite/g++.old-deja/g++.other/linkage4.C b/gcc/testsuite/g++.old-deja/g++.other/linkage4.C
new file mode 100644
index 0000000..65772f7
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/linkage4.C
@@ -0,0 +1,11 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+static int strlen (const char*) { return 0; }
+
+template <int (*)(const char*)>
+void f () {}
+
+// Check that the strlen declaration here is given internal linkage by
+// using it as a non-type template argument, and expecting an error.
+template void f<strlen>(); // ERROR - no matching template