diff mbox

[Fortran] Implement IMPLICIT NONE

Message ID 542C81C3.1010208@net-b.de
State New
Headers show

Commit Message

Tobias Burnus Oct. 1, 2014, 10:35 p.m. UTC
Tobias Burnus wrote:
> IMPLICIT NONE (external)
>
> While I have implemented is as vendor extension (-std=gnu)

Ups, I forgot to include the gcc/fortran/libgfortran.h change in the 
patch. See updated attachment.

> Build and regtested on x86-64-gnu-linux.
> OK for the trunk?

Tobias

Comments

FX Coudert Oct. 4, 2014, 9:27 a.m. UTC | #1
>> Build and regtested on x86-64-gnu-linux.
>> OK for the trunk?

Looks mostly OK, but I have one question: I don’t understand what the wording "Type IMPLICIT NONE statement” is supposed to mean. Why “type”?

FX
Tobias Burnus Oct. 4, 2014, 9:42 a.m. UTC | #2
FX wrote:
>>> Build and regtested on x86-64-gnu-linux.
>>> OK for the trunk?
> Looks mostly OK, but I have one question: I don’t understand what the wording "Type IMPLICIT NONE statement” is supposed to mean. Why “type”?

Well, I want to distinguish "IMPLICIT NONE (external)" which only 
applies to procedures from "IMPLICIT NONE" alias "IMPLICIT NONE (type)" 
which applies only to variables and function (return value) types. Thus,
   IMPLICIT NONE (external)
   IMPLICIT integer(a-z)
is valid while
   IMPLICIT NONE
   IMPLICIT integer(a-z)
is not.

If you have a better suggestion for the wording …

Tobias
FX Coudert Oct. 4, 2014, 9:53 a.m. UTC | #3
> If you have a better suggestion for the wording …

I’d suggest “IMPLICIT NONE (TYPE) statement at %C following an IMPLICIT statement” (and the other way around).

OK, with or without the wording change, I let you decide
Marek Polacek Oct. 6, 2014, 7:13 a.m. UTC | #4
On Thu, Oct 02, 2014 at 12:35:47AM +0200, Tobias Burnus wrote:
> Tobias Burnus wrote:
> >IMPLICIT NONE (external)
> >
> >While I have implemented is as vendor extension (-std=gnu)
> 
> Ups, I forgot to include the gcc/fortran/libgfortran.h change in the patch.
> See updated attachment.

Seems that gcc/fortran/libgfortran.h part is not committed, after
r215914 I get 

gcc/fortran/decl.c:2960:28: error: ‘GFC_STD_F2015’ was not declared in this scope
       if (!gfc_notify_std (GFC_STD_F2015, "IMPORT NONE with spec list at %C"))
                            ^
make[2]: *** [fortran/decl.o] Error 1

	Marek
Tobias Burnus Oct. 6, 2014, 7:20 a.m. UTC | #5
Hi Marek, hi all,

Tobias Burnus:
> Seems that gcc/fortran/libgfortran.h part is not committed, after
> r215914 I get 
> gcc/fortran/decl.c:2960:28: error: âGFC_STD_F2015â was not declared in this scope

Committing patches when having a cold doesn't seem to work. I don't have
access to the computer with SVN write permission, thus, I cannot fix it myself before
this evening.

Can someone commit the patch for me? It's the first chunk (= gcc/fortran/libgfortran.h)
at https://gcc.gnu.org/ml/gcc-patches/2014-10/msg00105.html

Thanks - and sorry for the breakage!

Tobias
Marek Polacek Oct. 6, 2014, 7:30 a.m. UTC | #6
Hi,

On Mon, Oct 06, 2014 at 09:20:50AM +0200, Tobias Burnus wrote:
> Committing patches when having a cold doesn't seem to work. I don't have

Having fight with cold last week, I know what you're talking about ;).

> access to the computer with SVN write permission, thus, I cannot fix it myself before
> this evening.
> 
> Can someone commit the patch for me? It's the first chunk (= gcc/fortran/libgfortran.h)
> at https://gcc.gnu.org/ml/gcc-patches/2014-10/msg00105.html

Sure, I'll commit it.

	Marek
Andreas Schwab Oct. 7, 2014, 6:16 p.m. UTC | #7
Tobias Burnus <burnus@net-b.de> writes:

