This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch, fortran] Implement VOLATILE statement/attribute (PR 29601)


Hi,

As suggested by FX via IRC:

1. Changed error message to the standard(?) wording:
-                               "In the selected standard, the VOLATILE "
+                              "New in Fortran 2003: the VOLATILE "
                               "attribute is not allowed at %C")

(I was thinking before of using these words, but I found them misleading:
It *is* allowed in Fortran 2003, but not in Fortran 95. I had therefore
chosen the wordings of ALLOCATABLE. I now changed it as suggested
to match the standard. Comments?)

I also changed the unrelated message
-                                  "In the selected standard, the
ALLOCATABLE "
+                                  "New in Fortran 2003: the ALLOCATABLE "
                                   "attribute at %C is not allowed in a
TYPE "
                                   "definition") == FAILURE)
to be in line with the standard.


2. Added volatile4.f90 which shows that a volatile variable is not
optimized away.

Regression-tested on x86_64-unknown-linux-gnu (alias openSUSE Factory).
Further comments? Ok for the trunk?


Tobias


fortran/
2006-11-04  Tobias Burnus  <burnus@net-b.de>

    fortran/29601
    * symbol.c (check_conflict, gfc_add_volatile): Add volatile support.
    * decl.c (match_attr_spec, gfc_match_volatile): Add volatile support.
    * gfortran.h (symbol_attribute): Add volatile_ to struct.
    * resolve.c (was_declared): Add volatile support.
    * trans-decl.c (gfc_finish_var_decl): Add volatile support.
    * match.h: Declare gfc_match_volatile.
    * parse.c (decode_statement): Recognize volatile.


testsuite/
2006-11-04  Tobias Burnus  <burnus@net-b.de>

    fortran/29601
    * volatile.f90: Add.
    * volatile2.f90: Add.
    * volatile3.f90: Add.
    * volatile4.f90: Add.

Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c	(Revision 118481)
+++ gcc/fortran/symbol.c	(Arbeitskopie)
@@ -265,14 +265,15 @@
 {
   static const char *dummy = "DUMMY", *save = "SAVE", *pointer = "POINTER",
     *target = "TARGET", *external = "EXTERNAL", *intent = "INTENT",
-    *intrinsic = "INTRINSIC", *allocatable = "ALLOCATABLE",
-    *elemental = "ELEMENTAL", *private = "PRIVATE", *recursive = "RECURSIVE",
+    *intent_in = "INTENT(IN)", *intrinsic = "INTRINSIC",
+    *allocatable = "ALLOCATABLE", *elemental = "ELEMENTAL",
+    *private = "PRIVATE", *recursive = "RECURSIVE",
     *in_common = "COMMON", *result = "RESULT", *in_namelist = "NAMELIST",
     *public = "PUBLIC", *optional = "OPTIONAL", *entry = "ENTRY",
     *function = "FUNCTION", *subroutine = "SUBROUTINE",
     *dimension = "DIMENSION", *in_equivalence = "EQUIVALENCE",
     *use_assoc = "USE ASSOCIATED", *cray_pointer = "CRAY POINTER",
-    *cray_pointee = "CRAY POINTEE", *data = "DATA";
+    *cray_pointee = "CRAY POINTEE", *data = "DATA", *volatile_ = "VOLATILE";
   static const char *threadprivate = "THREADPRIVATE";
 
   const char *a1, *a2;
@@ -399,6 +400,16 @@
   conf (data, allocatable);
   conf (data, use_assoc);
 
+  conf (volatile_, intrinsic)
+  conf (volatile_, external)
+
+  if (attr->volatile_ && attr->intent == INTENT_IN)
+    {
+      a1 = volatile_;
+      a2 = intent_in;
+      goto conflict;
+    }
+
   a1 = gfc_code2string (flavors, attr->flavor);
 
   if (attr->in_namelist
@@ -508,6 +519,7 @@
       conf2 (dummy);
       conf2 (in_common);
       conf2 (save);
+      conf2 (volatile_);
       conf2 (threadprivate);
       break;
 
@@ -812,7 +824,27 @@
   return check_conflict (attr, name, where);
 }
 
+try
+gfc_add_volatile (symbol_attribute * attr, const char *name, locus * where)
+{
 
+  if (check_used (attr, name, where))
+    return FAILURE;
+
+  if (attr->volatile_)
+    {
+	if (gfc_notify_std (GFC_STD_LEGACY, 
+			    "Duplicate VOLATILE attribute specified at %L",
+			    where) 
+	    == FAILURE)
+	  return FAILURE;
+    }
+
+  attr->volatile_ = 1;
+  return check_conflict (attr, name, where);
+}
+
+
 try
 gfc_add_threadprivate (symbol_attribute * attr, const char *name, locus * where)
 {
@@ -1249,6 +1281,8 @@
     goto fail;
   if (src->save && gfc_add_save (dest, NULL, where) == FAILURE)
     goto fail;
+  if (src->volatile_ && gfc_add_volatile (dest, NULL, where) == FAILURE)
+    goto fail;
   if (src->threadprivate && gfc_add_threadprivate (dest, NULL, where) == FAILURE)
     goto fail;
   if (src->target && gfc_add_target (dest, where) == FAILURE)
Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c	(Revision 118481)
+++ gcc/fortran/decl.c	(Arbeitskopie)
@@ -2025,7 +2025,7 @@
     DECL_ALLOCATABLE = GFC_DECL_BEGIN, DECL_DIMENSION, DECL_EXTERNAL,
     DECL_IN, DECL_OUT, DECL_INOUT, DECL_INTRINSIC, DECL_OPTIONAL,
     DECL_PARAMETER, DECL_POINTER, DECL_PRIVATE, DECL_PUBLIC, DECL_SAVE,
-    DECL_TARGET, DECL_COLON, DECL_NONE,
+    DECL_TARGET, DECL_VOLATILE, DECL_COLON, DECL_NONE,
     GFC_DECL_END /* Sentinel */
   }
   decl_types;
@@ -2048,6 +2048,7 @@
     minit (", public", DECL_PUBLIC),
     minit (", save", DECL_SAVE),
     minit (", target", DECL_TARGET),
+    minit (", volatile", DECL_VOLATILE),
     minit ("::", DECL_COLON),
     minit (NULL, DECL_NONE)
   };
