diff mbox

fortran/67758 -- Prevent ICE caused by misplaced COMMON

Message ID 560FAA38.1080008@sfr.fr
State New
Headers show

Commit Message

Mikael Morin Oct. 3, 2015, 10:13 a.m. UTC
Le 02/10/2015 18:44, Steve Kargl a écrit :
> On Fri, Oct 02, 2015 at 11:28:06AM +0200, Mikael Morin wrote:
>> Le 01/10/2015 18:30, Steve Kargl a écrit :
>>> The call-stmt in the code is the start of an execution-construct
>>> A common-stmt is not allowed in an execution-construct.  At
>>> least, that's how I intepret the BNF in 2.1 of F2008.
>>>
>> The error message appears too soon, before we finish parsing the common
>> statement.  If it's delayed, as with the following additional patch, the
>> common statements is properly rejected:
>>
>> common_24.f:10:72:
>>
>>          COMMON /FMCOM / XX(80 000 000) ! { dg-error "conflicts with
>> COMMON" }
>>                                                                           1
>> Error: Unexpected COMMON statement at (1)
>> common_24.f:8:72:
>>
>> Error: PROCEDURE attribute conflicts with COMMON attribute in ???xx??? at (1)
>>
>> This needs a little more polishing (location missing in the second error
>> message), then let's see how the testsuite likes it.
>>
>
> While I prefer the first error message above, if it requires
> too much polish, then at least commit your first patch to cure
> the ICE.  We can worry about polish later.
>
I have finally managed to find a patch that doesn't regress in the 
testsuite.

The gfc_add_in_common call in gfc_match_common is delayed after the 
array spec handling and without return value check, so that errors are 
ignored.  Another gfc_add_in_common call is necessary to report errors 
again during resolution.  This is patch number 2.
The error location for the second call is grabbed from the common block 
struct, which is made accessible in the function by patch number 1.

No regression on x86-unknown-linux-gnu, OK for trunk?

Mikael

Comments

Steve Kargl Oct. 3, 2015, 7:08 p.m. UTC | #1
On Sat, Oct 03, 2015 at 12:13:12PM +0200, Mikael Morin wrote:
>
> I have finally managed to find a patch that doesn't regress in the 
> testsuite.
> 
> The gfc_add_in_common call in gfc_match_common is delayed after the 
> array spec handling and without return value check, so that errors are 
> ignored.  Another gfc_add_in_common call is necessary to report errors 
> again during resolution.  This is patch number 2.
> The error location for the second call is grabbed from the common block 
> struct, which is made accessible in the function by patch number 1.
> 
> No regression on x86-unknown-linux-gnu, OK for trunk?
> 

The patch is OK.  Thanks for taking over PR.
diff mbox

Patch

2015-10-02  Mikael Morin  <mikael@gcc.gnu.org>

	PR fortran/67758
	* match.c (gfc_match_common): Delay the common_block pointer
	assignment after error checking.
	Delay the call to gfc_add_in_common attribute after the handling
	of array specs.
	* resolve.c (resolve_common_vars): Call gfc_add_in_common again.

2015-10-02  Mikael Morin  <mikael@gcc.gnu.org>

	PR fortran/67758
	* gfortran.dg/common_24.f: New.

diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 523e9b2..a63c731 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -4330,10 +4330,6 @@  gfc_match_common (void)
 	  if (m == MATCH_NO)
 	    goto syntax;
 
-          /* Store a ref to the common block for error checking.  */
-          sym->common_block = t;
-          sym->common_block->refs++;
-
           /* See if we know the current common block is bind(c), and if
              so, then see if we can check if the symbol is (which it'll
              need to be).  This can happen if the bind(c) attr stmt was
@@ -4376,8 +4372,8 @@  gfc_match_common (void)
 		goto cleanup;
 	    }
 
-	  if (!gfc_add_in_common (&sym->attr, sym->name, NULL))
-	    goto cleanup;
+	  sym->common_block = t;
+	  sym->common_block->refs++;
 
 	  if (tail != NULL)
 	    tail->common_next = sym;
@@ -4416,6 +4412,10 @@  gfc_match_common (void)
 
 	    }
 
+	  /* Add the in_common attribute, but ignore the reported errors
+	     if any, and continue matching.  */
+	  gfc_add_in_common (&sym->attr, sym->name, NULL);
+
 	  sym->common_head = t;
 
 	  /* Check to see if the symbol is already in an equivalence group.
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 582c3f9..6e61250 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -918,6 +918,12 @@  resolve_common_vars (gfc_common_head *common_block, bool named_common)
 
   for (; csym; csym = csym->common_next)
     {
+      /* gfc_add_in_common may have been called before, but the reported errors
+	 have been ignored to continue parsing.
+	 We do the checks again here.  */
+      if (!csym->attr.use_assoc)
+	gfc_add_in_common (&csym->attr, csym->name, &common_block->where);
+
       if (csym->value || csym->attr.data)
 	{
 	  if (!csym->ns->is_block_data)
diff --git a/gcc/testsuite/gfortran.dg/common_24.f b/gcc/testsuite/gfortran.dg/common_24.f
new file mode 100644
index 0000000..ea37c2a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/common_24.f
@@ -0,0 +1,11 @@ 
+c { dg-do compile }
+c PR fortran/67758
+c
+c Check the absence of ICE after emitting the error message
+c
+c Contributed by Ilya Enkovich <ienkovich@gcc.gnu.org>
+
+      COMMON /FMCOM / X(80 000 000)
+      CALL T(XX(A))
+      COMMON /FMCOM / XX(80 000 000) ! { dg-error "Unexpected COMMON" }
+      END