summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2013-05-20 20:05:40 +0000
committerburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2013-05-20 20:05:40 +0000
commitda5c730d38bf663ef786ec2138bca9daa6607f61 (patch)
tree39687a43e4fe7d4930831b3a86e693cd333c6c40 /gcc
parent7a914593ca6c0be50165cad4fe5ae7909ab19827 (diff)
downloadgcc-da5c730d38bf663ef786ec2138bca9daa6607f61.tar.gz
2013-05-20 Tobias Burnus <burnus@net-b.de>
PR fortran/48858 * decl.c (add_global_entry): Use nonbinding name only for F2003 or if no binding label exists. (gfc_match_entry): Update calls. * parse.c (gfc_global_used): Improve error message. (add_global_procedure): Use nonbinding name only for F2003 or if no binding label exists. (gfc_parse_file): Update call. * resolve.c (resolve_global_procedure): Use binding name when available. * trans-decl.c (gfc_get_extern_function_decl): Ditto. 2013-05-20 Tobias Burnus <burnus@net-b.de> PR fortran/48858 * gfortran.dg/binding_label_tests_17.f90: New. * gfortran.dg/binding_label_tests_18.f90: New. * gfortran.dg/binding_label_tests_19.f90: New. * gfortran.dg/binding_label_tests_20.f90: New. * gfortran.dg/binding_label_tests_21.f90: New. * gfortran.dg/binding_label_tests_22.f90: New. * gfortran.dg/binding_label_tests_23.f90: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199119 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fortran/ChangeLog14
-rw-r--r--gcc/fortran/decl.c71
-rw-r--r--gcc/fortran/parse.c60
-rw-r--r--gcc/fortran/resolve.c2
-rw-r--r--gcc/fortran/trans-decl.c3
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/gfortran.dg/binding_label_tests_17.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/binding_label_tests_18.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/binding_label_tests_19.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/binding_label_tests_20.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/binding_label_tests_21.f908
-rw-r--r--gcc/testsuite/gfortran.dg/binding_label_tests_22.f908
-rw-r--r--gcc/testsuite/gfortran.dg/binding_label_tests_23.f9021
13 files changed, 202 insertions, 37 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index fca9761697b..08b4602dd86 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,6 +1,20 @@
2013-05-20 Tobias Burnus <burnus@net-b.de>
PR fortran/48858
+ * decl.c (add_global_entry): Use nonbinding name
+ only for F2003 or if no binding label exists.
+ (gfc_match_entry): Update calls.
+ * parse.c (gfc_global_used): Improve error message.
+ (add_global_procedure): Use nonbinding name
+ only for F2003 or if no binding label exists.
+ (gfc_parse_file): Update call.
+ * resolve.c (resolve_global_procedure): Use binding
+ name when available.
+ * trans-decl.c (gfc_get_extern_function_decl): Ditto.
+
+2013-05-20 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/48858
* decl.c (gfc_match_bind_c_stmt): Add gfc_notify_std.
* match.c (gfc_match_common): Don't add commons to gsym.
* resolve.c (resolve_common_blocks): Add to gsym and
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 06a049c6fdd..cb449a2f7a6 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -5354,27 +5354,56 @@ cleanup:
to return false upon finding an existing global entry. */
static bool
-add_global_entry (const char *name, int sub)
+add_global_entry (const char *name, const char *binding_label, bool sub)
{
gfc_gsymbol *s;
enum gfc_symbol_type type;
- s = gfc_get_gsymbol(name);
type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
- if (s->defined
- || (s->type != GSYM_UNKNOWN
- && s->type != type))
- gfc_global_used(s, NULL);
- else
+ /* Only in Fortran 2003: For procedures with a binding label also the Fortran
+ name is a global identifier. */
+ if (!binding_label || gfc_notification_std (GFC_STD_F2008))
{
- s->type = type;
- s->where = gfc_current_locus;
- s->defined = 1;
- s->ns = gfc_current_ns;
- return true;
+ s = gfc_get_gsymbol (name);
+
+ if (s->defined || (s->type != GSYM_UNKNOWN && s->type != type))
+ {
+ gfc_global_used(s, NULL);
+ return false;
+ }
+ else
+ {
+ s->type = type;
+ s->where = gfc_current_locus;
+ s->defined = 1;
+ s->ns = gfc_current_ns;
+ }
}
- return false;
+
+ /* Don't add the symbol multiple times. */
+ if (binding_label
+ && (!gfc_notification_std (GFC_STD_F2008)
+ || strcmp (name, binding_label) != 0))
+ {
+ s = gfc_get_gsymbol (binding_label);
+
+ if (s->defined || (s->type != GSYM_UNKNOWN && s->type != type))
+ {
+ gfc_global_used(s, NULL);
+ return false;
+ }
+ else
+ {
+ s->type = type;
+ s->binding_label = binding_label;
+ s->where = gfc_current_locus;
+ s->defined = 1;
+ s->ns = gfc_current_ns;
+ }
+ }
+
+ return true;
}
@@ -5502,10 +5531,6 @@ gfc_match_entry (void)
if (state == COMP_SUBROUTINE)
{
- /* An entry in a subroutine. */
- if (!gfc_current_ns->parent && !add_global_entry (name, 1))
- return MATCH_ERROR;
-
m = gfc_match_formal_arglist (entry, 0, 1);
if (m != MATCH_YES)
return MATCH_ERROR;
@@ -5527,6 +5552,11 @@ gfc_match_entry (void)
return MATCH_ERROR;
}
+ if (!gfc_current_ns->parent
+ && !add_global_entry (name, entry->binding_label, true))
+ return MATCH_ERROR;
+
+ /* An entry in a subroutine. */
if (!gfc_add_entry (&entry->attr, entry->name, NULL)
|| !gfc_add_subroutine (&entry->attr, entry->name, NULL))
return MATCH_ERROR;
@@ -5542,9 +5572,6 @@ gfc_match_entry (void)
ENTRY f() RESULT (r)
can't be written as
ENTRY f RESULT (r). */
- if (!gfc_current_ns->parent && !add_global_entry (name, 0))
- return MATCH_ERROR;
-
old_loc = gfc_current_locus;
if (gfc_match_eos () == MATCH_YES)
{
@@ -5593,6 +5620,10 @@ gfc_match_entry (void)
entry->result = entry;
}
}
+
+ if (!gfc_current_ns->parent
+ && !add_global_entry (name, entry->binding_label, false))
+ return MATCH_ERROR;
}
if (gfc_match_eos () != MATCH_YES)
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 83011138ea5..ba1730a8f18 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -4232,8 +4232,12 @@ gfc_global_used (gfc_gsymbol *sym, locus *where)
name = NULL;
}
- gfc_error("Global name '%s' at %L is already being used as a %s at %L",
- sym->name, where, name, &sym->where);
+ if (sym->binding_label)
+ gfc_error ("Global binding name '%s' at %L is already being used as a %s "
+ "at %L", sym->binding_label, where, name, &sym->where);
+ else
+ gfc_error ("Global name '%s' at %L is already being used as a %s at %L",
+ sym->name, where, name, &sym->where);
}
@@ -4342,22 +4346,48 @@ loop:
/* Add a procedure name to the global symbol table. */
static void
-add_global_procedure (int sub)
+add_global_procedure (bool sub)
{
gfc_gsymbol *s;
- s = gfc_get_gsymbol(gfc_new_block->name);
+ /* Only in Fortran 2003: For procedures with a binding label also the Fortran
+ name is a global identifier. */
+ if (!gfc_new_block->binding_label || gfc_notification_std (GFC_STD_F2008))
+ {
+ s = gfc_get_gsymbol (gfc_new_block->name);
- if (s->defined
- || (s->type != GSYM_UNKNOWN
- && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
- gfc_global_used(s, NULL);
- else
+ if (s->defined
+ || (s->type != GSYM_UNKNOWN
+ && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
+ gfc_global_used(s, NULL);
+ else
+ {
+ s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
+ s->where = gfc_current_locus;
+ s->defined = 1;
+ s->ns = gfc_current_ns;
+ }
+ }
+
+ /* Don't add the symbol multiple times. */
+ if (gfc_new_block->binding_label
+ && (!gfc_notification_std (GFC_STD_F2008)
+ || strcmp (gfc_new_block->name, gfc_new_block->binding_label) != 0))
{
- s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
- s->where = gfc_current_locus;
- s->defined = 1;
- s->ns = gfc_current_ns;
+ s = gfc_get_gsymbol (gfc_new_block->binding_label);
+
+ if (s->defined
+ || (s->type != GSYM_UNKNOWN
+ && s->type != (sub ? GSYM_SUBROUTINE : GSYM_FUNCTION)))
+ gfc_global_used(s, NULL);
+ else
+ {
+ s->type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
+ s->binding_label = gfc_new_block->binding_label;
+ s->where = gfc_current_locus;
+ s->defined = 1;
+ s->ns = gfc_current_ns;
+ }
}
}
@@ -4556,7 +4586,7 @@ loop:
break;
case ST_SUBROUTINE:
- add_global_procedure (1);
+ add_global_procedure (true);
push_state (&s, COMP_SUBROUTINE, gfc_new_block);
accept_statement (st);
parse_progunit (ST_NONE);
@@ -4564,7 +4594,7 @@ loop:
break;
case ST_FUNCTION:
- add_global_procedure (0);
+ add_global_procedure (false);
push_state (&s, COMP_FUNCTION, gfc_new_block);
accept_statement (st);
parse_progunit (ST_NONE);
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 06fa3018f4c..f3607b41774 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -2333,7 +2333,7 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION;
- gsym = gfc_get_gsymbol (sym->name);
+ gsym = gfc_get_gsymbol (sym->binding_label ? sym->binding_label : sym->name);
if ((gsym->type != GSYM_UNKNOWN && gsym->type != type))
gfc_global_used (gsym, where);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 4c0b1da5af1..795057b9928 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1643,7 +1643,8 @@ gfc_get_extern_function_decl (gfc_symbol * sym)
/* See if this is an external procedure from the same file. If so,
return the backend_decl. */
- gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name);
+ gsym = gfc_find_gsymbol (gfc_gsym_root, sym->binding_label
+ ? sym->binding_label : sym->name);
if ((!sym->attr.use_assoc || sym->attr.if_source != IFSRC_DECL)
&& !sym->backend_decl
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a8611933715..d6b531c5709 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,17 @@
2013-05-20 Tobias Burnus <burnus@net-b.de>
PR fortran/48858
+ * gfortran.dg/binding_label_tests_17.f90: New.
+ * gfortran.dg/binding_label_tests_18.f90: New.
+ * gfortran.dg/binding_label_tests_19.f90: New.
+ * gfortran.dg/binding_label_tests_20.f90: New.
+ * gfortran.dg/binding_label_tests_21.f90: New.
+ * gfortran.dg/binding_label_tests_22.f90: New.
+ * gfortran.dg/binding_label_tests_23.f90: New.
+
+2013-05-20 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/48858
* gfortran.dg/test_common_binding_labels.f03: Update dg-error.
* gfortran.dg/test_common_binding_labels_2_main.f03: Ditto.
* gfortran.dg/test_common_binding_labels_3_main.f03: Ditto.
diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_17.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_17.f90
new file mode 100644
index 00000000000..4243ffbdb1e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/binding_label_tests_17.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+!
+! PR fortran/48858
+!
+subroutine foo() bind(C, name="bar") ! { dg-error "Global binding name 'bar' at .1. is already being used as a SUBROUTINE at .2." }
+end subroutine foo
+
+subroutine sub() bind(C, name="bar") ! { dg-error "Global binding name 'bar' at .1. is already being used as a SUBROUTINE at .2." }
+end subroutine sub
+
diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_18.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_18.f90
new file mode 100644
index 00000000000..548d367e3d2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/binding_label_tests_18.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+!
+! PR fortran/48858
+!
+subroutine foo() ! { dg-error "Global name 'foo' at .1. is already being used as a SUBROUTINE at .2." }
+end subroutine foo
+
+subroutine foo() ! { dg-error "Global name 'foo' at .1. is already being used as a SUBROUTINE at .2." }
+end subroutine foo
+
diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_19.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_19.f90
new file mode 100644
index 00000000000..a6f63e68588
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/binding_label_tests_19.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+!
+! PR fortran/48858
+!
+subroutine foo() bind(C,name="bar")
+end subroutine foo
+
+subroutine foo() bind(C,name="sub")
+end subroutine foo
+
diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_20.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_20.f90
new file mode 100644
index 00000000000..2b0da431697
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/binding_label_tests_20.f90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "-std=f2003" }
+!
+! PR fortran/48858
+!
+subroutine foo() bind(C,name="bar") ! { dg-error "Global name 'foo' at .1. is already being used as a SUBROUTINE at .2." }
+end subroutine foo
+
+subroutine foo() bind(C,name="sub") ! { dg-error "Global name 'foo' at .1. is already being used as a SUBROUTINE at .2." }
+end subroutine foo
+
diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_21.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_21.f90
new file mode 100644
index 00000000000..0519d0f1d2d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/binding_label_tests_21.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+!
+! PR fortran/48858
+!
+subroutine foo() bind(C, name="bar") ! { dg-error "Global binding name 'bar' at .1. is already being used as a SUBROUTINE at .2." }
+entry sub() bind(C, name="bar") ! { dg-error "Global binding name 'bar' at .1. is already being used as a SUBROUTINE at .2." }
+end subroutine foo
+
diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_22.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_22.f90
new file mode 100644
index 00000000000..b136754d593
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/binding_label_tests_22.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+!
+! PR fortran/48858
+!
+subroutine foo() ! { dg-error "Global name 'foo' at .1. is already being used as a SUBROUTINE at .2." }
+entry foo() ! { dg-error "Global name 'foo' at .1. is already being used as a SUBROUTINE at .2." }
+end subroutine foo
+
diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_23.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_23.f90
new file mode 100644
index 00000000000..ba9e61550f4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/binding_label_tests_23.f90
@@ -0,0 +1,21 @@
+! { dg-do run }
+!
+! PR fortran/48858
+!
+integer function foo(x)
+ integer :: x
+ call abort()
+ foo = 99
+end function foo
+
+integer function other() bind(C, name="bar")
+ other = 42
+end function other
+
+program test
+ interface
+ integer function foo() bind(C, name="bar")
+ end function foo
+ end interface
+ if (foo() /= 42) call abort() ! Ensure that the binding name is all what counts
+end program test