@@ -2168,6 +2169,9 @@
 	  case DECL_TARGET:
 	    attr = "TARGET";
 	    break;
+	  case DECL_VOLATILE:
+	    attr = "VOLATILE";
+	    break;
 	  default:
 	    attr = NULL;	/* This shouldn't happen */
 	  }
@@ -2191,7 +2195,7 @@
 	  if (d == DECL_ALLOCATABLE)
 	    {
 	      if (gfc_notify_std (GFC_STD_F2003, 
-				   "In the selected standard, the ALLOCATABLE "
+				   "New in Fortran 2003: the ALLOCATABLE "
 				   "attribute at %C is not allowed in a TYPE "
 				   "definition") == FAILURE)         
 		{
@@ -2282,6 +2286,16 @@
 	  t = gfc_add_target (&current_attr, &seen_at[d]);
 	  break;
 
+	case DECL_VOLATILE:
+	  if (gfc_notify_std (GFC_STD_F2003,
+                              "New in Fortran 2003: the VOLATILE "
+                              "attribute is not allowed at %C")
+	      == FAILURE)
+	    t = FAILURE;
+	  else
+	    t = gfc_add_volatile (&current_attr, NULL, &seen_at[d]);
+	  break;
+
 	default:
 	  gfc_internal_error ("match_attr_spec(): Bad attribute");
 	}
@@ -3894,7 +3908,7 @@
     {
       if (gfc_notify_std (GFC_STD_LEGACY, 
 			  "SAVE statement at %C follows blanket SAVE statement")
-	  == FAILURE)
+ 	  == FAILURE)
 	return MATCH_ERROR;
     }
 
@@ -3944,6 +3958,60 @@
 }
 
 