> diff --git a/gcc/testsuite/gfortran.dg/implicit_4.f90 b/gcc/testsuite/gfortran.dg/implicit_4.f90
> index 2e871b0..9bf8d86 100644
> --- a/gcc/testsuite/gfortran.dg/implicit_4.f90
> +++ b/gcc/testsuite/gfortran.dg/implicit_4.f90
> @@ -5,13 +5,13 @@ IMPLICIT NONE ! { dg-error "Duplicate" }
>  END
>  
>  SUBROUTINE a
> -IMPLICIT REAL(b-j) ! { dg-error "cannot follow" }
> -implicit none      ! { dg-error "cannot follow" }
> +IMPLICIT REAL(b-j)
> +implicit none      ! { dg-error "Type IMPLICIT NONE statement at .1. following an IMPLICIT statement" }

That doesn't match.

/usr/local/gcc/gcc-20141007/gcc/testsuite/gfortran.dg/implicit_4.f90:9:103: Err\or: IMPLICIT NONE (type) statement at (1) following an IMPLICIT statement

Andreas.
diff mbox

Patch

2014-10-02  Tobias Burnus  <burnus@net-b.de>

gcc/fortran/
	* libgfortran.h (GFC_STD_F2015): Add.
	* decl.c (gfc_match_implicit_none): Handle spec list.
	(gfc_match_implicit): Move double intrinsic warning here.
	* gfortran.h (gfc_namespace): Add has_implicit_none_export:1.
	(gfc_set_implicit_none): Update interface.
	* interface.c (gfc_procedure_use): Add implicit-none external
	error check.
	* parse.c (accept_statement): Remove call.
	(verify_st_order): Permit that external-implict-none follows
	implicit statement.
	* symbol.c (gfc_set_implicit_none): Handle external/type
	implicit none.

gcc/testsuite/
	* gfortran.dg/implicit_14.f90: New.
	* gfortran.dg/implicit_15.f90: New.
	* gfortran.dg/implicit_4.f90: Update dg-error.

diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h
index df5c14f..338a75e 100644
--- a/gcc/fortran/libgfortran.h
+++ b/gcc/fortran/libgfortran.h
@@ -22,6 +22,8 @@  along with GCC; see the file COPYING3.  If not see
    Note that no features were obsoleted nor deleted in F2003.
    Please remember to keep those definitions in sync with
    gfortran.texi.  */
+/* For now, use F2015 = GFC_STD_GNU.  */
+#define GFC_STD_F2015	        (1<<5)	/* PLACEHOLDER for Fortran 2015.  */
 #define GFC_STD_F2008_TS	(1<<9)	/* POST-F2008 technical reports.  */
 #define GFC_STD_F2008_OBS	(1<<8)	/* Obsolescent in F2008.  */
 #define GFC_STD_F2008		(1<<7)	/* New in F2008.  */
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 0e0364c..bbf35ce 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -2946,7 +2946,50 @@  get_kind:
 match
 gfc_match_implicit_none (void)
 {
-  return (gfc_match_eos () == MATCH_YES) ? MATCH_YES : MATCH_NO;
+  char c;
+  match m;
+  char name[GFC_MAX_SYMBOL_LEN + 1];
+  bool type = false;
+  bool external = false;
+
+  gfc_gobble_whitespace ();
+  c = gfc_peek_ascii_char ();
+  if (c == '(')
+    {
+      (void) gfc_next_ascii_char ();
+      if (!gfc_notify_std (GFC_STD_F2015, "IMPORT NONE with spec list at %C"))
+	return MATCH_ERROR;
+      for(;;)
+	{
+	  m = gfc_match (" %n", name);
+          if (m != MATCH_YES)
+	    return MATCH_ERROR;
+
+          if (strcmp (name, "type") == 0)
+	    type = true;
+          else if (strcmp (name, "external") == 0)
+	    external = true;
+          else
+            return MATCH_ERROR;
+
+	  gfc_gobble_whitespace ();
+          c = gfc_next_ascii_char ();
+          if (c == ',')
+	    continue;
+	  if (c == ')')
+	    break;
+	  return MATCH_ERROR;
+	}
+    }
+  else
+    type = true;
+
+  if (gfc_match_eos () != MATCH_YES)
+    return MATCH_ERROR;
+
+  gfc_set_implicit_none (type, external);
+
+  return MATCH_YES;
 }
 
 
@@ -3062,6 +3105,13 @@  gfc_match_implicit (void)
   char c;
   match m;
 
