aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/c-decl.c55
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.dg/inline1.c8
-rw-r--r--gcc/testsuite/gcc.dg/inline2.c5
-rw-r--r--gcc/testsuite/gcc.dg/inline3.c7
-rw-r--r--gcc/testsuite/gcc.dg/inline4.c6
-rw-r--r--gcc/testsuite/gcc.dg/inline5.c6
8 files changed, 69 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3d7f993..2afa66c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2005-06-28 Eric Christopher <echristo@redhat.com>
+
+ PR c/22052
+ PR c/21975
+ * c-decl.c (diagnose_mismatched_decls): Define DECL_EXTERN_INLINE.
+ Use. Fix detection of invalid extern inline redefinition.
+
2005-06-28 Diego Novillo <dnovillo@redhat.com>
* tree-optimize.c (init_tree_optimization_passes): Fix typo.
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index eececb1..21248ae 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -1154,6 +1154,9 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
bool warned = false;
bool retval = true;
+#define DECL_EXTERN_INLINE(DECL) (DECL_DECLARED_INLINE_P (DECL) \
+ && DECL_EXTERNAL (DECL))
+
/* If we have error_mark_node for either decl or type, just discard
the previous decl - we're in an error cascade already. */
if (olddecl == error_mark_node || newdecl == error_mark_node)
@@ -1282,6 +1285,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
Multiple definitions are not allowed (6.9p3,5) but GCC permits
two definitions if one is 'extern inline' and one is not. The non-
extern-inline definition supersedes the extern-inline definition. */
+
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
/* If you declare a built-in function name as static, or
@@ -1304,45 +1308,25 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
{
if (DECL_INITIAL (olddecl))
{
- /* If both decls have extern inline and are in the same TU,
- reject the new decl. */
- if (DECL_DECLARED_INLINE_P (olddecl)
- && DECL_EXTERNAL (olddecl)
- && DECL_DECLARED_INLINE_P (newdecl)
- && DECL_EXTERNAL (newdecl)
+ /* If both decls are in the same TU and the new declaration
+ isn't overridding an extern inline reject the new decl.
+ When we handle c99 style inline rules we'll want to reject
+ the following:
+
+ DECL_EXTERN_INLINE (olddecl)
+ && !DECL_EXTERN_INLINE (newdecl)
+
+ if they're in the same translation unit. Until we implement
+ the full semantics we accept the construct. */
+ if (!(DECL_EXTERN_INLINE (olddecl)
+ && !DECL_EXTERN_INLINE (newdecl))
&& same_translation_unit_p (newdecl, olddecl))
{
error ("%Jredefinition of %qD", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
- /* If both decls have not extern inline, reject the new decl. */
- if (!DECL_DECLARED_INLINE_P (olddecl)
- && !DECL_EXTERNAL (olddecl)
- && !DECL_DECLARED_INLINE_P (newdecl)
- && !DECL_EXTERNAL (newdecl))
- {
- error ("%Jredefinition of %qD", newdecl, newdecl);
- locate_old_decl (olddecl, error);
- return false;
- }
- /* If the new decl is declared as extern inline, error if they are
- in the same TU, otherwise retain the old decl. */
- if (!DECL_DECLARED_INLINE_P (olddecl)
- && !DECL_EXTERNAL (olddecl)
- && DECL_DECLARED_INLINE_P (newdecl)
- && DECL_EXTERNAL (newdecl))
- {
- if (same_translation_unit_p (newdecl, olddecl))
- {
- error ("%Jredefinition of %qD", newdecl, newdecl);
- locate_old_decl (olddecl, error);
- return false;
- }
- else
- retval = false;
- }
- }
+ }
}
/* If we have a prototype after an old-style function definition,
the argument types must be checked specially. */
@@ -1371,8 +1355,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
occur only in Objective C; see also above. (FIXME: Make
Objective C use normal builtins.) */
if (!DECL_IS_BUILTIN (olddecl)
- && !(DECL_EXTERNAL (olddecl)
- && DECL_DECLARED_INLINE_P (olddecl)))
+ && !DECL_EXTERN_INLINE (olddecl))
{
error ("%Jstatic declaration of %qD follows "
"non-static declaration", newdecl, newdecl);
@@ -1585,6 +1568,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (warned || pedwarned)
locate_old_decl (olddecl, pedwarned ? pedwarn : warning0);
+#undef DECL_EXTERN_INLINE
+
return retval;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3f6a4c5..1634814 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2005-06-28 Eric Christopher <echristo@redhat.com>
+
+ PR c/22052
+ PR c/21975
+ * gcc.dg/inline1.c: New test.
+ * gcc.dg/inline2.c: Ditto.
+ * gcc.dg/inline3.c: Ditto.
+ * gcc.dg/inline4.c: Ditto.
+ * gcc.dg/inline5.c: Ditto.
+
2005-06-28 Thomas Koenig <Thomas.Koenig@online.de>
PR libfortran/22142
diff --git a/gcc/testsuite/gcc.dg/inline1.c b/gcc/testsuite/gcc.dg/inline1.c
new file mode 100644
index 0000000..f7a7eb4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/inline1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -std=gnu89" } */
+/* This test is expected to fail with an error for the redefinition of foo.
+ This violates the constraint of 6.9#3 (no more than one external definition
+ of an identifier with internal linkage in the same translation unit). */
+static inline int foo(void) { return 1; } /* { dg-error "previous definition of" } */
+static inline int foo(void) { return 0; } /* { dg-error "redefinition of" } */
+
diff --git a/gcc/testsuite/gcc.dg/inline2.c b/gcc/testsuite/gcc.dg/inline2.c
new file mode 100644
index 0000000..ede4104
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/inline2.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -std=gnu89" } */
+/* This test should compile successfully. */
+extern inline int foo (void) { return 0; }
+inline int foo (void) { return 1; }
diff --git a/gcc/testsuite/gcc.dg/inline3.c b/gcc/testsuite/gcc.dg/inline3.c
new file mode 100644
index 0000000..bc755e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/inline3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -std=gnu89" } */
+/* This testcase should fail since we're redefining foo in the same
+ translation unit. */
+extern inline int foo(void) { return 0; }
+inline int foo (void) { return 1; } /* { dg-error "previous definition of" } */
+int foo (void) { return 2; } /* { dg-error "error: redefinition of" } */
diff --git a/gcc/testsuite/gcc.dg/inline4.c b/gcc/testsuite/gcc.dg/inline4.c
new file mode 100644
index 0000000..a5c7dda
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/inline4.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -std=gnu89" } */
+/* This testcase should fail since we're redefining foo in the same
+ translation unit. */
+int foo (void) { return 2; } /* { dg-error "previous definition of" } */
+extern inline int foo (void) { return 1; } /* { dg-error "redefinition of" } */
diff --git a/gcc/testsuite/gcc.dg/inline5.c b/gcc/testsuite/gcc.dg/inline5.c
new file mode 100644
index 0000000..86a2776
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/inline5.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -std=gnu89" } */
+/* This testcase should fail since we're redefining foo in the same
+ translation unit. */
+extern inline int foo (void) { return 2; } /* { dg-error "previous definition of" } */
+extern inline int foo (void) { return 1; } /* { dg-error "redefinition of" } */