+match
+gfc_match_volatile (void)
+{
+  gfc_symbol *sym;
+  match m;
+
+  if (gfc_notify_std (GFC_STD_F2003, 
+		      "New in Fortran 2003: the VOLATILE "
+                      "statement is not allowed at %C")
+      == FAILURE)
+    return MATCH_ERROR;
+
+  if (gfc_match (" ::") == MATCH_NO && gfc_match_space () == MATCH_NO)
+    {
+      return MATCH_ERROR;
+    }
+
+  if (gfc_match_eos () == MATCH_YES)
+    goto syntax;
+
+  for(;;)
+    {
+      m = gfc_match_symbol (&sym, 0);
+      switch (m)
+	{
+	case MATCH_YES:
+	  if (gfc_add_volatile (&sym->attr, sym->name,
+  			        &gfc_current_locus) == FAILURE)
+	    return MATCH_ERROR;
+	  goto next_item;
+
+	case MATCH_NO:
+	  break;
+
+	case MATCH_ERROR:
+	  return MATCH_ERROR;
+	}
+
+    next_item:
+      if (gfc_match_eos () == MATCH_YES)
+	break;
+      if (gfc_match_char (',') != MATCH_YES)
+	goto syntax;
+    }
+
+  return MATCH_YES;
+
+syntax:
+  gfc_error ("Syntax error in VOLATILE statement at %C");
+  return MATCH_ERROR;
+}
+
+
+
 /* Match a module procedure statement.  Note that we have to modify
    symbols in the parent's namespace because the current one was there
    to receive symbols that are in an interface's formal argument list.  */
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(Revision 118481)
+++ gcc/fortran/gfortran.h	(Arbeitskopie)
@@ -477,7 +477,7 @@
 {
   /* Variable attributes.  */
   unsigned allocatable:1, dimension:1, external:1, intrinsic:1,
-    optional:1, pointer:1, save:1, target:1,
+    optional:1, pointer:1, save:1, target:1, volatile_:1,
     dummy:1, result:1, assign:1, threadprivate:1;
 
   unsigned data:1,		/* Symbol is named in a DATA statement.  */
@@ -1866,6 +1866,7 @@
 try gfc_add_recursive (symbol_attribute *, locus *);
 try gfc_add_function (symbol_attribute *, const char *, locus *);
 try gfc_add_subroutine (symbol_attribute *, const char *, locus *);
+try gfc_add_volatile (symbol_attribute *, const char *, locus *);
 
 try gfc_add_access (symbol_attribute *, gfc_access, const char *, locus *);
 try gfc_add_flavor (symbol_attribute *, sym_flavor, const char *, locus *);
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(Revision 118481)
+++ gcc/fortran/resolve.c	(Arbeitskopie)
@@ -677,7 +677,7 @@
     return 1;
 
   if (a.allocatable || a.dimension || a.dummy || a.external || a.intrinsic
-      || a.optional || a.pointer || a.save || a.target
+      || a.optional || a.pointer || a.save || a.target || a.volatile_
       || a.access != ACCESS_UNKNOWN || a.intent != INTENT_UNKNOWN)
     return 1;
 
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c	(Revision 118481)
+++ gcc/fortran/trans-decl.c	(Arbeitskopie)
@@ -513,7 +513,15 @@
   if ((sym->attr.save || sym->attr.data || sym->value)
       && !sym->attr.use_assoc)
     TREE_STATIC (decl) = 1;
-  
+
+  if (sym->attr.volatile_)
+    {
+      tree new;
+      TREE_THIS_VOLATILE (decl) = 1;
+      new = build_qualified_type (TREE_TYPE (decl), TYPE_QUAL_VOLATILE);
+      TREE_TYPE (decl) = new;
+    } 
+
   /* Keep variables larger than max-stack-var-size off stack.  */
   if (!sym->ns->proc_name->attr.recursive
       && INTEGER_CST_P (DECL_SIZE_UNIT (decl))
Index: gcc/fortran/match.h
===================================================================
--- gcc/fortran/match.h	(Revision 118481)
+++ gcc/fortran/match.h	(Arbeitskopie)
@@ -146,6 +146,7 @@
 match gfc_match_save (void);
 match gfc_match_modproc (void);
 match gfc_match_target (void);
+match gfc_match_volatile (void);
 
 /* primary.c */
 match gfc_match_structure_constructor (gfc_symbol *, gfc_expr **);
Index: gcc/fortran/parse.c
===================================================================
--- gcc/fortran/parse.c	(Revision 118481)
+++ gcc/fortran/parse.c	(Arbeitskopie)
@@ -282,6 +282,10 @@
       match ("use% ", gfc_match_use, ST_USE);
       break;
 
+    case 'v':
+      match ("volatile", gfc_match_volatile, ST_ATTR_DECL);
+      break;
+
     case 'w':
       match ("write", gfc_match_write, ST_WRITE);
       break;
--- /dev/null	2006-10-21 23:34:46.000000000 +0200
+++ gcc/testsuite/gfortran.dg/volatile.f90	2006-11-04 18:55:35.000000000 +0100
@@ -0,0 +1,11 @@
+! { dg-do run }
+! Test whether volatile statements and attributes are accepted
+! PR fortran/29601
+program volatile_test
+  implicit none
+  real :: l,m
+  real, volatile :: r = 3.
+  volatile :: l
+  l = 4.0
+  m = 3.0
+end program volatile_test
--- /dev/null	2006-10-21 23:34:46.000000000 +0200
+++ gcc/testsuite/gfortran.dg/volatile2.f90	2006-11-04 18:55:30.000000000 +0100
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-shouldfail "VOLATILE not part of F95" }
+! { dg-options "-std=f95" }
+! Test whether volatile statements and attributes are rejected
+! with -std=f95.
+! PR fortran/29601
+program volatile_test
+  implicit none
+  real, external,  volatile :: foo     ! { dg-error "VOLATILE attribute is not allowed" }
+  real, intrinsic,  volatile :: sin     ! { dg-error "VOLATILE attribute is not allowed" }
+  real, parameter, volatile :: r = 5.5 ! { dg-error "VOLATILE attribute is not allowed" }
+  real :: l,m
+  real, volatile :: r = 3. ! { dg-error "VOLATILE attribute is not allowed" }
+  volatile :: l ! { dg-error "VOLATILE statement is not allowed" }
+  l = 4.0
+  m = 3.0
+end program volatile_test
--- /dev/null	2006-10-21 23:34:46.000000000 +0200
+++ gcc/testsuite/gfortran.dg/volatile3.f90	2006-11-04 18:55:31.000000000 +0100
@@ -0,0 +1,22 @@
+! { dg-do compile }
+! { dg-shouldfail "Invalid use of VOLATILE" }
+! Test whether volatile statements and attributes are
+! properly error checked.
+! PR fortran/29601
+program volatile_test
+  implicit none
+  real, external,  volatile :: foo ! { dg-error "VOLATILE attribute conflicts with EXTERNAL attribute" }
+  real, intrinsic, volatile :: sin ! { dg-error "VOLATILE attribute conflicts with INTRINSIC attribute" }
+  real, parameter, volatile :: r = 5.5 ! { dg-error "PARAMETER attribute conflicts with VOLATILE attribute" }
+  real :: l,m
+  real,volatile :: n
+  real, volatile,volatile :: r = 3. ! { dg-error "Duplicate VOLATILE attribute" }
+  volatile :: l,n ! { dg-error "Duplicate VOLATILE attribute" }
+  volatile ! { dg-error "Syntax error in VOLATILE statement" }
+  l = 4.0
+  m = 3.0
+contains
+  subroutine foo(a) ! { dg-error "has no IMPLICIT type" } ! due to error below
+    integer, intent(in), volatile :: a ! { dg-error "VOLATILE attribute conflicts with INTENT\\(IN\\)" }
+  end subroutine
+end program volatile_test
--- /dev/null	2006-10-21 23:34:46.000000000 +0200
+++ gcc/testsuite/gfortran.dg/volatile4.f90	2006-11-04 20:19:13.000000000 +0100
@@ -0,0 +1,19 @@
+! { dg-do compile }
+! { dg-options "-O2 -fdump-tree-optimized" }
+! Tests whether volatile really works
+! with -std=f95.
+! PR fortran/29601
+logical, volatile :: t1
+logical :: t2
+integer :: i
+
+t2 = .false.
+t1 = .false.
+do i = 1, 2
+  if(t1) print *, 'VolatileNotOptimizedAway'
+  if(t2) print *, 'NonVolatileNotOptimizedAway'
+end do
+end
+! { dg-final { scan-tree-dump "VolatileNotOptimizedAway"  } } */
+! { dg-final { scan-tree-dump-not "NonVolatileNotOptimizedAway" } } */
+! { dg-final { cleanup-tree-dump "optimized" } } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]