+  if (gfc_current_ns->seen_implicit_none)
+    {
+      gfc_error ("IMPLICIT statement at %C following a type IMPLICIT NONE "
+		 "statement");
+      return MATCH_ERROR;
+    }
+
   gfc_clear_ts (&ts);
 
   /* We don't allow empty implicit statements.  */
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index f1c78cc..f6f95f8 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1655,6 +1655,9 @@  typedef struct gfc_namespace
   /* Set to 1 if namespace is an interface body with "IMPORT" used.  */
   unsigned has_import_set:1;
 
+  /* Set to 1 if the namespace uses "IMPLICT NONE (export)".  */
+  unsigned has_implicit_none_export:1;
+
   /* Set to 1 if resolved has been called for this namespace.
      Holds -1 during resolution.  */
   signed resolved:2;
@@ -2754,7 +2757,7 @@  extern int gfc_character_storage_size;
 void gfc_clear_new_implicit (void);
 bool gfc_add_new_implicit_range (int, int);
 bool gfc_merge_new_implicit (gfc_typespec *);
-void gfc_set_implicit_none (void);
+void gfc_set_implicit_none (bool, bool);
 void gfc_check_function_type (gfc_namespace *);
 bool gfc_is_intrinsic_typename (const char *);
 
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index f6233b7..1eb09ac 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -3252,8 +3252,14 @@  gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
      for calling a ISO_C_BINDING because c_loc and c_funloc
      are pseudo-unknown.  Additionally, warn about procedures not
      explicitly declared at all if requested.  */
-  if (sym->attr.if_source == IFSRC_UNKNOWN && ! sym->attr.is_iso_c)
+  if (sym->attr.if_source == IFSRC_UNKNOWN && !sym->attr.is_iso_c)
     {
+      if (sym->ns->has_implicit_none_export && sym->attr.proc == PROC_UNKNOWN)
+	{
+	  gfc_error ("Procedure '%s' called at %L is not explicitly declared",
+		     sym->name, where);
+	  return false;
+	}
       if (gfc_option.warn_implicit_interface)
 	gfc_warning ("Procedure '%s' called with an implicit interface at %L",
 		     sym->name, where);
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 9165061..4539beb 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -1950,9 +1950,6 @@  accept_statement (gfc_statement st)
   switch (st)
     {
     case ST_IMPLICIT_NONE:
-      gfc_set_implicit_none ();
-      break;
-
     case ST_IMPLICIT:
       break;
 
@@ -2142,7 +2139,7 @@  verify_st_order (st_state *p, gfc_statement st, bool silent)
       break;
 
     case ST_IMPLICIT_NONE:
-      if (p->state > ORDER_IMPLICIT_NONE)
+      if (p->state > ORDER_IMPLICIT)
 	goto order;
 
       /* The '>' sign cannot be a '>=', because a FORMAT or ENTRY
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 8e1d8b3..3f17152 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -114,22 +114,34 @@  static int new_flag[GFC_LETTERS];
 /* Handle a correctly parsed IMPLICIT NONE.  */
 
 void
-gfc_set_implicit_none (void)
+gfc_set_implicit_none (bool type, bool external)
 {
   int i;
 
-  if (gfc_current_ns->seen_implicit_none)
+  if (gfc_current_ns->seen_implicit_none
+      || gfc_current_ns->has_implicit_none_export)
     {
-      gfc_error ("Duplicate IMPLICIT NONE statement at %C");
+      gfc_error_now ("Duplicate IMPLICIT NONE statement at %C");
       return;
     }
 
-  gfc_current_ns->seen_implicit_none = 1;
+  if (external)
+    gfc_current_ns->has_implicit_none_export = 1;
 
-  for (i = 0; i < GFC_LETTERS; i++)
+  if (type)
     {
-      gfc_clear_ts (&gfc_current_ns->default_type[i]);
-      gfc_current_ns->set_flag[i] = 1;
+      gfc_current_ns->seen_implicit_none = 1;
+      for (i = 0; i < GFC_LETTERS; i++)
+	{
+	  if (gfc_current_ns->set_flag[i])
+	    {
+	      gfc_error_now ("Type IMPLICIT NONE statement at %C following an "
+			     "IMPLICIT statement");
+	      return;
+	    }
+	  gfc_clear_ts (&gfc_current_ns->default_type[i]);
+	  gfc_current_ns->set_flag[i] = 1;
+	}
     }
 }
 
@@ -2383,6 +2395,9 @@  gfc_get_namespace (gfc_namespace *parent, int parent_types)
 	}
     }
 
+  if (parent_types && ns->parent != NULL)
+    ns->has_implicit_none_export = ns->parent->has_implicit_none_export;
+
   ns->refs = 1;
 
   return ns;
diff --git a/gcc/testsuite/gfortran.dg/implicit_14.f90 b/gcc/testsuite/gfortran.dg/implicit_14.f90
new file mode 100644
index 0000000..5b1a3b6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/implicit_14.f90
@@ -0,0 +1,8 @@ 
+! { dg-do compile }
+! { dg-options "-std=f2008ts" }
+!
+! Support Fortran 2015's IMPLICIT NONE with spec list
+! (currently implemented as vendor extension)
+
+implicit none (type) ! { dg-error "GNU Extension: IMPORT NONE with spec list at \\(1\\)" }
+end
diff --git a/gcc/testsuite/gfortran.dg/implicit_15.f90 b/gcc/testsuite/gfortran.dg/implicit_15.f90
new file mode 100644
index 0000000..7924b42
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/implicit_15.f90
@@ -0,0 +1,70 @@ 
+! { dg-do compile }
+! { dg-options "" }
+!
+! Support Fortran 2015's IMPLICIT NONE with spec list
+!
+
+subroutine sub1
+implicit none (type)
+call test()
+i = 1 ! { dg-error "Symbol 'i' at .1. has no IMPLICIT type" }
+end subroutine sub1
+
+subroutine sub2
+implicit none ( external )
+call foo() ! { dg-error "Procedure 'foo' called at .1. is not explicitly declared" }
+i = 2
+end subroutine sub2
+
+subroutine sub3
+implicit none ( external, type, external, type )
+call foo() ! { dg-error "Procedure 'foo' called at .1. is not explicitly declared" }
+i = 3 ! { dg-error "Symbol 'i' at .1. has no IMPLICIT type" }
+end subroutine sub3
+
+subroutine sub4
+implicit none ( external ,type)
+external foo
+call foo()
+i = 4 ! { dg-error "Symbol 'i' at .1. has no IMPLICIT type" }
+end subroutine sub4
+
+subroutine sub5  ! OK
+implicit integer(a-z)
+implicit none ( external )
+procedure() :: foo
+call foo()
+i = 5
+end subroutine sub5
+
+subroutine sub6  ! OK
+implicit none ( external )
+implicit integer(a-z)
+procedure() :: foo
+call foo()
+i = 5
+end subroutine sub6
+
+subroutine sub7
+implicit none ( external )
+implicit none ! { dg-error "Duplicate IMPLICIT NONE statement" }
+end subroutine sub7
+
+subroutine sub8
+implicit none
+implicit none ( type ) ! { dg-error "Duplicate IMPLICIT NONE statement" }
+end subroutine sub8
+
+subroutine sub9
+implicit none ( external, type )
+implicit integer(a-z) ! { dg-error "IMPLICIT statement at .1. following a type IMPLICIT NONE statement" }
+procedure() :: foo
+call foo()
+end subroutine sub9
+
+subroutine sub10
+implicit integer(a-z)
+implicit none ( external, type ) ! { dg-error "Type IMPLICIT NONE statement at .1. following an IMPLICIT statement" }
+procedure() :: foo
+call foo()
+end subroutine sub10
diff --git a/gcc/testsuite/gfortran.dg/implicit_4.f90 b/gcc/testsuite/gfortran.dg/implicit_4.f90
index 2e871b0..9bf8d86 100644
--- a/gcc/testsuite/gfortran.dg/implicit_4.f90
+++ b/gcc/testsuite/gfortran.dg/implicit_4.f90
@@ -5,13 +5,13 @@  IMPLICIT NONE ! { dg-error "Duplicate" }
 END
 
 SUBROUTINE a
-IMPLICIT REAL(b-j) ! { dg-error "cannot follow" }
-implicit none      ! { dg-error "cannot follow" }
+IMPLICIT REAL(b-j)
+implicit none      ! { dg-error "Type IMPLICIT NONE statement at .1. following an IMPLICIT statement" }
 END SUBROUTINE a
 
 subroutine b
 implicit none
-implicit real(g-k) ! { dg-error "Cannot specify" }
+implicit real(g-k) ! { dg-error "IMPLICIT statement at .1. following a type IMPLICIT NONE statement" }
 end subroutine b
 
 subroutine c