xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/interface.c (revision 4ac76180e904e771b9d522c7e57296d371f06499)
1627f7eb2Smrg /* Deal with interfaces.
24c3eb207Smrg    Copyright (C) 2000-2020 Free Software Foundation, Inc.
3627f7eb2Smrg    Contributed by Andy Vaught
4627f7eb2Smrg 
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg 
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg 
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg 
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3.  If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
20627f7eb2Smrg 
21627f7eb2Smrg 
22627f7eb2Smrg /* Deal with interfaces.  An explicit interface is represented as a
23627f7eb2Smrg    singly linked list of formal argument structures attached to the
24627f7eb2Smrg    relevant symbols.  For an implicit interface, the arguments don't
25627f7eb2Smrg    point to symbols.  Explicit interfaces point to namespaces that
26627f7eb2Smrg    contain the symbols within that interface.
27627f7eb2Smrg 
28627f7eb2Smrg    Implicit interfaces are linked together in a singly linked list
29627f7eb2Smrg    along the next_if member of symbol nodes.  Since a particular
30627f7eb2Smrg    symbol can only have a single explicit interface, the symbol cannot
31627f7eb2Smrg    be part of multiple lists and a single next-member suffices.
32627f7eb2Smrg 
33627f7eb2Smrg    This is not the case for general classes, though.  An operator
34627f7eb2Smrg    definition is independent of just about all other uses and has it's
35627f7eb2Smrg    own head pointer.
36627f7eb2Smrg 
37627f7eb2Smrg    Nameless interfaces:
38627f7eb2Smrg      Nameless interfaces create symbols with explicit interfaces within
39627f7eb2Smrg      the current namespace.  They are otherwise unlinked.
40627f7eb2Smrg 
41627f7eb2Smrg    Generic interfaces:
42627f7eb2Smrg      The generic name points to a linked list of symbols.  Each symbol
43627f7eb2Smrg      has an explicit interface.  Each explicit interface has its own
44627f7eb2Smrg      namespace containing the arguments.  Module procedures are symbols in
45627f7eb2Smrg      which the interface is added later when the module procedure is parsed.
46627f7eb2Smrg 
47627f7eb2Smrg    User operators:
48627f7eb2Smrg      User-defined operators are stored in a their own set of symtrees
49627f7eb2Smrg      separate from regular symbols.  The symtrees point to gfc_user_op
50627f7eb2Smrg      structures which in turn head up a list of relevant interfaces.
51627f7eb2Smrg 
52627f7eb2Smrg    Extended intrinsics and assignment:
53627f7eb2Smrg      The head of these interface lists are stored in the containing namespace.
54627f7eb2Smrg 
55627f7eb2Smrg    Implicit interfaces:
56627f7eb2Smrg      An implicit interface is represented as a singly linked list of
57627f7eb2Smrg      formal argument list structures that don't point to any symbol
58627f7eb2Smrg      nodes -- they just contain types.
59627f7eb2Smrg 
60627f7eb2Smrg 
61627f7eb2Smrg    When a subprogram is defined, the program unit's name points to an
62627f7eb2Smrg    interface as usual, but the link to the namespace is NULL and the
63627f7eb2Smrg    formal argument list points to symbols within the same namespace as
64627f7eb2Smrg    the program unit name.  */
65627f7eb2Smrg 
66627f7eb2Smrg #include "config.h"
67627f7eb2Smrg #include "system.h"
68627f7eb2Smrg #include "coretypes.h"
69627f7eb2Smrg #include "options.h"
70627f7eb2Smrg #include "gfortran.h"
71627f7eb2Smrg #include "match.h"
72627f7eb2Smrg #include "arith.h"
73627f7eb2Smrg 
74627f7eb2Smrg /* The current_interface structure holds information about the
75627f7eb2Smrg    interface currently being parsed.  This structure is saved and
76627f7eb2Smrg    restored during recursive interfaces.  */
77627f7eb2Smrg 
78627f7eb2Smrg gfc_interface_info current_interface;
79627f7eb2Smrg 
80627f7eb2Smrg 
81627f7eb2Smrg /* Free a singly linked list of gfc_interface structures.  */
82627f7eb2Smrg 
83627f7eb2Smrg void
gfc_free_interface(gfc_interface * intr)84627f7eb2Smrg gfc_free_interface (gfc_interface *intr)
85627f7eb2Smrg {
86627f7eb2Smrg   gfc_interface *next;
87627f7eb2Smrg 
88627f7eb2Smrg   for (; intr; intr = next)
89627f7eb2Smrg     {
90627f7eb2Smrg       next = intr->next;
91627f7eb2Smrg       free (intr);
92627f7eb2Smrg     }
93627f7eb2Smrg }
94627f7eb2Smrg 
95627f7eb2Smrg 
96627f7eb2Smrg /* Change the operators unary plus and minus into binary plus and
97627f7eb2Smrg    minus respectively, leaving the rest unchanged.  */
98627f7eb2Smrg 
99627f7eb2Smrg static gfc_intrinsic_op
fold_unary_intrinsic(gfc_intrinsic_op op)100627f7eb2Smrg fold_unary_intrinsic (gfc_intrinsic_op op)
101627f7eb2Smrg {
102627f7eb2Smrg   switch (op)
103627f7eb2Smrg     {
104627f7eb2Smrg     case INTRINSIC_UPLUS:
105627f7eb2Smrg       op = INTRINSIC_PLUS;
106627f7eb2Smrg       break;
107627f7eb2Smrg     case INTRINSIC_UMINUS:
108627f7eb2Smrg       op = INTRINSIC_MINUS;
109627f7eb2Smrg       break;
110627f7eb2Smrg     default:
111627f7eb2Smrg       break;
112627f7eb2Smrg     }
113627f7eb2Smrg 
114627f7eb2Smrg   return op;
115627f7eb2Smrg }
116627f7eb2Smrg 
117627f7eb2Smrg 
118627f7eb2Smrg /* Return the operator depending on the DTIO moded string.  Note that
119627f7eb2Smrg    these are not operators in the normal sense and so have been placed
120627f7eb2Smrg    beyond GFC_INTRINSIC_END in gfortran.h:enum gfc_intrinsic_op.  */
121627f7eb2Smrg 
122627f7eb2Smrg static gfc_intrinsic_op
dtio_op(char * mode)123627f7eb2Smrg dtio_op (char* mode)
124627f7eb2Smrg {
125627f7eb2Smrg   if (strcmp (mode, "formatted") == 0)
126627f7eb2Smrg     return INTRINSIC_FORMATTED;
127627f7eb2Smrg   if (strcmp (mode, "unformatted") == 0)
128627f7eb2Smrg     return INTRINSIC_UNFORMATTED;
129627f7eb2Smrg   return INTRINSIC_NONE;
130627f7eb2Smrg }
131627f7eb2Smrg 
132627f7eb2Smrg 
133627f7eb2Smrg /* Match a generic specification.  Depending on which type of
134627f7eb2Smrg    interface is found, the 'name' or 'op' pointers may be set.
135627f7eb2Smrg    This subroutine doesn't return MATCH_NO.  */
136627f7eb2Smrg 
137627f7eb2Smrg match
gfc_match_generic_spec(interface_type * type,char * name,gfc_intrinsic_op * op)138627f7eb2Smrg gfc_match_generic_spec (interface_type *type,
139627f7eb2Smrg 			char *name,
140627f7eb2Smrg 			gfc_intrinsic_op *op)
141627f7eb2Smrg {
142627f7eb2Smrg   char buffer[GFC_MAX_SYMBOL_LEN + 1];
143627f7eb2Smrg   match m;
144627f7eb2Smrg   gfc_intrinsic_op i;
145627f7eb2Smrg 
146627f7eb2Smrg   if (gfc_match (" assignment ( = )") == MATCH_YES)
147627f7eb2Smrg     {
148627f7eb2Smrg       *type = INTERFACE_INTRINSIC_OP;
149627f7eb2Smrg       *op = INTRINSIC_ASSIGN;
150627f7eb2Smrg       return MATCH_YES;
151627f7eb2Smrg     }
152627f7eb2Smrg 
153627f7eb2Smrg   if (gfc_match (" operator ( %o )", &i) == MATCH_YES)
154627f7eb2Smrg     {				/* Operator i/f */
155627f7eb2Smrg       *type = INTERFACE_INTRINSIC_OP;
156627f7eb2Smrg       *op = fold_unary_intrinsic (i);
157627f7eb2Smrg       return MATCH_YES;
158627f7eb2Smrg     }
159627f7eb2Smrg 
160627f7eb2Smrg   *op = INTRINSIC_NONE;
161627f7eb2Smrg   if (gfc_match (" operator ( ") == MATCH_YES)
162627f7eb2Smrg     {
163627f7eb2Smrg       m = gfc_match_defined_op_name (buffer, 1);
164627f7eb2Smrg       if (m == MATCH_NO)
165627f7eb2Smrg 	goto syntax;
166627f7eb2Smrg       if (m != MATCH_YES)
167627f7eb2Smrg 	return MATCH_ERROR;
168627f7eb2Smrg 
169627f7eb2Smrg       m = gfc_match_char (')');
170627f7eb2Smrg       if (m == MATCH_NO)
171627f7eb2Smrg 	goto syntax;
172627f7eb2Smrg       if (m != MATCH_YES)
173627f7eb2Smrg 	return MATCH_ERROR;
174627f7eb2Smrg 
175627f7eb2Smrg       strcpy (name, buffer);
176627f7eb2Smrg       *type = INTERFACE_USER_OP;
177627f7eb2Smrg       return MATCH_YES;
178627f7eb2Smrg     }
179627f7eb2Smrg 
180627f7eb2Smrg   if (gfc_match (" read ( %n )", buffer) == MATCH_YES)
181627f7eb2Smrg     {
182627f7eb2Smrg       *op = dtio_op (buffer);
183627f7eb2Smrg       if (*op == INTRINSIC_FORMATTED)
184627f7eb2Smrg 	{
185627f7eb2Smrg 	  strcpy (name, gfc_code2string (dtio_procs, DTIO_RF));
186627f7eb2Smrg 	  *type = INTERFACE_DTIO;
187627f7eb2Smrg 	}
188627f7eb2Smrg       if (*op == INTRINSIC_UNFORMATTED)
189627f7eb2Smrg 	{
190627f7eb2Smrg 	  strcpy (name, gfc_code2string (dtio_procs, DTIO_RUF));
191627f7eb2Smrg 	  *type = INTERFACE_DTIO;
192627f7eb2Smrg 	}
193627f7eb2Smrg       if (*op != INTRINSIC_NONE)
194627f7eb2Smrg 	return MATCH_YES;
195627f7eb2Smrg     }
196627f7eb2Smrg 
197627f7eb2Smrg   if (gfc_match (" write ( %n )", buffer) == MATCH_YES)
198627f7eb2Smrg     {
199627f7eb2Smrg       *op = dtio_op (buffer);
200627f7eb2Smrg       if (*op == INTRINSIC_FORMATTED)
201627f7eb2Smrg 	{
202627f7eb2Smrg 	  strcpy (name, gfc_code2string (dtio_procs, DTIO_WF));
203627f7eb2Smrg 	  *type = INTERFACE_DTIO;
204627f7eb2Smrg 	}
205627f7eb2Smrg       if (*op == INTRINSIC_UNFORMATTED)
206627f7eb2Smrg 	{
207627f7eb2Smrg 	  strcpy (name, gfc_code2string (dtio_procs, DTIO_WUF));
208627f7eb2Smrg 	  *type = INTERFACE_DTIO;
209627f7eb2Smrg 	}
210627f7eb2Smrg       if (*op != INTRINSIC_NONE)
211627f7eb2Smrg 	return MATCH_YES;
212627f7eb2Smrg     }
213627f7eb2Smrg 
214627f7eb2Smrg   if (gfc_match_name (buffer) == MATCH_YES)
215627f7eb2Smrg     {
216627f7eb2Smrg       strcpy (name, buffer);
217627f7eb2Smrg       *type = INTERFACE_GENERIC;
218627f7eb2Smrg       return MATCH_YES;
219627f7eb2Smrg     }
220627f7eb2Smrg 
221627f7eb2Smrg   *type = INTERFACE_NAMELESS;
222627f7eb2Smrg   return MATCH_YES;
223627f7eb2Smrg 
224627f7eb2Smrg syntax:
225627f7eb2Smrg   gfc_error ("Syntax error in generic specification at %C");
226627f7eb2Smrg   return MATCH_ERROR;
227627f7eb2Smrg }
228627f7eb2Smrg 
229627f7eb2Smrg 
230627f7eb2Smrg /* Match one of the five F95 forms of an interface statement.  The
231627f7eb2Smrg    matcher for the abstract interface follows.  */
232627f7eb2Smrg 
233627f7eb2Smrg match
gfc_match_interface(void)234627f7eb2Smrg gfc_match_interface (void)
235627f7eb2Smrg {
236627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
237627f7eb2Smrg   interface_type type;
238627f7eb2Smrg   gfc_symbol *sym;
239627f7eb2Smrg   gfc_intrinsic_op op;
240627f7eb2Smrg   match m;
241627f7eb2Smrg 
242627f7eb2Smrg   m = gfc_match_space ();
243627f7eb2Smrg 
244627f7eb2Smrg   if (gfc_match_generic_spec (&type, name, &op) == MATCH_ERROR)
245627f7eb2Smrg     return MATCH_ERROR;
246627f7eb2Smrg 
247627f7eb2Smrg   /* If we're not looking at the end of the statement now, or if this
248627f7eb2Smrg      is not a nameless interface but we did not see a space, punt.  */
249627f7eb2Smrg   if (gfc_match_eos () != MATCH_YES
250627f7eb2Smrg       || (type != INTERFACE_NAMELESS && m != MATCH_YES))
251627f7eb2Smrg     {
252627f7eb2Smrg       gfc_error ("Syntax error: Trailing garbage in INTERFACE statement "
253627f7eb2Smrg 		 "at %C");
254627f7eb2Smrg       return MATCH_ERROR;
255627f7eb2Smrg     }
256627f7eb2Smrg 
257627f7eb2Smrg   current_interface.type = type;
258627f7eb2Smrg 
259627f7eb2Smrg   switch (type)
260627f7eb2Smrg     {
261627f7eb2Smrg     case INTERFACE_DTIO:
262627f7eb2Smrg     case INTERFACE_GENERIC:
263627f7eb2Smrg       if (gfc_get_symbol (name, NULL, &sym))
264627f7eb2Smrg 	return MATCH_ERROR;
265627f7eb2Smrg 
266627f7eb2Smrg       if (!sym->attr.generic
267627f7eb2Smrg 	  && !gfc_add_generic (&sym->attr, sym->name, NULL))
268627f7eb2Smrg 	return MATCH_ERROR;
269627f7eb2Smrg 
270627f7eb2Smrg       if (sym->attr.dummy)
271627f7eb2Smrg 	{
272627f7eb2Smrg 	  gfc_error ("Dummy procedure %qs at %C cannot have a "
273627f7eb2Smrg 		     "generic interface", sym->name);
274627f7eb2Smrg 	  return MATCH_ERROR;
275627f7eb2Smrg 	}
276627f7eb2Smrg 
277627f7eb2Smrg       current_interface.sym = gfc_new_block = sym;
278627f7eb2Smrg       break;
279627f7eb2Smrg 
280627f7eb2Smrg     case INTERFACE_USER_OP:
281627f7eb2Smrg       current_interface.uop = gfc_get_uop (name);
282627f7eb2Smrg       break;
283627f7eb2Smrg 
284627f7eb2Smrg     case INTERFACE_INTRINSIC_OP:
285627f7eb2Smrg       current_interface.op = op;
286627f7eb2Smrg       break;
287627f7eb2Smrg 
288627f7eb2Smrg     case INTERFACE_NAMELESS:
289627f7eb2Smrg     case INTERFACE_ABSTRACT:
290627f7eb2Smrg       break;
291627f7eb2Smrg     }
292627f7eb2Smrg 
293627f7eb2Smrg   return MATCH_YES;
294627f7eb2Smrg }
295627f7eb2Smrg 
296627f7eb2Smrg 
297627f7eb2Smrg 
298627f7eb2Smrg /* Match a F2003 abstract interface.  */
299627f7eb2Smrg 
300627f7eb2Smrg match
gfc_match_abstract_interface(void)301627f7eb2Smrg gfc_match_abstract_interface (void)
302627f7eb2Smrg {
303627f7eb2Smrg   match m;
304627f7eb2Smrg 
305627f7eb2Smrg   if (!gfc_notify_std (GFC_STD_F2003, "ABSTRACT INTERFACE at %C"))
306627f7eb2Smrg     return MATCH_ERROR;
307627f7eb2Smrg 
308627f7eb2Smrg   m = gfc_match_eos ();
309627f7eb2Smrg 
310627f7eb2Smrg   if (m != MATCH_YES)
311627f7eb2Smrg     {
312627f7eb2Smrg       gfc_error ("Syntax error in ABSTRACT INTERFACE statement at %C");
313627f7eb2Smrg       return MATCH_ERROR;
314627f7eb2Smrg     }
315627f7eb2Smrg 
316627f7eb2Smrg   current_interface.type = INTERFACE_ABSTRACT;
317627f7eb2Smrg 
318627f7eb2Smrg   return m;
319627f7eb2Smrg }
320627f7eb2Smrg 
321627f7eb2Smrg 
322627f7eb2Smrg /* Match the different sort of generic-specs that can be present after
323627f7eb2Smrg    the END INTERFACE itself.  */
324627f7eb2Smrg 
325627f7eb2Smrg match
gfc_match_end_interface(void)326627f7eb2Smrg gfc_match_end_interface (void)
327627f7eb2Smrg {
328627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
329627f7eb2Smrg   interface_type type;
330627f7eb2Smrg   gfc_intrinsic_op op;
331627f7eb2Smrg   match m;
332627f7eb2Smrg 
333627f7eb2Smrg   m = gfc_match_space ();
334627f7eb2Smrg 
335627f7eb2Smrg   if (gfc_match_generic_spec (&type, name, &op) == MATCH_ERROR)
336627f7eb2Smrg     return MATCH_ERROR;
337627f7eb2Smrg 
338627f7eb2Smrg   /* If we're not looking at the end of the statement now, or if this
339627f7eb2Smrg      is not a nameless interface but we did not see a space, punt.  */
340627f7eb2Smrg   if (gfc_match_eos () != MATCH_YES
341627f7eb2Smrg       || (type != INTERFACE_NAMELESS && m != MATCH_YES))
342627f7eb2Smrg     {
343627f7eb2Smrg       gfc_error ("Syntax error: Trailing garbage in END INTERFACE "
344627f7eb2Smrg 		 "statement at %C");
345627f7eb2Smrg       return MATCH_ERROR;
346627f7eb2Smrg     }
347627f7eb2Smrg 
348627f7eb2Smrg   m = MATCH_YES;
349627f7eb2Smrg 
350627f7eb2Smrg   switch (current_interface.type)
351627f7eb2Smrg     {
352627f7eb2Smrg     case INTERFACE_NAMELESS:
353627f7eb2Smrg     case INTERFACE_ABSTRACT:
354627f7eb2Smrg       if (type != INTERFACE_NAMELESS)
355627f7eb2Smrg 	{
356627f7eb2Smrg 	  gfc_error ("Expected a nameless interface at %C");
357627f7eb2Smrg 	  m = MATCH_ERROR;
358627f7eb2Smrg 	}
359627f7eb2Smrg 
360627f7eb2Smrg       break;
361627f7eb2Smrg 
362627f7eb2Smrg     case INTERFACE_INTRINSIC_OP:
363627f7eb2Smrg       if (type != current_interface.type || op != current_interface.op)
364627f7eb2Smrg 	{
365627f7eb2Smrg 
366627f7eb2Smrg 	  if (current_interface.op == INTRINSIC_ASSIGN)
367627f7eb2Smrg 	    {
368627f7eb2Smrg 	      m = MATCH_ERROR;
369627f7eb2Smrg 	      gfc_error ("Expected %<END INTERFACE ASSIGNMENT (=)%> at %C");
370627f7eb2Smrg 	    }
371627f7eb2Smrg 	  else
372627f7eb2Smrg 	    {
373627f7eb2Smrg 	      const char *s1, *s2;
374627f7eb2Smrg 	      s1 = gfc_op2string (current_interface.op);
375627f7eb2Smrg 	      s2 = gfc_op2string (op);
376627f7eb2Smrg 
377627f7eb2Smrg 	      /* The following if-statements are used to enforce C1202
378627f7eb2Smrg 		 from F2003.  */
379627f7eb2Smrg 	      if ((strcmp(s1, "==") == 0 && strcmp (s2, ".eq.") == 0)
380627f7eb2Smrg 		  || (strcmp(s1, ".eq.") == 0 && strcmp (s2, "==") == 0))
381627f7eb2Smrg 		break;
382627f7eb2Smrg 	      if ((strcmp(s1, "/=") == 0 && strcmp (s2, ".ne.") == 0)
383627f7eb2Smrg 		  || (strcmp(s1, ".ne.") == 0 && strcmp (s2, "/=") == 0))
384627f7eb2Smrg 		break;
385627f7eb2Smrg 	      if ((strcmp(s1, "<=") == 0 && strcmp (s2, ".le.") == 0)
386627f7eb2Smrg 		  || (strcmp(s1, ".le.") == 0 && strcmp (s2, "<=") == 0))
387627f7eb2Smrg 		break;
388627f7eb2Smrg 	      if ((strcmp(s1, "<") == 0 && strcmp (s2, ".lt.") == 0)
389627f7eb2Smrg 		  || (strcmp(s1, ".lt.") == 0 && strcmp (s2, "<") == 0))
390627f7eb2Smrg 		break;
391627f7eb2Smrg 	      if ((strcmp(s1, ">=") == 0 && strcmp (s2, ".ge.") == 0)
392627f7eb2Smrg 		  || (strcmp(s1, ".ge.") == 0 && strcmp (s2, ">=") == 0))
393627f7eb2Smrg 		break;
394627f7eb2Smrg 	      if ((strcmp(s1, ">") == 0 && strcmp (s2, ".gt.") == 0)
395627f7eb2Smrg 		  || (strcmp(s1, ".gt.") == 0 && strcmp (s2, ">") == 0))
396627f7eb2Smrg 		break;
397627f7eb2Smrg 
398627f7eb2Smrg 	      m = MATCH_ERROR;
399627f7eb2Smrg 	      if (strcmp(s2, "none") == 0)
400627f7eb2Smrg 		gfc_error ("Expecting %<END INTERFACE OPERATOR (%s)%> "
401627f7eb2Smrg 			   "at %C", s1);
402627f7eb2Smrg 	      else
403627f7eb2Smrg 		gfc_error ("Expecting %<END INTERFACE OPERATOR (%s)%> at %C, "
404627f7eb2Smrg 			   "but got %qs", s1, s2);
405627f7eb2Smrg 	    }
406627f7eb2Smrg 
407627f7eb2Smrg 	}
408627f7eb2Smrg 
409627f7eb2Smrg       break;
410627f7eb2Smrg 
411627f7eb2Smrg     case INTERFACE_USER_OP:
412627f7eb2Smrg       /* Comparing the symbol node names is OK because only use-associated
413627f7eb2Smrg 	 symbols can be renamed.  */
414627f7eb2Smrg       if (type != current_interface.type
415627f7eb2Smrg 	  || strcmp (current_interface.uop->name, name) != 0)
416627f7eb2Smrg 	{
417627f7eb2Smrg 	  gfc_error ("Expecting %<END INTERFACE OPERATOR (.%s.)%> at %C",
418627f7eb2Smrg 		     current_interface.uop->name);
419627f7eb2Smrg 	  m = MATCH_ERROR;
420627f7eb2Smrg 	}
421627f7eb2Smrg 
422627f7eb2Smrg       break;
423627f7eb2Smrg 
424627f7eb2Smrg     case INTERFACE_DTIO:
425627f7eb2Smrg     case INTERFACE_GENERIC:
426627f7eb2Smrg       if (type != current_interface.type
427627f7eb2Smrg 	  || strcmp (current_interface.sym->name, name) != 0)
428627f7eb2Smrg 	{
429627f7eb2Smrg 	  gfc_error ("Expecting %<END INTERFACE %s%> at %C",
430627f7eb2Smrg 		     current_interface.sym->name);
431627f7eb2Smrg 	  m = MATCH_ERROR;
432627f7eb2Smrg 	}
433627f7eb2Smrg 
434627f7eb2Smrg       break;
435627f7eb2Smrg     }
436627f7eb2Smrg 
437627f7eb2Smrg   return m;
438627f7eb2Smrg }
439627f7eb2Smrg 
440627f7eb2Smrg 
441627f7eb2Smrg /* Return whether the component was defined anonymously.  */
442627f7eb2Smrg 
443627f7eb2Smrg static bool
is_anonymous_component(gfc_component * cmp)444627f7eb2Smrg is_anonymous_component (gfc_component *cmp)
445627f7eb2Smrg {
446627f7eb2Smrg   /* Only UNION and MAP components are anonymous.  In the case of a MAP,
447627f7eb2Smrg      the derived type symbol is FL_STRUCT and the component name looks like mM*.
448627f7eb2Smrg      This is the only case in which the second character of a component name is
449627f7eb2Smrg      uppercase.  */
450627f7eb2Smrg   return cmp->ts.type == BT_UNION
451627f7eb2Smrg     || (cmp->ts.type == BT_DERIVED
452627f7eb2Smrg         && cmp->ts.u.derived->attr.flavor == FL_STRUCT
453627f7eb2Smrg         && cmp->name[0] && cmp->name[1] && ISUPPER (cmp->name[1]));
454627f7eb2Smrg }
455627f7eb2Smrg 
456627f7eb2Smrg 
457627f7eb2Smrg /* Return whether the derived type was defined anonymously.  */
458627f7eb2Smrg 
459627f7eb2Smrg static bool
is_anonymous_dt(gfc_symbol * derived)460627f7eb2Smrg is_anonymous_dt (gfc_symbol *derived)
461627f7eb2Smrg {
462627f7eb2Smrg   /* UNION and MAP types are always anonymous. Otherwise, only nested STRUCTURE
463627f7eb2Smrg      types can be anonymous.  For anonymous MAP/STRUCTURE, we have FL_STRUCT
464627f7eb2Smrg      and the type name looks like XX*.  This is the only case in which the
465627f7eb2Smrg      second character of a type name is uppercase.  */
466627f7eb2Smrg   return derived->attr.flavor == FL_UNION
467627f7eb2Smrg     || (derived->attr.flavor == FL_STRUCT
468627f7eb2Smrg         && derived->name[0] && derived->name[1] && ISUPPER (derived->name[1]));
469627f7eb2Smrg }
470627f7eb2Smrg 
471627f7eb2Smrg 
472627f7eb2Smrg /* Compare components according to 4.4.2 of the Fortran standard.  */
473627f7eb2Smrg 
474627f7eb2Smrg static bool
compare_components(gfc_component * cmp1,gfc_component * cmp2,gfc_symbol * derived1,gfc_symbol * derived2)475627f7eb2Smrg compare_components (gfc_component *cmp1, gfc_component *cmp2,
476627f7eb2Smrg     gfc_symbol *derived1, gfc_symbol *derived2)
477627f7eb2Smrg {
478627f7eb2Smrg   /* Compare names, but not for anonymous components such as UNION or MAP.  */
479627f7eb2Smrg   if (!is_anonymous_component (cmp1) && !is_anonymous_component (cmp2)
480627f7eb2Smrg       && strcmp (cmp1->name, cmp2->name) != 0)
481627f7eb2Smrg     return false;
482627f7eb2Smrg 
483627f7eb2Smrg   if (cmp1->attr.access != cmp2->attr.access)
484627f7eb2Smrg     return false;
485627f7eb2Smrg 
486627f7eb2Smrg   if (cmp1->attr.pointer != cmp2->attr.pointer)
487627f7eb2Smrg     return false;
488627f7eb2Smrg 
489627f7eb2Smrg   if (cmp1->attr.dimension != cmp2->attr.dimension)
490627f7eb2Smrg     return false;
491627f7eb2Smrg 
492627f7eb2Smrg   if (cmp1->attr.allocatable != cmp2->attr.allocatable)
493627f7eb2Smrg     return false;
494627f7eb2Smrg 
495627f7eb2Smrg   if (cmp1->attr.dimension && gfc_compare_array_spec (cmp1->as, cmp2->as) == 0)
496627f7eb2Smrg     return false;
497627f7eb2Smrg 
498627f7eb2Smrg   if (cmp1->ts.type == BT_CHARACTER && cmp2->ts.type == BT_CHARACTER)
499627f7eb2Smrg     {
500627f7eb2Smrg       gfc_charlen *l1 = cmp1->ts.u.cl;
501627f7eb2Smrg       gfc_charlen *l2 = cmp2->ts.u.cl;
502627f7eb2Smrg       if (l1 && l2 && l1->length && l2->length
503627f7eb2Smrg           && l1->length->expr_type == EXPR_CONSTANT
504627f7eb2Smrg           && l2->length->expr_type == EXPR_CONSTANT
505627f7eb2Smrg           && gfc_dep_compare_expr (l1->length, l2->length) != 0)
506627f7eb2Smrg         return false;
507627f7eb2Smrg     }
508627f7eb2Smrg 
509627f7eb2Smrg   /* Make sure that link lists do not put this function into an
510627f7eb2Smrg      endless recursive loop!  */
511627f7eb2Smrg   if (!(cmp1->ts.type == BT_DERIVED && derived1 == cmp1->ts.u.derived)
512627f7eb2Smrg       && !(cmp2->ts.type == BT_DERIVED && derived2 == cmp2->ts.u.derived)
513627f7eb2Smrg       && !gfc_compare_types (&cmp1->ts, &cmp2->ts))
514627f7eb2Smrg     return false;
515627f7eb2Smrg 
516627f7eb2Smrg   else if ( (cmp1->ts.type == BT_DERIVED && derived1 == cmp1->ts.u.derived)
517627f7eb2Smrg         && !(cmp2->ts.type == BT_DERIVED && derived2 == cmp2->ts.u.derived))
518627f7eb2Smrg     return false;
519627f7eb2Smrg 
520627f7eb2Smrg   else if (!(cmp1->ts.type == BT_DERIVED && derived1 == cmp1->ts.u.derived)
521627f7eb2Smrg         &&  (cmp2->ts.type == BT_DERIVED && derived2 == cmp2->ts.u.derived))
522627f7eb2Smrg     return false;
523627f7eb2Smrg 
524627f7eb2Smrg   return true;
525627f7eb2Smrg }
526627f7eb2Smrg 
527627f7eb2Smrg 
528627f7eb2Smrg /* Compare two union types by comparing the components of their maps.
529627f7eb2Smrg    Because unions and maps are anonymous their types get special internal
530627f7eb2Smrg    names; therefore the usual derived type comparison will fail on them.
531627f7eb2Smrg 
532627f7eb2Smrg    Returns nonzero if equal, as with gfc_compare_derived_types. Also as with
533627f7eb2Smrg    gfc_compare_derived_types, 'equal' is closer to meaning 'duplicate
534627f7eb2Smrg    definitions' than 'equivalent structure'. */
535627f7eb2Smrg 
536627f7eb2Smrg static bool
compare_union_types(gfc_symbol * un1,gfc_symbol * un2)537627f7eb2Smrg compare_union_types (gfc_symbol *un1, gfc_symbol *un2)
538627f7eb2Smrg {
539627f7eb2Smrg   gfc_component *map1, *map2, *cmp1, *cmp2;
540627f7eb2Smrg   gfc_symbol *map1_t, *map2_t;
541627f7eb2Smrg 
542627f7eb2Smrg   if (un1->attr.flavor != FL_UNION || un2->attr.flavor != FL_UNION)
543627f7eb2Smrg     return false;
544627f7eb2Smrg 
545627f7eb2Smrg   if (un1->attr.zero_comp != un2->attr.zero_comp)
546627f7eb2Smrg     return false;
547627f7eb2Smrg 
548627f7eb2Smrg   if (un1->attr.zero_comp)
549627f7eb2Smrg     return true;
550627f7eb2Smrg 
551627f7eb2Smrg   map1 = un1->components;
552627f7eb2Smrg   map2 = un2->components;
553627f7eb2Smrg 
554627f7eb2Smrg   /* In terms of 'equality' here we are worried about types which are
555627f7eb2Smrg      declared the same in two places, not types that represent equivalent
556627f7eb2Smrg      structures. (This is common because of FORTRAN's weird scoping rules.)
557627f7eb2Smrg      Though two unions with their maps in different orders could be equivalent,
558627f7eb2Smrg      we will say they are not equal for the purposes of this test; therefore
559627f7eb2Smrg      we compare the maps sequentially. */
560627f7eb2Smrg   for (;;)
561627f7eb2Smrg     {
562627f7eb2Smrg       map1_t = map1->ts.u.derived;
563627f7eb2Smrg       map2_t = map2->ts.u.derived;
564627f7eb2Smrg 
565627f7eb2Smrg       cmp1 = map1_t->components;
566627f7eb2Smrg       cmp2 = map2_t->components;
567627f7eb2Smrg 
568627f7eb2Smrg       /* Protect against null components.  */
569627f7eb2Smrg       if (map1_t->attr.zero_comp != map2_t->attr.zero_comp)
570627f7eb2Smrg 	return false;
571627f7eb2Smrg 
572627f7eb2Smrg       if (map1_t->attr.zero_comp)
573627f7eb2Smrg 	return true;
574627f7eb2Smrg 
575627f7eb2Smrg       for (;;)
576627f7eb2Smrg 	{
577627f7eb2Smrg 	  /* No two fields will ever point to the same map type unless they are
578627f7eb2Smrg 	     the same component, because one map field is created with its type
579627f7eb2Smrg 	     declaration. Therefore don't worry about recursion here. */
580627f7eb2Smrg 	  /* TODO: worry about recursion into parent types of the unions? */
581627f7eb2Smrg 	  if (!compare_components (cmp1, cmp2, map1_t, map2_t))
582627f7eb2Smrg 	    return false;
583627f7eb2Smrg 
584627f7eb2Smrg 	  cmp1 = cmp1->next;
585627f7eb2Smrg 	  cmp2 = cmp2->next;
586627f7eb2Smrg 
587627f7eb2Smrg 	  if (cmp1 == NULL && cmp2 == NULL)
588627f7eb2Smrg 	    break;
589627f7eb2Smrg 	  if (cmp1 == NULL || cmp2 == NULL)
590627f7eb2Smrg 	    return false;
591627f7eb2Smrg 	}
592627f7eb2Smrg 
593627f7eb2Smrg       map1 = map1->next;
594627f7eb2Smrg       map2 = map2->next;
595627f7eb2Smrg 
596627f7eb2Smrg       if (map1 == NULL && map2 == NULL)
597627f7eb2Smrg 	break;
598627f7eb2Smrg       if (map1 == NULL || map2 == NULL)
599627f7eb2Smrg 	return false;
600627f7eb2Smrg     }
601627f7eb2Smrg 
602627f7eb2Smrg   return true;
603627f7eb2Smrg }
604627f7eb2Smrg 
605627f7eb2Smrg 
606627f7eb2Smrg 
607627f7eb2Smrg /* Compare two derived types using the criteria in 4.4.2 of the standard,
608627f7eb2Smrg    recursing through gfc_compare_types for the components.  */
609627f7eb2Smrg 
610627f7eb2Smrg bool
gfc_compare_derived_types(gfc_symbol * derived1,gfc_symbol * derived2)611627f7eb2Smrg gfc_compare_derived_types (gfc_symbol *derived1, gfc_symbol *derived2)
612627f7eb2Smrg {
613627f7eb2Smrg   gfc_component *cmp1, *cmp2;
614627f7eb2Smrg 
615627f7eb2Smrg   if (derived1 == derived2)
616627f7eb2Smrg     return true;
617627f7eb2Smrg 
618627f7eb2Smrg   if (!derived1 || !derived2)
619627f7eb2Smrg     gfc_internal_error ("gfc_compare_derived_types: invalid derived type");
620627f7eb2Smrg 
621627f7eb2Smrg   /* Compare UNION types specially.  */
622627f7eb2Smrg   if (derived1->attr.flavor == FL_UNION || derived2->attr.flavor == FL_UNION)
623627f7eb2Smrg     return compare_union_types (derived1, derived2);
624627f7eb2Smrg 
625627f7eb2Smrg   /* Special case for comparing derived types across namespaces.  If the
626627f7eb2Smrg      true names and module names are the same and the module name is
627627f7eb2Smrg      nonnull, then they are equal.  */
628627f7eb2Smrg   if (strcmp (derived1->name, derived2->name) == 0
629627f7eb2Smrg       && derived1->module != NULL && derived2->module != NULL
630627f7eb2Smrg       && strcmp (derived1->module, derived2->module) == 0)
631627f7eb2Smrg     return true;
632627f7eb2Smrg 
633627f7eb2Smrg   /* Compare type via the rules of the standard.  Both types must have
634627f7eb2Smrg      the SEQUENCE or BIND(C) attribute to be equal. STRUCTUREs are special
635627f7eb2Smrg      because they can be anonymous; therefore two structures with different
636627f7eb2Smrg      names may be equal.  */
637627f7eb2Smrg 
638627f7eb2Smrg   /* Compare names, but not for anonymous types such as UNION or MAP.  */
639627f7eb2Smrg   if (!is_anonymous_dt (derived1) && !is_anonymous_dt (derived2)
640627f7eb2Smrg       && strcmp (derived1->name, derived2->name) != 0)
641627f7eb2Smrg     return false;
642627f7eb2Smrg 
643627f7eb2Smrg   if (derived1->component_access == ACCESS_PRIVATE
644627f7eb2Smrg       || derived2->component_access == ACCESS_PRIVATE)
645627f7eb2Smrg     return false;
646627f7eb2Smrg 
647627f7eb2Smrg   if (!(derived1->attr.sequence && derived2->attr.sequence)
648627f7eb2Smrg       && !(derived1->attr.is_bind_c && derived2->attr.is_bind_c)
649627f7eb2Smrg       && !(derived1->attr.pdt_type && derived2->attr.pdt_type))
650627f7eb2Smrg     return false;
651627f7eb2Smrg 
652627f7eb2Smrg   /* Protect against null components.  */
653627f7eb2Smrg   if (derived1->attr.zero_comp != derived2->attr.zero_comp)
654627f7eb2Smrg     return false;
655627f7eb2Smrg 
656627f7eb2Smrg   if (derived1->attr.zero_comp)
657627f7eb2Smrg     return true;
658627f7eb2Smrg 
659627f7eb2Smrg   cmp1 = derived1->components;
660627f7eb2Smrg   cmp2 = derived2->components;
661627f7eb2Smrg 
662627f7eb2Smrg   /* Since subtypes of SEQUENCE types must be SEQUENCE types as well, a
663627f7eb2Smrg      simple test can speed things up.  Otherwise, lots of things have to
664627f7eb2Smrg      match.  */
665627f7eb2Smrg   for (;;)
666627f7eb2Smrg     {
667627f7eb2Smrg       if (!compare_components (cmp1, cmp2, derived1, derived2))
668627f7eb2Smrg         return false;
669627f7eb2Smrg 
670627f7eb2Smrg       cmp1 = cmp1->next;
671627f7eb2Smrg       cmp2 = cmp2->next;
672627f7eb2Smrg 
673627f7eb2Smrg       if (cmp1 == NULL && cmp2 == NULL)
674627f7eb2Smrg 	break;
675627f7eb2Smrg       if (cmp1 == NULL || cmp2 == NULL)
676627f7eb2Smrg 	return false;
677627f7eb2Smrg     }
678627f7eb2Smrg 
679627f7eb2Smrg   return true;
680627f7eb2Smrg }
681627f7eb2Smrg 
682627f7eb2Smrg 
683627f7eb2Smrg /* Compare two typespecs, recursively if necessary.  */
684627f7eb2Smrg 
685627f7eb2Smrg bool
gfc_compare_types(gfc_typespec * ts1,gfc_typespec * ts2)686627f7eb2Smrg gfc_compare_types (gfc_typespec *ts1, gfc_typespec *ts2)
687627f7eb2Smrg {
688627f7eb2Smrg   /* See if one of the typespecs is a BT_VOID, which is what is being used
689627f7eb2Smrg      to allow the funcs like c_f_pointer to accept any pointer type.
690627f7eb2Smrg      TODO: Possibly should narrow this to just the one typespec coming in
691627f7eb2Smrg      that is for the formal arg, but oh well.  */
692627f7eb2Smrg   if (ts1->type == BT_VOID || ts2->type == BT_VOID)
693627f7eb2Smrg     return true;
694627f7eb2Smrg 
695627f7eb2Smrg   /* Special case for our C interop types.  FIXME: There should be a
696627f7eb2Smrg      better way of doing this.  When ISO C binding is cleared up,
697627f7eb2Smrg      this can probably be removed.  See PR 57048.  */
698627f7eb2Smrg 
699627f7eb2Smrg   if (((ts1->type == BT_INTEGER && ts2->type == BT_DERIVED)
700627f7eb2Smrg        || (ts1->type == BT_DERIVED && ts2->type == BT_INTEGER))
701627f7eb2Smrg       && ts1->u.derived && ts2->u.derived
702627f7eb2Smrg       && ts1->u.derived == ts2->u.derived)
703627f7eb2Smrg     return true;
704627f7eb2Smrg 
705627f7eb2Smrg   /* The _data component is not always present, therefore check for its
706627f7eb2Smrg      presence before assuming, that its derived->attr is available.
707627f7eb2Smrg      When the _data component is not present, then nevertheless the
708627f7eb2Smrg      unlimited_polymorphic flag may be set in the derived type's attr.  */
709627f7eb2Smrg   if (ts1->type == BT_CLASS && ts1->u.derived->components
710627f7eb2Smrg       && ((ts1->u.derived->attr.is_class
711627f7eb2Smrg 	   && ts1->u.derived->components->ts.u.derived->attr
712627f7eb2Smrg 						  .unlimited_polymorphic)
713627f7eb2Smrg 	  || ts1->u.derived->attr.unlimited_polymorphic))
714627f7eb2Smrg     return true;
715627f7eb2Smrg 
716627f7eb2Smrg   /* F2003: C717  */
717627f7eb2Smrg   if (ts2->type == BT_CLASS && ts1->type == BT_DERIVED
718627f7eb2Smrg       && ts2->u.derived->components
719627f7eb2Smrg       && ((ts2->u.derived->attr.is_class
720627f7eb2Smrg 	   && ts2->u.derived->components->ts.u.derived->attr
721627f7eb2Smrg 						  .unlimited_polymorphic)
722627f7eb2Smrg 	  || ts2->u.derived->attr.unlimited_polymorphic)
723627f7eb2Smrg       && (ts1->u.derived->attr.sequence || ts1->u.derived->attr.is_bind_c))
724627f7eb2Smrg     return true;
725627f7eb2Smrg 
726627f7eb2Smrg   if (ts1->type != ts2->type
727627f7eb2Smrg       && ((ts1->type != BT_DERIVED && ts1->type != BT_CLASS)
728627f7eb2Smrg 	  || (ts2->type != BT_DERIVED && ts2->type != BT_CLASS)))
729627f7eb2Smrg     return false;
730627f7eb2Smrg 
731627f7eb2Smrg   if (ts1->type == BT_UNION)
732627f7eb2Smrg     return compare_union_types (ts1->u.derived, ts2->u.derived);
733627f7eb2Smrg 
734627f7eb2Smrg   if (ts1->type != BT_DERIVED && ts1->type != BT_CLASS)
735627f7eb2Smrg     return (ts1->kind == ts2->kind);
736627f7eb2Smrg 
737627f7eb2Smrg   /* Compare derived types.  */
738627f7eb2Smrg   return gfc_type_compatible (ts1, ts2);
739627f7eb2Smrg }
740627f7eb2Smrg 
741627f7eb2Smrg 
742627f7eb2Smrg static bool
compare_type(gfc_symbol * s1,gfc_symbol * s2)743627f7eb2Smrg compare_type (gfc_symbol *s1, gfc_symbol *s2)
744627f7eb2Smrg {
745627f7eb2Smrg   if (s2->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
746627f7eb2Smrg     return true;
747627f7eb2Smrg 
748627f7eb2Smrg   return gfc_compare_types (&s1->ts, &s2->ts) || s2->ts.type == BT_ASSUMED;
749627f7eb2Smrg }
750627f7eb2Smrg 
751627f7eb2Smrg 
752627f7eb2Smrg static bool
compare_type_characteristics(gfc_symbol * s1,gfc_symbol * s2)753627f7eb2Smrg compare_type_characteristics (gfc_symbol *s1, gfc_symbol *s2)
754627f7eb2Smrg {
755627f7eb2Smrg   /* TYPE and CLASS of the same declared type are type compatible,
756627f7eb2Smrg      but have different characteristics.  */
757627f7eb2Smrg   if ((s1->ts.type == BT_CLASS && s2->ts.type == BT_DERIVED)
758627f7eb2Smrg       || (s1->ts.type == BT_DERIVED && s2->ts.type == BT_CLASS))
759627f7eb2Smrg     return false;
760627f7eb2Smrg 
761627f7eb2Smrg   return compare_type (s1, s2);
762627f7eb2Smrg }
763627f7eb2Smrg 
764627f7eb2Smrg 
765627f7eb2Smrg static bool
compare_rank(gfc_symbol * s1,gfc_symbol * s2)766627f7eb2Smrg compare_rank (gfc_symbol *s1, gfc_symbol *s2)
767627f7eb2Smrg {
768627f7eb2Smrg   gfc_array_spec *as1, *as2;
769627f7eb2Smrg   int r1, r2;
770627f7eb2Smrg 
771627f7eb2Smrg   if (s2->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
772627f7eb2Smrg     return true;
773627f7eb2Smrg 
774627f7eb2Smrg   as1 = (s1->ts.type == BT_CLASS
775627f7eb2Smrg 	 && !s1->ts.u.derived->attr.unlimited_polymorphic)
776627f7eb2Smrg 	? CLASS_DATA (s1)->as : s1->as;
777627f7eb2Smrg   as2 = (s2->ts.type == BT_CLASS
778627f7eb2Smrg 	 && !s2->ts.u.derived->attr.unlimited_polymorphic)
779627f7eb2Smrg 	? CLASS_DATA (s2)->as : s2->as;
780627f7eb2Smrg 
781627f7eb2Smrg   r1 = as1 ? as1->rank : 0;
782627f7eb2Smrg   r2 = as2 ? as2->rank : 0;
783627f7eb2Smrg 
784627f7eb2Smrg   if (r1 != r2 && (!as2 || as2->type != AS_ASSUMED_RANK))
785627f7eb2Smrg     return false;  /* Ranks differ.  */
786627f7eb2Smrg 
787627f7eb2Smrg   return true;
788627f7eb2Smrg }
789627f7eb2Smrg 
790627f7eb2Smrg 
791627f7eb2Smrg /* Given two symbols that are formal arguments, compare their ranks
792627f7eb2Smrg    and types.  Returns true if they have the same rank and type,
793627f7eb2Smrg    false otherwise.  */
794627f7eb2Smrg 
795627f7eb2Smrg static bool
compare_type_rank(gfc_symbol * s1,gfc_symbol * s2)796627f7eb2Smrg compare_type_rank (gfc_symbol *s1, gfc_symbol *s2)
797627f7eb2Smrg {
798627f7eb2Smrg   return compare_type (s1, s2) && compare_rank (s1, s2);
799627f7eb2Smrg }
800627f7eb2Smrg 
801627f7eb2Smrg 
802627f7eb2Smrg /* Given two symbols that are formal arguments, compare their types
803627f7eb2Smrg    and rank and their formal interfaces if they are both dummy
804627f7eb2Smrg    procedures.  Returns true if the same, false if different.  */
805627f7eb2Smrg 
806627f7eb2Smrg static bool
compare_type_rank_if(gfc_symbol * s1,gfc_symbol * s2)807627f7eb2Smrg compare_type_rank_if (gfc_symbol *s1, gfc_symbol *s2)
808627f7eb2Smrg {
809627f7eb2Smrg   if (s1 == NULL || s2 == NULL)
810627f7eb2Smrg     return (s1 == s2);
811627f7eb2Smrg 
812627f7eb2Smrg   if (s1 == s2)
813627f7eb2Smrg     return true;
814627f7eb2Smrg 
815627f7eb2Smrg   if (s1->attr.flavor != FL_PROCEDURE && s2->attr.flavor != FL_PROCEDURE)
816627f7eb2Smrg     return compare_type_rank (s1, s2);
817627f7eb2Smrg 
818627f7eb2Smrg   if (s1->attr.flavor != FL_PROCEDURE || s2->attr.flavor != FL_PROCEDURE)
819627f7eb2Smrg     return false;
820627f7eb2Smrg 
821627f7eb2Smrg   /* At this point, both symbols are procedures.  It can happen that
822627f7eb2Smrg      external procedures are compared, where one is identified by usage
823627f7eb2Smrg      to be a function or subroutine but the other is not.  Check TKR
824627f7eb2Smrg      nonetheless for these cases.  */
825627f7eb2Smrg   if (s1->attr.function == 0 && s1->attr.subroutine == 0)
826627f7eb2Smrg     return s1->attr.external ? compare_type_rank (s1, s2) : false;
827627f7eb2Smrg 
828627f7eb2Smrg   if (s2->attr.function == 0 && s2->attr.subroutine == 0)
829627f7eb2Smrg     return s2->attr.external ? compare_type_rank (s1, s2) : false;
830627f7eb2Smrg 
831627f7eb2Smrg   /* Now the type of procedure has been identified.  */
832627f7eb2Smrg   if (s1->attr.function != s2->attr.function
833627f7eb2Smrg       || s1->attr.subroutine != s2->attr.subroutine)
834627f7eb2Smrg     return false;
835627f7eb2Smrg 
836627f7eb2Smrg   if (s1->attr.function && !compare_type_rank (s1, s2))
837627f7eb2Smrg     return false;
838627f7eb2Smrg 
839627f7eb2Smrg   /* Originally, gfortran recursed here to check the interfaces of passed
840627f7eb2Smrg      procedures.  This is explicitly not required by the standard.  */
841627f7eb2Smrg   return true;
842627f7eb2Smrg }
843627f7eb2Smrg 
844627f7eb2Smrg 
845627f7eb2Smrg /* Given a formal argument list and a keyword name, search the list
846627f7eb2Smrg    for that keyword.  Returns the correct symbol node if found, NULL
847627f7eb2Smrg    if not found.  */
848627f7eb2Smrg 
849627f7eb2Smrg static gfc_symbol *
find_keyword_arg(const char * name,gfc_formal_arglist * f)850627f7eb2Smrg find_keyword_arg (const char *name, gfc_formal_arglist *f)
851627f7eb2Smrg {
852627f7eb2Smrg   for (; f; f = f->next)
853627f7eb2Smrg     if (strcmp (f->sym->name, name) == 0)
854627f7eb2Smrg       return f->sym;
855627f7eb2Smrg 
856627f7eb2Smrg   return NULL;
857627f7eb2Smrg }
858627f7eb2Smrg 
859627f7eb2Smrg 
860627f7eb2Smrg /******** Interface checking subroutines **********/
861627f7eb2Smrg 
862627f7eb2Smrg 
863627f7eb2Smrg /* Given an operator interface and the operator, make sure that all
864627f7eb2Smrg    interfaces for that operator are legal.  */
865627f7eb2Smrg 
866627f7eb2Smrg bool
gfc_check_operator_interface(gfc_symbol * sym,gfc_intrinsic_op op,locus opwhere)867627f7eb2Smrg gfc_check_operator_interface (gfc_symbol *sym, gfc_intrinsic_op op,
868627f7eb2Smrg 			      locus opwhere)
869627f7eb2Smrg {
870627f7eb2Smrg   gfc_formal_arglist *formal;
871627f7eb2Smrg   sym_intent i1, i2;
872627f7eb2Smrg   bt t1, t2;
873627f7eb2Smrg   int args, r1, r2, k1, k2;
874627f7eb2Smrg 
875627f7eb2Smrg   gcc_assert (sym);
876627f7eb2Smrg 
877627f7eb2Smrg   args = 0;
878627f7eb2Smrg   t1 = t2 = BT_UNKNOWN;
879627f7eb2Smrg   i1 = i2 = INTENT_UNKNOWN;
880627f7eb2Smrg   r1 = r2 = -1;
881627f7eb2Smrg   k1 = k2 = -1;
882627f7eb2Smrg 
883627f7eb2Smrg   for (formal = gfc_sym_get_dummy_args (sym); formal; formal = formal->next)
884627f7eb2Smrg     {
885627f7eb2Smrg       gfc_symbol *fsym = formal->sym;
886627f7eb2Smrg       if (fsym == NULL)
887627f7eb2Smrg 	{
888627f7eb2Smrg 	  gfc_error ("Alternate return cannot appear in operator "
889627f7eb2Smrg 		     "interface at %L", &sym->declared_at);
890627f7eb2Smrg 	  return false;
891627f7eb2Smrg 	}
892627f7eb2Smrg       if (args == 0)
893627f7eb2Smrg 	{
894627f7eb2Smrg 	  t1 = fsym->ts.type;
895627f7eb2Smrg 	  i1 = fsym->attr.intent;
896627f7eb2Smrg 	  r1 = (fsym->as != NULL) ? fsym->as->rank : 0;
897627f7eb2Smrg 	  k1 = fsym->ts.kind;
898627f7eb2Smrg 	}
899627f7eb2Smrg       if (args == 1)
900627f7eb2Smrg 	{
901627f7eb2Smrg 	  t2 = fsym->ts.type;
902627f7eb2Smrg 	  i2 = fsym->attr.intent;
903627f7eb2Smrg 	  r2 = (fsym->as != NULL) ? fsym->as->rank : 0;
904627f7eb2Smrg 	  k2 = fsym->ts.kind;
905627f7eb2Smrg 	}
906627f7eb2Smrg       args++;
907627f7eb2Smrg     }
908627f7eb2Smrg 
909627f7eb2Smrg   /* Only +, - and .not. can be unary operators.
910627f7eb2Smrg      .not. cannot be a binary operator.  */
911627f7eb2Smrg   if (args == 0 || args > 2 || (args == 1 && op != INTRINSIC_PLUS
912627f7eb2Smrg 				&& op != INTRINSIC_MINUS
913627f7eb2Smrg 				&& op != INTRINSIC_NOT)
914627f7eb2Smrg       || (args == 2 && op == INTRINSIC_NOT))
915627f7eb2Smrg     {
916627f7eb2Smrg       if (op == INTRINSIC_ASSIGN)
917627f7eb2Smrg 	gfc_error ("Assignment operator interface at %L must have "
918627f7eb2Smrg 		   "two arguments", &sym->declared_at);
919627f7eb2Smrg       else
920627f7eb2Smrg 	gfc_error ("Operator interface at %L has the wrong number of arguments",
921627f7eb2Smrg 		   &sym->declared_at);
922627f7eb2Smrg       return false;
923627f7eb2Smrg     }
924627f7eb2Smrg 
925627f7eb2Smrg   /* Check that intrinsics are mapped to functions, except
926627f7eb2Smrg      INTRINSIC_ASSIGN which should map to a subroutine.  */
927627f7eb2Smrg   if (op == INTRINSIC_ASSIGN)
928627f7eb2Smrg     {
929627f7eb2Smrg       gfc_formal_arglist *dummy_args;
930627f7eb2Smrg 
931627f7eb2Smrg       if (!sym->attr.subroutine)
932627f7eb2Smrg 	{
933627f7eb2Smrg 	  gfc_error ("Assignment operator interface at %L must be "
934627f7eb2Smrg 		     "a SUBROUTINE", &sym->declared_at);
935627f7eb2Smrg 	  return false;
936627f7eb2Smrg 	}
937627f7eb2Smrg 
938627f7eb2Smrg       /* Allowed are (per F2003, 12.3.2.1.2 Defined assignments):
939627f7eb2Smrg 	 - First argument an array with different rank than second,
940627f7eb2Smrg 	 - First argument is a scalar and second an array,
941627f7eb2Smrg 	 - Types and kinds do not conform, or
942627f7eb2Smrg 	 - First argument is of derived type.  */
943627f7eb2Smrg       dummy_args = gfc_sym_get_dummy_args (sym);
944627f7eb2Smrg       if (dummy_args->sym->ts.type != BT_DERIVED
945627f7eb2Smrg 	  && dummy_args->sym->ts.type != BT_CLASS
946627f7eb2Smrg 	  && (r2 == 0 || r1 == r2)
947627f7eb2Smrg 	  && (dummy_args->sym->ts.type == dummy_args->next->sym->ts.type
948627f7eb2Smrg 	      || (gfc_numeric_ts (&dummy_args->sym->ts)
949627f7eb2Smrg 		  && gfc_numeric_ts (&dummy_args->next->sym->ts))))
950627f7eb2Smrg 	{
951627f7eb2Smrg 	  gfc_error ("Assignment operator interface at %L must not redefine "
952627f7eb2Smrg 		     "an INTRINSIC type assignment", &sym->declared_at);
953627f7eb2Smrg 	  return false;
954627f7eb2Smrg 	}
955627f7eb2Smrg     }
956627f7eb2Smrg   else
957627f7eb2Smrg     {
958627f7eb2Smrg       if (!sym->attr.function)
959627f7eb2Smrg 	{
960627f7eb2Smrg 	  gfc_error ("Intrinsic operator interface at %L must be a FUNCTION",
961627f7eb2Smrg 		     &sym->declared_at);
962627f7eb2Smrg 	  return false;
963627f7eb2Smrg 	}
964627f7eb2Smrg     }
965627f7eb2Smrg 
966627f7eb2Smrg   /* Check intents on operator interfaces.  */
967627f7eb2Smrg   if (op == INTRINSIC_ASSIGN)
968627f7eb2Smrg     {
969627f7eb2Smrg       if (i1 != INTENT_OUT && i1 != INTENT_INOUT)
970627f7eb2Smrg 	{
971627f7eb2Smrg 	  gfc_error ("First argument of defined assignment at %L must be "
972627f7eb2Smrg 		     "INTENT(OUT) or INTENT(INOUT)", &sym->declared_at);
973627f7eb2Smrg 	  return false;
974627f7eb2Smrg 	}
975627f7eb2Smrg 
976627f7eb2Smrg       if (i2 != INTENT_IN)
977627f7eb2Smrg 	{
978627f7eb2Smrg 	  gfc_error ("Second argument of defined assignment at %L must be "
979627f7eb2Smrg 		     "INTENT(IN)", &sym->declared_at);
980627f7eb2Smrg 	  return false;
981627f7eb2Smrg 	}
982627f7eb2Smrg     }
983627f7eb2Smrg   else
984627f7eb2Smrg     {
985627f7eb2Smrg       if (i1 != INTENT_IN)
986627f7eb2Smrg 	{
987627f7eb2Smrg 	  gfc_error ("First argument of operator interface at %L must be "
988627f7eb2Smrg 		     "INTENT(IN)", &sym->declared_at);
989627f7eb2Smrg 	  return false;
990627f7eb2Smrg 	}
991627f7eb2Smrg 
992627f7eb2Smrg       if (args == 2 && i2 != INTENT_IN)
993627f7eb2Smrg 	{
994627f7eb2Smrg 	  gfc_error ("Second argument of operator interface at %L must be "
995627f7eb2Smrg 		     "INTENT(IN)", &sym->declared_at);
996627f7eb2Smrg 	  return false;
997627f7eb2Smrg 	}
998627f7eb2Smrg     }
999627f7eb2Smrg 
1000627f7eb2Smrg   /* From now on, all we have to do is check that the operator definition
1001627f7eb2Smrg      doesn't conflict with an intrinsic operator. The rules for this
1002627f7eb2Smrg      game are defined in 7.1.2 and 7.1.3 of both F95 and F2003 standards,
1003627f7eb2Smrg      as well as 12.3.2.1.1 of Fortran 2003:
1004627f7eb2Smrg 
1005627f7eb2Smrg      "If the operator is an intrinsic-operator (R310), the number of
1006627f7eb2Smrg      function arguments shall be consistent with the intrinsic uses of
1007627f7eb2Smrg      that operator, and the types, kind type parameters, or ranks of the
1008627f7eb2Smrg      dummy arguments shall differ from those required for the intrinsic
1009627f7eb2Smrg      operation (7.1.2)."  */
1010627f7eb2Smrg 
1011627f7eb2Smrg #define IS_NUMERIC_TYPE(t) \
1012627f7eb2Smrg   ((t) == BT_INTEGER || (t) == BT_REAL || (t) == BT_COMPLEX)
1013627f7eb2Smrg 
1014627f7eb2Smrg   /* Unary ops are easy, do them first.  */
1015627f7eb2Smrg   if (op == INTRINSIC_NOT)
1016627f7eb2Smrg     {
1017627f7eb2Smrg       if (t1 == BT_LOGICAL)
1018627f7eb2Smrg 	goto bad_repl;
1019627f7eb2Smrg       else
1020627f7eb2Smrg 	return true;
1021627f7eb2Smrg     }
1022627f7eb2Smrg 
1023627f7eb2Smrg   if (args == 1 && (op == INTRINSIC_PLUS || op == INTRINSIC_MINUS))
1024627f7eb2Smrg     {
1025627f7eb2Smrg       if (IS_NUMERIC_TYPE (t1))
1026627f7eb2Smrg 	goto bad_repl;
1027627f7eb2Smrg       else
1028627f7eb2Smrg 	return true;
1029627f7eb2Smrg     }
1030627f7eb2Smrg 
1031627f7eb2Smrg   /* Character intrinsic operators have same character kind, thus
1032627f7eb2Smrg      operator definitions with operands of different character kinds
1033627f7eb2Smrg      are always safe.  */
1034627f7eb2Smrg   if (t1 == BT_CHARACTER && t2 == BT_CHARACTER && k1 != k2)
1035627f7eb2Smrg     return true;
1036627f7eb2Smrg 
1037627f7eb2Smrg   /* Intrinsic operators always perform on arguments of same rank,
1038627f7eb2Smrg      so different ranks is also always safe.  (rank == 0) is an exception
1039627f7eb2Smrg      to that, because all intrinsic operators are elemental.  */
1040627f7eb2Smrg   if (r1 != r2 && r1 != 0 && r2 != 0)
1041627f7eb2Smrg     return true;
1042627f7eb2Smrg 
1043627f7eb2Smrg   switch (op)
1044627f7eb2Smrg   {
1045627f7eb2Smrg     case INTRINSIC_EQ:
1046627f7eb2Smrg     case INTRINSIC_EQ_OS:
1047627f7eb2Smrg     case INTRINSIC_NE:
1048627f7eb2Smrg     case INTRINSIC_NE_OS:
1049627f7eb2Smrg       if (t1 == BT_CHARACTER && t2 == BT_CHARACTER)
1050627f7eb2Smrg 	goto bad_repl;
1051627f7eb2Smrg       /* Fall through.  */
1052627f7eb2Smrg 
1053627f7eb2Smrg     case INTRINSIC_PLUS:
1054627f7eb2Smrg     case INTRINSIC_MINUS:
1055627f7eb2Smrg     case INTRINSIC_TIMES:
1056627f7eb2Smrg     case INTRINSIC_DIVIDE:
1057627f7eb2Smrg     case INTRINSIC_POWER:
1058627f7eb2Smrg       if (IS_NUMERIC_TYPE (t1) && IS_NUMERIC_TYPE (t2))
1059627f7eb2Smrg 	goto bad_repl;
1060627f7eb2Smrg       break;
1061627f7eb2Smrg 
1062627f7eb2Smrg     case INTRINSIC_GT:
1063627f7eb2Smrg     case INTRINSIC_GT_OS:
1064627f7eb2Smrg     case INTRINSIC_GE:
1065627f7eb2Smrg     case INTRINSIC_GE_OS:
1066627f7eb2Smrg     case INTRINSIC_LT:
1067627f7eb2Smrg     case INTRINSIC_LT_OS:
1068627f7eb2Smrg     case INTRINSIC_LE:
1069627f7eb2Smrg     case INTRINSIC_LE_OS:
1070627f7eb2Smrg       if (t1 == BT_CHARACTER && t2 == BT_CHARACTER)
1071627f7eb2Smrg 	goto bad_repl;
1072627f7eb2Smrg       if ((t1 == BT_INTEGER || t1 == BT_REAL)
1073627f7eb2Smrg 	  && (t2 == BT_INTEGER || t2 == BT_REAL))
1074627f7eb2Smrg 	goto bad_repl;
1075627f7eb2Smrg       break;
1076627f7eb2Smrg 
1077627f7eb2Smrg     case INTRINSIC_CONCAT:
1078627f7eb2Smrg       if (t1 == BT_CHARACTER && t2 == BT_CHARACTER)
1079627f7eb2Smrg 	goto bad_repl;
1080627f7eb2Smrg       break;
1081627f7eb2Smrg 
1082627f7eb2Smrg     case INTRINSIC_AND:
1083627f7eb2Smrg     case INTRINSIC_OR:
1084627f7eb2Smrg     case INTRINSIC_EQV:
1085627f7eb2Smrg     case INTRINSIC_NEQV:
1086627f7eb2Smrg       if (t1 == BT_LOGICAL && t2 == BT_LOGICAL)
1087627f7eb2Smrg 	goto bad_repl;
1088627f7eb2Smrg       break;
1089627f7eb2Smrg 
1090627f7eb2Smrg     default:
1091627f7eb2Smrg       break;
1092627f7eb2Smrg   }
1093627f7eb2Smrg 
1094627f7eb2Smrg   return true;
1095627f7eb2Smrg 
1096627f7eb2Smrg #undef IS_NUMERIC_TYPE
1097627f7eb2Smrg 
1098627f7eb2Smrg bad_repl:
1099627f7eb2Smrg   gfc_error ("Operator interface at %L conflicts with intrinsic interface",
1100627f7eb2Smrg 	     &opwhere);
1101627f7eb2Smrg   return false;
1102627f7eb2Smrg }
1103627f7eb2Smrg 
1104627f7eb2Smrg 
1105627f7eb2Smrg /* Given a pair of formal argument lists, we see if the two lists can
1106627f7eb2Smrg    be distinguished by counting the number of nonoptional arguments of
1107627f7eb2Smrg    a given type/rank in f1 and seeing if there are less then that
1108627f7eb2Smrg    number of those arguments in f2 (including optional arguments).
1109627f7eb2Smrg    Since this test is asymmetric, it has to be called twice to make it
1110627f7eb2Smrg    symmetric. Returns nonzero if the argument lists are incompatible
1111627f7eb2Smrg    by this test. This subroutine implements rule 1 of section F03:16.2.3.
1112627f7eb2Smrg    'p1' and 'p2' are the PASS arguments of both procedures (if applicable).  */
1113627f7eb2Smrg 
1114627f7eb2Smrg static bool
count_types_test(gfc_formal_arglist * f1,gfc_formal_arglist * f2,const char * p1,const char * p2)1115627f7eb2Smrg count_types_test (gfc_formal_arglist *f1, gfc_formal_arglist *f2,
1116627f7eb2Smrg 		  const char *p1, const char *p2)
1117627f7eb2Smrg {
1118627f7eb2Smrg   int ac1, ac2, i, j, k, n1;
1119627f7eb2Smrg   gfc_formal_arglist *f;
1120627f7eb2Smrg 
1121627f7eb2Smrg   typedef struct
1122627f7eb2Smrg   {
1123627f7eb2Smrg     int flag;
1124627f7eb2Smrg     gfc_symbol *sym;
1125627f7eb2Smrg   }
1126627f7eb2Smrg   arginfo;
1127627f7eb2Smrg 
1128627f7eb2Smrg   arginfo *arg;
1129627f7eb2Smrg 
1130627f7eb2Smrg   n1 = 0;
1131627f7eb2Smrg 
1132627f7eb2Smrg   for (f = f1; f; f = f->next)
1133627f7eb2Smrg     n1++;
1134627f7eb2Smrg 
1135627f7eb2Smrg   /* Build an array of integers that gives the same integer to
1136627f7eb2Smrg      arguments of the same type/rank.  */
1137627f7eb2Smrg   arg = XCNEWVEC (arginfo, n1);
1138627f7eb2Smrg 
1139627f7eb2Smrg   f = f1;
1140627f7eb2Smrg   for (i = 0; i < n1; i++, f = f->next)
1141627f7eb2Smrg     {
1142627f7eb2Smrg       arg[i].flag = -1;
1143627f7eb2Smrg       arg[i].sym = f->sym;
1144627f7eb2Smrg     }
1145627f7eb2Smrg 
1146627f7eb2Smrg   k = 0;
1147627f7eb2Smrg 
1148627f7eb2Smrg   for (i = 0; i < n1; i++)
1149627f7eb2Smrg     {
1150627f7eb2Smrg       if (arg[i].flag != -1)
1151627f7eb2Smrg 	continue;
1152627f7eb2Smrg 
1153627f7eb2Smrg       if (arg[i].sym && (arg[i].sym->attr.optional
1154627f7eb2Smrg 			 || (p1 && strcmp (arg[i].sym->name, p1) == 0)))
1155627f7eb2Smrg 	continue;		/* Skip OPTIONAL and PASS arguments.  */
1156627f7eb2Smrg 
1157627f7eb2Smrg       arg[i].flag = k;
1158627f7eb2Smrg 
1159627f7eb2Smrg       /* Find other non-optional, non-pass arguments of the same type/rank.  */
1160627f7eb2Smrg       for (j = i + 1; j < n1; j++)
1161627f7eb2Smrg 	if ((arg[j].sym == NULL
1162627f7eb2Smrg 	     || !(arg[j].sym->attr.optional
1163627f7eb2Smrg 		  || (p1 && strcmp (arg[j].sym->name, p1) == 0)))
1164627f7eb2Smrg 	    && (compare_type_rank_if (arg[i].sym, arg[j].sym)
1165627f7eb2Smrg 	        || compare_type_rank_if (arg[j].sym, arg[i].sym)))
1166627f7eb2Smrg 	  arg[j].flag = k;
1167627f7eb2Smrg 
1168627f7eb2Smrg       k++;
1169627f7eb2Smrg     }
1170627f7eb2Smrg 
1171627f7eb2Smrg   /* Now loop over each distinct type found in f1.  */
1172627f7eb2Smrg   k = 0;
1173627f7eb2Smrg   bool rc = false;
1174627f7eb2Smrg 
1175627f7eb2Smrg   for (i = 0; i < n1; i++)
1176627f7eb2Smrg     {
1177627f7eb2Smrg       if (arg[i].flag != k)
1178627f7eb2Smrg 	continue;
1179627f7eb2Smrg 
1180627f7eb2Smrg       ac1 = 1;
1181627f7eb2Smrg       for (j = i + 1; j < n1; j++)
1182627f7eb2Smrg 	if (arg[j].flag == k)
1183627f7eb2Smrg 	  ac1++;
1184627f7eb2Smrg 
1185627f7eb2Smrg       /* Count the number of non-pass arguments in f2 with that type,
1186627f7eb2Smrg 	 including those that are optional.  */
1187627f7eb2Smrg       ac2 = 0;
1188627f7eb2Smrg 
1189627f7eb2Smrg       for (f = f2; f; f = f->next)
1190627f7eb2Smrg 	if ((!p2 || strcmp (f->sym->name, p2) != 0)
1191627f7eb2Smrg 	    && (compare_type_rank_if (arg[i].sym, f->sym)
1192627f7eb2Smrg 		|| compare_type_rank_if (f->sym, arg[i].sym)))
1193627f7eb2Smrg 	  ac2++;
1194627f7eb2Smrg 
1195627f7eb2Smrg       if (ac1 > ac2)
1196627f7eb2Smrg 	{
1197627f7eb2Smrg 	  rc = true;
1198627f7eb2Smrg 	  break;
1199627f7eb2Smrg 	}
1200627f7eb2Smrg 
1201627f7eb2Smrg       k++;
1202627f7eb2Smrg     }
1203627f7eb2Smrg 
1204627f7eb2Smrg   free (arg);
1205627f7eb2Smrg 
1206627f7eb2Smrg   return rc;
1207627f7eb2Smrg }
1208627f7eb2Smrg 
1209627f7eb2Smrg 
1210627f7eb2Smrg /* Returns true if two dummy arguments are distinguishable due to their POINTER
1211627f7eb2Smrg    and ALLOCATABLE attributes according to F2018 section 15.4.3.4.5 (3).
1212627f7eb2Smrg    The function is asymmetric wrt to the arguments s1 and s2 and should always
1213627f7eb2Smrg    be called twice (with flipped arguments in the second call).  */
1214627f7eb2Smrg 
1215627f7eb2Smrg static bool
compare_ptr_alloc(gfc_symbol * s1,gfc_symbol * s2)1216627f7eb2Smrg compare_ptr_alloc(gfc_symbol *s1, gfc_symbol *s2)
1217627f7eb2Smrg {
1218627f7eb2Smrg   /* Is s1 allocatable?  */
1219627f7eb2Smrg   const bool a1 = s1->ts.type == BT_CLASS ?
1220627f7eb2Smrg 		  CLASS_DATA(s1)->attr.allocatable : s1->attr.allocatable;
1221627f7eb2Smrg   /* Is s2 a pointer?  */
1222627f7eb2Smrg   const bool p2 = s2->ts.type == BT_CLASS ?
1223627f7eb2Smrg 		  CLASS_DATA(s2)->attr.class_pointer : s2->attr.pointer;
1224627f7eb2Smrg   return a1 && p2 && (s2->attr.intent != INTENT_IN);
1225627f7eb2Smrg }
1226627f7eb2Smrg 
1227627f7eb2Smrg 
1228627f7eb2Smrg /* Perform the correspondence test in rule (3) of F08:C1215.
1229627f7eb2Smrg    Returns zero if no argument is found that satisfies this rule,
1230627f7eb2Smrg    nonzero otherwise. 'p1' and 'p2' are the PASS arguments of both procedures
1231627f7eb2Smrg    (if applicable).
1232627f7eb2Smrg 
1233627f7eb2Smrg    This test is also not symmetric in f1 and f2 and must be called
1234627f7eb2Smrg    twice.  This test finds problems caused by sorting the actual
1235627f7eb2Smrg    argument list with keywords.  For example:
1236627f7eb2Smrg 
1237627f7eb2Smrg    INTERFACE FOO
1238627f7eb2Smrg      SUBROUTINE F1(A, B)
1239627f7eb2Smrg        INTEGER :: A ; REAL :: B
1240627f7eb2Smrg      END SUBROUTINE F1
1241627f7eb2Smrg 
1242627f7eb2Smrg      SUBROUTINE F2(B, A)
1243627f7eb2Smrg        INTEGER :: A ; REAL :: B
1244627f7eb2Smrg      END SUBROUTINE F1
1245627f7eb2Smrg    END INTERFACE FOO
1246627f7eb2Smrg 
1247627f7eb2Smrg    At this point, 'CALL FOO(A=1, B=1.0)' is ambiguous.  */
1248627f7eb2Smrg 
1249627f7eb2Smrg static bool
generic_correspondence(gfc_formal_arglist * f1,gfc_formal_arglist * f2,const char * p1,const char * p2)1250627f7eb2Smrg generic_correspondence (gfc_formal_arglist *f1, gfc_formal_arglist *f2,
1251627f7eb2Smrg 			const char *p1, const char *p2)
1252627f7eb2Smrg {
1253627f7eb2Smrg   gfc_formal_arglist *f2_save, *g;
1254627f7eb2Smrg   gfc_symbol *sym;
1255627f7eb2Smrg 
1256627f7eb2Smrg   f2_save = f2;
1257627f7eb2Smrg 
1258627f7eb2Smrg   while (f1)
1259627f7eb2Smrg     {
1260627f7eb2Smrg       if (f1->sym->attr.optional)
1261627f7eb2Smrg 	goto next;
1262627f7eb2Smrg 
1263627f7eb2Smrg       if (p1 && strcmp (f1->sym->name, p1) == 0)
1264627f7eb2Smrg 	f1 = f1->next;
1265627f7eb2Smrg       if (f2 && p2 && strcmp (f2->sym->name, p2) == 0)
1266627f7eb2Smrg 	f2 = f2->next;
1267627f7eb2Smrg 
1268627f7eb2Smrg       if (f2 != NULL && (compare_type_rank (f1->sym, f2->sym)
1269627f7eb2Smrg 			 || compare_type_rank (f2->sym, f1->sym))
1270627f7eb2Smrg 	  && !((gfc_option.allow_std & GFC_STD_F2008)
1271627f7eb2Smrg 	       && (compare_ptr_alloc(f1->sym, f2->sym)
1272627f7eb2Smrg 		   || compare_ptr_alloc(f2->sym, f1->sym))))
1273627f7eb2Smrg 	goto next;
1274627f7eb2Smrg 
1275627f7eb2Smrg       /* Now search for a disambiguating keyword argument starting at
1276627f7eb2Smrg 	 the current non-match.  */
1277627f7eb2Smrg       for (g = f1; g; g = g->next)
1278627f7eb2Smrg 	{
1279627f7eb2Smrg 	  if (g->sym->attr.optional || (p1 && strcmp (g->sym->name, p1) == 0))
1280627f7eb2Smrg 	    continue;
1281627f7eb2Smrg 
1282627f7eb2Smrg 	  sym = find_keyword_arg (g->sym->name, f2_save);
1283627f7eb2Smrg 	  if (sym == NULL || !compare_type_rank (g->sym, sym)
1284627f7eb2Smrg 	      || ((gfc_option.allow_std & GFC_STD_F2008)
1285627f7eb2Smrg 		  && (compare_ptr_alloc(sym, g->sym)
1286627f7eb2Smrg 		      || compare_ptr_alloc(g->sym, sym))))
1287627f7eb2Smrg 	    return true;
1288627f7eb2Smrg 	}
1289627f7eb2Smrg 
1290627f7eb2Smrg     next:
1291627f7eb2Smrg       if (f1 != NULL)
1292627f7eb2Smrg 	f1 = f1->next;
1293627f7eb2Smrg       if (f2 != NULL)
1294627f7eb2Smrg 	f2 = f2->next;
1295627f7eb2Smrg     }
1296627f7eb2Smrg 
1297627f7eb2Smrg   return false;
1298627f7eb2Smrg }
1299627f7eb2Smrg 
1300627f7eb2Smrg 
1301627f7eb2Smrg static int
symbol_rank(gfc_symbol * sym)1302627f7eb2Smrg symbol_rank (gfc_symbol *sym)
1303627f7eb2Smrg {
1304627f7eb2Smrg   gfc_array_spec *as = NULL;
1305627f7eb2Smrg 
1306627f7eb2Smrg   if (sym->ts.type == BT_CLASS && CLASS_DATA (sym))
1307627f7eb2Smrg     as = CLASS_DATA (sym)->as;
1308627f7eb2Smrg   else
1309627f7eb2Smrg     as = sym->as;
1310627f7eb2Smrg 
1311627f7eb2Smrg   return as ? as->rank : 0;
1312627f7eb2Smrg }
1313627f7eb2Smrg 
1314627f7eb2Smrg 
1315627f7eb2Smrg /* Check if the characteristics of two dummy arguments match,
1316627f7eb2Smrg    cf. F08:12.3.2.  */
1317627f7eb2Smrg 
1318627f7eb2Smrg bool
gfc_check_dummy_characteristics(gfc_symbol * s1,gfc_symbol * s2,bool type_must_agree,char * errmsg,int err_len)1319627f7eb2Smrg gfc_check_dummy_characteristics (gfc_symbol *s1, gfc_symbol *s2,
1320627f7eb2Smrg 				 bool type_must_agree, char *errmsg,
1321627f7eb2Smrg 				 int err_len)
1322627f7eb2Smrg {
1323627f7eb2Smrg   if (s1 == NULL || s2 == NULL)
1324627f7eb2Smrg     return s1 == s2 ? true : false;
1325627f7eb2Smrg 
1326627f7eb2Smrg   /* Check type and rank.  */
1327627f7eb2Smrg   if (type_must_agree)
1328627f7eb2Smrg     {
1329627f7eb2Smrg       if (!compare_type_characteristics (s1, s2)
1330627f7eb2Smrg 	  || !compare_type_characteristics (s2, s1))
1331627f7eb2Smrg 	{
1332627f7eb2Smrg 	  snprintf (errmsg, err_len, "Type mismatch in argument '%s' (%s/%s)",
13334c3eb207Smrg 		    s1->name, gfc_dummy_typename (&s1->ts),
13344c3eb207Smrg 		    gfc_dummy_typename (&s2->ts));
1335627f7eb2Smrg 	  return false;
1336627f7eb2Smrg 	}
1337627f7eb2Smrg       if (!compare_rank (s1, s2))
1338627f7eb2Smrg 	{
1339627f7eb2Smrg 	  snprintf (errmsg, err_len, "Rank mismatch in argument '%s' (%i/%i)",
1340627f7eb2Smrg 		    s1->name, symbol_rank (s1), symbol_rank (s2));
1341627f7eb2Smrg 	  return false;
1342627f7eb2Smrg 	}
1343627f7eb2Smrg     }
1344627f7eb2Smrg 
1345627f7eb2Smrg   /* Check INTENT.  */
1346627f7eb2Smrg   if (s1->attr.intent != s2->attr.intent)
1347627f7eb2Smrg     {
1348627f7eb2Smrg       snprintf (errmsg, err_len, "INTENT mismatch in argument '%s'",
1349627f7eb2Smrg 		s1->name);
1350627f7eb2Smrg       return false;
1351627f7eb2Smrg     }
1352627f7eb2Smrg 
1353627f7eb2Smrg   /* Check OPTIONAL attribute.  */
1354627f7eb2Smrg   if (s1->attr.optional != s2->attr.optional)
1355627f7eb2Smrg     {
1356627f7eb2Smrg       snprintf (errmsg, err_len, "OPTIONAL mismatch in argument '%s'",
1357627f7eb2Smrg 		s1->name);
1358627f7eb2Smrg       return false;
1359627f7eb2Smrg     }
1360627f7eb2Smrg 
1361627f7eb2Smrg   /* Check ALLOCATABLE attribute.  */
1362627f7eb2Smrg   if (s1->attr.allocatable != s2->attr.allocatable)
1363627f7eb2Smrg     {
1364627f7eb2Smrg       snprintf (errmsg, err_len, "ALLOCATABLE mismatch in argument '%s'",
1365627f7eb2Smrg 		s1->name);
1366627f7eb2Smrg       return false;
1367627f7eb2Smrg     }
1368627f7eb2Smrg 
1369627f7eb2Smrg   /* Check POINTER attribute.  */
1370627f7eb2Smrg   if (s1->attr.pointer != s2->attr.pointer)
1371627f7eb2Smrg     {
1372627f7eb2Smrg       snprintf (errmsg, err_len, "POINTER mismatch in argument '%s'",
1373627f7eb2Smrg 		s1->name);
1374627f7eb2Smrg       return false;
1375627f7eb2Smrg     }
1376627f7eb2Smrg 
1377627f7eb2Smrg   /* Check TARGET attribute.  */
1378627f7eb2Smrg   if (s1->attr.target != s2->attr.target)
1379627f7eb2Smrg     {
1380627f7eb2Smrg       snprintf (errmsg, err_len, "TARGET mismatch in argument '%s'",
1381627f7eb2Smrg 		s1->name);
1382627f7eb2Smrg       return false;
1383627f7eb2Smrg     }
1384627f7eb2Smrg 
1385627f7eb2Smrg   /* Check ASYNCHRONOUS attribute.  */
1386627f7eb2Smrg   if (s1->attr.asynchronous != s2->attr.asynchronous)
1387627f7eb2Smrg     {
1388627f7eb2Smrg       snprintf (errmsg, err_len, "ASYNCHRONOUS mismatch in argument '%s'",
1389627f7eb2Smrg 		s1->name);
1390627f7eb2Smrg       return false;
1391627f7eb2Smrg     }
1392627f7eb2Smrg 
1393627f7eb2Smrg   /* Check CONTIGUOUS attribute.  */
1394627f7eb2Smrg   if (s1->attr.contiguous != s2->attr.contiguous)
1395627f7eb2Smrg     {
1396627f7eb2Smrg       snprintf (errmsg, err_len, "CONTIGUOUS mismatch in argument '%s'",
1397627f7eb2Smrg 		s1->name);
1398627f7eb2Smrg       return false;
1399627f7eb2Smrg     }
1400627f7eb2Smrg 
1401627f7eb2Smrg   /* Check VALUE attribute.  */
1402627f7eb2Smrg   if (s1->attr.value != s2->attr.value)
1403627f7eb2Smrg     {
1404627f7eb2Smrg       snprintf (errmsg, err_len, "VALUE mismatch in argument '%s'",
1405627f7eb2Smrg 		s1->name);
1406627f7eb2Smrg       return false;
1407627f7eb2Smrg     }
1408627f7eb2Smrg 
1409627f7eb2Smrg   /* Check VOLATILE attribute.  */
1410627f7eb2Smrg   if (s1->attr.volatile_ != s2->attr.volatile_)
1411627f7eb2Smrg     {
1412627f7eb2Smrg       snprintf (errmsg, err_len, "VOLATILE mismatch in argument '%s'",
1413627f7eb2Smrg 		s1->name);
1414627f7eb2Smrg       return false;
1415627f7eb2Smrg     }
1416627f7eb2Smrg 
1417627f7eb2Smrg   /* Check interface of dummy procedures.  */
1418627f7eb2Smrg   if (s1->attr.flavor == FL_PROCEDURE)
1419627f7eb2Smrg     {
1420627f7eb2Smrg       char err[200];
1421627f7eb2Smrg       if (!gfc_compare_interfaces (s1, s2, s2->name, 0, 1, err, sizeof(err),
1422627f7eb2Smrg 				   NULL, NULL))
1423627f7eb2Smrg 	{
1424627f7eb2Smrg 	  snprintf (errmsg, err_len, "Interface mismatch in dummy procedure "
1425627f7eb2Smrg 		    "'%s': %s", s1->name, err);
1426627f7eb2Smrg 	  return false;
1427627f7eb2Smrg 	}
1428627f7eb2Smrg     }
1429627f7eb2Smrg 
1430627f7eb2Smrg   /* Check string length.  */
1431627f7eb2Smrg   if (s1->ts.type == BT_CHARACTER
1432627f7eb2Smrg       && s1->ts.u.cl && s1->ts.u.cl->length
1433627f7eb2Smrg       && s2->ts.u.cl && s2->ts.u.cl->length)
1434627f7eb2Smrg     {
1435627f7eb2Smrg       int compval = gfc_dep_compare_expr (s1->ts.u.cl->length,
1436627f7eb2Smrg 					  s2->ts.u.cl->length);
1437627f7eb2Smrg       switch (compval)
1438627f7eb2Smrg       {
1439627f7eb2Smrg 	case -1:
1440627f7eb2Smrg 	case  1:
1441627f7eb2Smrg 	case -3:
1442627f7eb2Smrg 	  snprintf (errmsg, err_len, "Character length mismatch "
1443627f7eb2Smrg 		    "in argument '%s'", s1->name);
1444627f7eb2Smrg 	  return false;
1445627f7eb2Smrg 
1446627f7eb2Smrg 	case -2:
1447627f7eb2Smrg 	  /* FIXME: Implement a warning for this case.
1448627f7eb2Smrg 	  gfc_warning (0, "Possible character length mismatch in argument %qs",
1449627f7eb2Smrg 		       s1->name);*/
1450627f7eb2Smrg 	  break;
1451627f7eb2Smrg 
1452627f7eb2Smrg 	case 0:
1453627f7eb2Smrg 	  break;
1454627f7eb2Smrg 
1455627f7eb2Smrg 	default:
1456627f7eb2Smrg 	  gfc_internal_error ("check_dummy_characteristics: Unexpected result "
1457627f7eb2Smrg 			      "%i of gfc_dep_compare_expr", compval);
1458627f7eb2Smrg 	  break;
1459627f7eb2Smrg       }
1460627f7eb2Smrg     }
1461627f7eb2Smrg 
1462627f7eb2Smrg   /* Check array shape.  */
1463627f7eb2Smrg   if (s1->as && s2->as)
1464627f7eb2Smrg     {
1465627f7eb2Smrg       int i, compval;
1466627f7eb2Smrg       gfc_expr *shape1, *shape2;
1467627f7eb2Smrg 
14684c3eb207Smrg       /* Sometimes the ambiguity between deferred shape and assumed shape
14694c3eb207Smrg 	 does not get resolved in module procedures, where the only explicit
14704c3eb207Smrg 	 declaration of the dummy is in the interface.  */
14714c3eb207Smrg       if (s1->ns->proc_name && s1->ns->proc_name->attr.module_procedure
14724c3eb207Smrg 	  && s1->as->type == AS_ASSUMED_SHAPE
14734c3eb207Smrg 	  && s2->as->type == AS_DEFERRED)
14744c3eb207Smrg 	{
14754c3eb207Smrg 	  s2->as->type = AS_ASSUMED_SHAPE;
14764c3eb207Smrg 	  for (i = 0; i < s2->as->rank; i++)
14774c3eb207Smrg 	    if (s1->as->lower[i] != NULL)
14784c3eb207Smrg 	      s2->as->lower[i] = gfc_copy_expr (s1->as->lower[i]);
14794c3eb207Smrg 	}
14804c3eb207Smrg 
1481627f7eb2Smrg       if (s1->as->type != s2->as->type)
1482627f7eb2Smrg 	{
1483627f7eb2Smrg 	  snprintf (errmsg, err_len, "Shape mismatch in argument '%s'",
1484627f7eb2Smrg 		    s1->name);
1485627f7eb2Smrg 	  return false;
1486627f7eb2Smrg 	}
1487627f7eb2Smrg 
1488627f7eb2Smrg       if (s1->as->corank != s2->as->corank)
1489627f7eb2Smrg 	{
1490627f7eb2Smrg 	  snprintf (errmsg, err_len, "Corank mismatch in argument '%s' (%i/%i)",
1491627f7eb2Smrg 		    s1->name, s1->as->corank, s2->as->corank);
1492627f7eb2Smrg 	  return false;
1493627f7eb2Smrg 	}
1494627f7eb2Smrg 
1495627f7eb2Smrg       if (s1->as->type == AS_EXPLICIT)
1496627f7eb2Smrg 	for (i = 0; i < s1->as->rank + MAX (0, s1->as->corank-1); i++)
1497627f7eb2Smrg 	  {
1498627f7eb2Smrg 	    shape1 = gfc_subtract (gfc_copy_expr (s1->as->upper[i]),
1499627f7eb2Smrg 				  gfc_copy_expr (s1->as->lower[i]));
1500627f7eb2Smrg 	    shape2 = gfc_subtract (gfc_copy_expr (s2->as->upper[i]),
1501627f7eb2Smrg 				  gfc_copy_expr (s2->as->lower[i]));
1502627f7eb2Smrg 	    compval = gfc_dep_compare_expr (shape1, shape2);
1503627f7eb2Smrg 	    gfc_free_expr (shape1);
1504627f7eb2Smrg 	    gfc_free_expr (shape2);
1505627f7eb2Smrg 	    switch (compval)
1506627f7eb2Smrg 	    {
1507627f7eb2Smrg 	      case -1:
1508627f7eb2Smrg 	      case  1:
1509627f7eb2Smrg 	      case -3:
1510627f7eb2Smrg 		if (i < s1->as->rank)
1511627f7eb2Smrg 		  snprintf (errmsg, err_len, "Shape mismatch in dimension %i of"
1512627f7eb2Smrg 			    " argument '%s'", i + 1, s1->name);
1513627f7eb2Smrg 		else
1514627f7eb2Smrg 		  snprintf (errmsg, err_len, "Shape mismatch in codimension %i "
1515627f7eb2Smrg 			    "of argument '%s'", i - s1->as->rank + 1, s1->name);
1516627f7eb2Smrg 		return false;
1517627f7eb2Smrg 
1518627f7eb2Smrg 	      case -2:
1519627f7eb2Smrg 		/* FIXME: Implement a warning for this case.
1520627f7eb2Smrg 		gfc_warning (0, "Possible shape mismatch in argument %qs",
1521627f7eb2Smrg 			    s1->name);*/
1522627f7eb2Smrg 		break;
1523627f7eb2Smrg 
1524627f7eb2Smrg 	      case 0:
1525627f7eb2Smrg 		break;
1526627f7eb2Smrg 
1527627f7eb2Smrg 	      default:
1528627f7eb2Smrg 		gfc_internal_error ("check_dummy_characteristics: Unexpected "
1529627f7eb2Smrg 				    "result %i of gfc_dep_compare_expr",
1530627f7eb2Smrg 				    compval);
1531627f7eb2Smrg 		break;
1532627f7eb2Smrg 	    }
1533627f7eb2Smrg 	  }
1534627f7eb2Smrg     }
1535627f7eb2Smrg 
1536627f7eb2Smrg   return true;
1537627f7eb2Smrg }
1538627f7eb2Smrg 
1539627f7eb2Smrg 
1540627f7eb2Smrg /* Check if the characteristics of two function results match,
1541627f7eb2Smrg    cf. F08:12.3.3.  */
1542627f7eb2Smrg 
1543627f7eb2Smrg bool
gfc_check_result_characteristics(gfc_symbol * s1,gfc_symbol * s2,char * errmsg,int err_len)1544627f7eb2Smrg gfc_check_result_characteristics (gfc_symbol *s1, gfc_symbol *s2,
1545627f7eb2Smrg 				  char *errmsg, int err_len)
1546627f7eb2Smrg {
1547627f7eb2Smrg   gfc_symbol *r1, *r2;
1548627f7eb2Smrg 
1549627f7eb2Smrg   if (s1->ts.interface && s1->ts.interface->result)
1550627f7eb2Smrg     r1 = s1->ts.interface->result;
1551627f7eb2Smrg   else
1552627f7eb2Smrg     r1 = s1->result ? s1->result : s1;
1553627f7eb2Smrg 
1554627f7eb2Smrg   if (s2->ts.interface && s2->ts.interface->result)
1555627f7eb2Smrg     r2 = s2->ts.interface->result;
1556627f7eb2Smrg   else
1557627f7eb2Smrg     r2 = s2->result ? s2->result : s2;
1558627f7eb2Smrg 
1559627f7eb2Smrg   if (r1->ts.type == BT_UNKNOWN)
1560627f7eb2Smrg     return true;
1561627f7eb2Smrg 
1562627f7eb2Smrg   /* Check type and rank.  */
1563627f7eb2Smrg   if (!compare_type_characteristics (r1, r2))
1564627f7eb2Smrg     {
1565627f7eb2Smrg       snprintf (errmsg, err_len, "Type mismatch in function result (%s/%s)",
1566627f7eb2Smrg 		gfc_typename (&r1->ts), gfc_typename (&r2->ts));
1567627f7eb2Smrg       return false;
1568627f7eb2Smrg     }
1569627f7eb2Smrg   if (!compare_rank (r1, r2))
1570627f7eb2Smrg     {
1571627f7eb2Smrg       snprintf (errmsg, err_len, "Rank mismatch in function result (%i/%i)",
1572627f7eb2Smrg 		symbol_rank (r1), symbol_rank (r2));
1573627f7eb2Smrg       return false;
1574627f7eb2Smrg     }
1575627f7eb2Smrg 
1576627f7eb2Smrg   /* Check ALLOCATABLE attribute.  */
1577627f7eb2Smrg   if (r1->attr.allocatable != r2->attr.allocatable)
1578627f7eb2Smrg     {
1579627f7eb2Smrg       snprintf (errmsg, err_len, "ALLOCATABLE attribute mismatch in "
1580627f7eb2Smrg 		"function result");
1581627f7eb2Smrg       return false;
1582627f7eb2Smrg     }
1583627f7eb2Smrg 
1584627f7eb2Smrg   /* Check POINTER attribute.  */
1585627f7eb2Smrg   if (r1->attr.pointer != r2->attr.pointer)
1586627f7eb2Smrg     {
1587627f7eb2Smrg       snprintf (errmsg, err_len, "POINTER attribute mismatch in "
1588627f7eb2Smrg 		"function result");
1589627f7eb2Smrg       return false;
1590627f7eb2Smrg     }
1591627f7eb2Smrg 
1592627f7eb2Smrg   /* Check CONTIGUOUS attribute.  */
1593627f7eb2Smrg   if (r1->attr.contiguous != r2->attr.contiguous)
1594627f7eb2Smrg     {
1595627f7eb2Smrg       snprintf (errmsg, err_len, "CONTIGUOUS attribute mismatch in "
1596627f7eb2Smrg 		"function result");
1597627f7eb2Smrg       return false;
1598627f7eb2Smrg     }
1599627f7eb2Smrg 
1600627f7eb2Smrg   /* Check PROCEDURE POINTER attribute.  */
1601627f7eb2Smrg   if (r1 != s1 && r1->attr.proc_pointer != r2->attr.proc_pointer)
1602627f7eb2Smrg     {
1603627f7eb2Smrg       snprintf (errmsg, err_len, "PROCEDURE POINTER mismatch in "
1604627f7eb2Smrg 		"function result");
1605627f7eb2Smrg       return false;
1606627f7eb2Smrg     }
1607627f7eb2Smrg 
1608627f7eb2Smrg   /* Check string length.  */
1609627f7eb2Smrg   if (r1->ts.type == BT_CHARACTER && r1->ts.u.cl && r2->ts.u.cl)
1610627f7eb2Smrg     {
1611627f7eb2Smrg       if (r1->ts.deferred != r2->ts.deferred)
1612627f7eb2Smrg 	{
1613627f7eb2Smrg 	  snprintf (errmsg, err_len, "Character length mismatch "
1614627f7eb2Smrg 		    "in function result");
1615627f7eb2Smrg 	  return false;
1616627f7eb2Smrg 	}
1617627f7eb2Smrg 
1618627f7eb2Smrg       if (r1->ts.u.cl->length && r2->ts.u.cl->length)
1619627f7eb2Smrg 	{
1620627f7eb2Smrg 	  int compval = gfc_dep_compare_expr (r1->ts.u.cl->length,
1621627f7eb2Smrg 					      r2->ts.u.cl->length);
1622627f7eb2Smrg 	  switch (compval)
1623627f7eb2Smrg 	  {
1624627f7eb2Smrg 	    case -1:
1625627f7eb2Smrg 	    case  1:
1626627f7eb2Smrg 	    case -3:
1627627f7eb2Smrg 	      snprintf (errmsg, err_len, "Character length mismatch "
1628627f7eb2Smrg 			"in function result");
1629627f7eb2Smrg 	      return false;
1630627f7eb2Smrg 
1631627f7eb2Smrg 	    case -2:
1632627f7eb2Smrg 	      /* FIXME: Implement a warning for this case.
1633627f7eb2Smrg 	      snprintf (errmsg, err_len, "Possible character length mismatch "
1634627f7eb2Smrg 			"in function result");*/
1635627f7eb2Smrg 	      break;
1636627f7eb2Smrg 
1637627f7eb2Smrg 	    case 0:
1638627f7eb2Smrg 	      break;
1639627f7eb2Smrg 
1640627f7eb2Smrg 	    default:
1641627f7eb2Smrg 	      gfc_internal_error ("check_result_characteristics (1): Unexpected "
1642627f7eb2Smrg 				  "result %i of gfc_dep_compare_expr", compval);
1643627f7eb2Smrg 	      break;
1644627f7eb2Smrg 	  }
1645627f7eb2Smrg 	}
1646627f7eb2Smrg     }
1647627f7eb2Smrg 
1648627f7eb2Smrg   /* Check array shape.  */
1649627f7eb2Smrg   if (!r1->attr.allocatable && !r1->attr.pointer && r1->as && r2->as)
1650627f7eb2Smrg     {
1651627f7eb2Smrg       int i, compval;
1652627f7eb2Smrg       gfc_expr *shape1, *shape2;
1653627f7eb2Smrg 
1654627f7eb2Smrg       if (r1->as->type != r2->as->type)
1655627f7eb2Smrg 	{
1656627f7eb2Smrg 	  snprintf (errmsg, err_len, "Shape mismatch in function result");
1657627f7eb2Smrg 	  return false;
1658627f7eb2Smrg 	}
1659627f7eb2Smrg 
1660627f7eb2Smrg       if (r1->as->type == AS_EXPLICIT)
1661627f7eb2Smrg 	for (i = 0; i < r1->as->rank + r1->as->corank; i++)
1662627f7eb2Smrg 	  {
1663627f7eb2Smrg 	    shape1 = gfc_subtract (gfc_copy_expr (r1->as->upper[i]),
1664627f7eb2Smrg 				   gfc_copy_expr (r1->as->lower[i]));
1665627f7eb2Smrg 	    shape2 = gfc_subtract (gfc_copy_expr (r2->as->upper[i]),
1666627f7eb2Smrg 				   gfc_copy_expr (r2->as->lower[i]));
1667627f7eb2Smrg 	    compval = gfc_dep_compare_expr (shape1, shape2);
1668627f7eb2Smrg 	    gfc_free_expr (shape1);
1669627f7eb2Smrg 	    gfc_free_expr (shape2);
1670627f7eb2Smrg 	    switch (compval)
1671627f7eb2Smrg 	    {
1672627f7eb2Smrg 	      case -1:
1673627f7eb2Smrg 	      case  1:
1674627f7eb2Smrg 	      case -3:
1675627f7eb2Smrg 		snprintf (errmsg, err_len, "Shape mismatch in dimension %i of "
1676627f7eb2Smrg 			  "function result", i + 1);
1677627f7eb2Smrg 		return false;
1678627f7eb2Smrg 
1679627f7eb2Smrg 	      case -2:
1680627f7eb2Smrg 		/* FIXME: Implement a warning for this case.
1681627f7eb2Smrg 		gfc_warning (0, "Possible shape mismatch in return value");*/
1682627f7eb2Smrg 		break;
1683627f7eb2Smrg 
1684627f7eb2Smrg 	      case 0:
1685627f7eb2Smrg 		break;
1686627f7eb2Smrg 
1687627f7eb2Smrg 	      default:
1688627f7eb2Smrg 		gfc_internal_error ("check_result_characteristics (2): "
1689627f7eb2Smrg 				    "Unexpected result %i of "
1690627f7eb2Smrg 				    "gfc_dep_compare_expr", compval);
1691627f7eb2Smrg 		break;
1692627f7eb2Smrg 	    }
1693627f7eb2Smrg 	  }
1694627f7eb2Smrg     }
1695627f7eb2Smrg 
1696627f7eb2Smrg   return true;
1697627f7eb2Smrg }
1698627f7eb2Smrg 
1699627f7eb2Smrg 
1700627f7eb2Smrg /* 'Compare' two formal interfaces associated with a pair of symbols.
1701627f7eb2Smrg    We return true if there exists an actual argument list that
1702627f7eb2Smrg    would be ambiguous between the two interfaces, zero otherwise.
1703627f7eb2Smrg    'strict_flag' specifies whether all the characteristics are
1704627f7eb2Smrg    required to match, which is not the case for ambiguity checks.
1705627f7eb2Smrg    'p1' and 'p2' are the PASS arguments of both procedures (if applicable).  */
1706627f7eb2Smrg 
1707627f7eb2Smrg bool
gfc_compare_interfaces(gfc_symbol * s1,gfc_symbol * s2,const char * name2,int generic_flag,int strict_flag,char * errmsg,int err_len,const char * p1,const char * p2,bool * bad_result_characteristics)1708627f7eb2Smrg gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, const char *name2,
1709627f7eb2Smrg 			int generic_flag, int strict_flag,
1710627f7eb2Smrg 			char *errmsg, int err_len,
17114c3eb207Smrg 			const char *p1, const char *p2,
17124c3eb207Smrg 			bool *bad_result_characteristics)
1713627f7eb2Smrg {
1714627f7eb2Smrg   gfc_formal_arglist *f1, *f2;
1715627f7eb2Smrg 
1716627f7eb2Smrg   gcc_assert (name2 != NULL);
1717627f7eb2Smrg 
17184c3eb207Smrg   if (bad_result_characteristics)
17194c3eb207Smrg     *bad_result_characteristics = false;
17204c3eb207Smrg 
1721627f7eb2Smrg   if (s1->attr.function && (s2->attr.subroutine
1722627f7eb2Smrg       || (!s2->attr.function && s2->ts.type == BT_UNKNOWN
1723627f7eb2Smrg 	  && gfc_get_default_type (name2, s2->ns)->type == BT_UNKNOWN)))
1724627f7eb2Smrg     {
1725627f7eb2Smrg       if (errmsg != NULL)
1726627f7eb2Smrg 	snprintf (errmsg, err_len, "'%s' is not a function", name2);
1727627f7eb2Smrg       return false;
1728627f7eb2Smrg     }
1729627f7eb2Smrg 
1730627f7eb2Smrg   if (s1->attr.subroutine && s2->attr.function)
1731627f7eb2Smrg     {
1732627f7eb2Smrg       if (errmsg != NULL)
1733627f7eb2Smrg 	snprintf (errmsg, err_len, "'%s' is not a subroutine", name2);
1734627f7eb2Smrg       return false;
1735627f7eb2Smrg     }
1736627f7eb2Smrg 
1737627f7eb2Smrg   /* Do strict checks on all characteristics
1738627f7eb2Smrg      (for dummy procedures and procedure pointer assignments).  */
1739627f7eb2Smrg   if (!generic_flag && strict_flag)
1740627f7eb2Smrg     {
1741627f7eb2Smrg       if (s1->attr.function && s2->attr.function)
1742627f7eb2Smrg 	{
1743627f7eb2Smrg 	  /* If both are functions, check result characteristics.  */
1744627f7eb2Smrg 	  if (!gfc_check_result_characteristics (s1, s2, errmsg, err_len)
1745627f7eb2Smrg 	      || !gfc_check_result_characteristics (s2, s1, errmsg, err_len))
17464c3eb207Smrg 	    {
17474c3eb207Smrg 	      if (bad_result_characteristics)
17484c3eb207Smrg 		*bad_result_characteristics = true;
1749627f7eb2Smrg 	      return false;
1750627f7eb2Smrg 	    }
17514c3eb207Smrg 	}
1752627f7eb2Smrg 
1753627f7eb2Smrg       if (s1->attr.pure && !s2->attr.pure)
1754627f7eb2Smrg 	{
1755627f7eb2Smrg 	  snprintf (errmsg, err_len, "Mismatch in PURE attribute");
1756627f7eb2Smrg 	  return false;
1757627f7eb2Smrg 	}
1758627f7eb2Smrg       if (s1->attr.elemental && !s2->attr.elemental)
1759627f7eb2Smrg 	{
1760627f7eb2Smrg 	  snprintf (errmsg, err_len, "Mismatch in ELEMENTAL attribute");
1761627f7eb2Smrg 	  return false;
1762627f7eb2Smrg 	}
1763627f7eb2Smrg     }
1764627f7eb2Smrg 
1765627f7eb2Smrg   if (s1->attr.if_source == IFSRC_UNKNOWN
1766627f7eb2Smrg       || s2->attr.if_source == IFSRC_UNKNOWN)
1767627f7eb2Smrg     return true;
1768627f7eb2Smrg 
1769627f7eb2Smrg   f1 = gfc_sym_get_dummy_args (s1);
1770627f7eb2Smrg   f2 = gfc_sym_get_dummy_args (s2);
1771627f7eb2Smrg 
1772627f7eb2Smrg   /* Special case: No arguments.  */
1773627f7eb2Smrg   if (f1 == NULL && f2 == NULL)
1774627f7eb2Smrg     return true;
1775627f7eb2Smrg 
1776627f7eb2Smrg   if (generic_flag)
1777627f7eb2Smrg     {
1778627f7eb2Smrg       if (count_types_test (f1, f2, p1, p2)
1779627f7eb2Smrg 	  || count_types_test (f2, f1, p2, p1))
1780627f7eb2Smrg 	return false;
1781627f7eb2Smrg 
1782627f7eb2Smrg       /* Special case: alternate returns.  If both f1->sym and f2->sym are
1783627f7eb2Smrg 	 NULL, then the leading formal arguments are alternate returns.
1784627f7eb2Smrg 	 The previous conditional should catch argument lists with
1785627f7eb2Smrg 	 different number of argument.  */
1786627f7eb2Smrg       if (f1 && f1->sym == NULL && f2 && f2->sym == NULL)
1787627f7eb2Smrg 	return true;
1788627f7eb2Smrg 
1789627f7eb2Smrg       if (generic_correspondence (f1, f2, p1, p2)
1790627f7eb2Smrg 	  || generic_correspondence (f2, f1, p2, p1))
1791627f7eb2Smrg 	return false;
1792627f7eb2Smrg     }
1793627f7eb2Smrg   else
1794627f7eb2Smrg     /* Perform the abbreviated correspondence test for operators (the
1795627f7eb2Smrg        arguments cannot be optional and are always ordered correctly).
1796627f7eb2Smrg        This is also done when comparing interfaces for dummy procedures and in
1797627f7eb2Smrg        procedure pointer assignments.  */
1798627f7eb2Smrg 
1799627f7eb2Smrg     for (; f1 || f2; f1 = f1->next, f2 = f2->next)
1800627f7eb2Smrg       {
1801627f7eb2Smrg 	/* Check existence.  */
1802627f7eb2Smrg 	if (f1 == NULL || f2 == NULL)
1803627f7eb2Smrg 	  {
1804627f7eb2Smrg 	    if (errmsg != NULL)
1805627f7eb2Smrg 	      snprintf (errmsg, err_len, "'%s' has the wrong number of "
1806627f7eb2Smrg 			"arguments", name2);
1807627f7eb2Smrg 	    return false;
1808627f7eb2Smrg 	  }
1809627f7eb2Smrg 
1810627f7eb2Smrg 	if (strict_flag)
1811627f7eb2Smrg 	  {
1812627f7eb2Smrg 	    /* Check all characteristics.  */
1813627f7eb2Smrg 	    if (!gfc_check_dummy_characteristics (f1->sym, f2->sym, true,
1814627f7eb2Smrg 					      errmsg, err_len))
1815627f7eb2Smrg 	      return false;
1816627f7eb2Smrg 	  }
1817627f7eb2Smrg 	else
1818627f7eb2Smrg 	  {
1819627f7eb2Smrg 	    /* Operators: Only check type and rank of arguments.  */
1820627f7eb2Smrg 	    if (!compare_type (f2->sym, f1->sym))
1821627f7eb2Smrg 	      {
1822627f7eb2Smrg 		if (errmsg != NULL)
1823627f7eb2Smrg 		  snprintf (errmsg, err_len, "Type mismatch in argument '%s' "
1824627f7eb2Smrg 			    "(%s/%s)", f1->sym->name,
1825627f7eb2Smrg 			    gfc_typename (&f1->sym->ts),
1826627f7eb2Smrg 			    gfc_typename (&f2->sym->ts));
1827627f7eb2Smrg 		return false;
1828627f7eb2Smrg 	      }
1829627f7eb2Smrg 	    if (!compare_rank (f2->sym, f1->sym))
1830627f7eb2Smrg 	      {
1831627f7eb2Smrg 		if (errmsg != NULL)
18324c3eb207Smrg 		  snprintf (errmsg, err_len, "Rank mismatch in argument "
18334c3eb207Smrg 			    "'%s' (%i/%i)", f1->sym->name,
18344c3eb207Smrg 			    symbol_rank (f1->sym), symbol_rank (f2->sym));
1835627f7eb2Smrg 		return false;
1836627f7eb2Smrg 	      }
1837627f7eb2Smrg 	    if ((gfc_option.allow_std & GFC_STD_F2008)
1838627f7eb2Smrg 		&& (compare_ptr_alloc(f1->sym, f2->sym)
1839627f7eb2Smrg 		    || compare_ptr_alloc(f2->sym, f1->sym)))
1840627f7eb2Smrg 	      {
1841627f7eb2Smrg     		if (errmsg != NULL)
1842627f7eb2Smrg 		  snprintf (errmsg, err_len, "Mismatching POINTER/ALLOCATABLE "
1843627f7eb2Smrg 			    "attribute in argument '%s' ", f1->sym->name);
1844627f7eb2Smrg 		return false;
1845627f7eb2Smrg 	      }
1846627f7eb2Smrg 	  }
1847627f7eb2Smrg       }
1848627f7eb2Smrg 
1849627f7eb2Smrg   return true;
1850627f7eb2Smrg }
1851627f7eb2Smrg 
1852627f7eb2Smrg 
1853627f7eb2Smrg /* Given a pointer to an interface pointer, remove duplicate
1854627f7eb2Smrg    interfaces and make sure that all symbols are either functions
1855627f7eb2Smrg    or subroutines, and all of the same kind.  Returns true if
1856627f7eb2Smrg    something goes wrong.  */
1857627f7eb2Smrg 
1858627f7eb2Smrg static bool
check_interface0(gfc_interface * p,const char * interface_name)1859627f7eb2Smrg check_interface0 (gfc_interface *p, const char *interface_name)
1860627f7eb2Smrg {
1861627f7eb2Smrg   gfc_interface *psave, *q, *qlast;
1862627f7eb2Smrg 
1863627f7eb2Smrg   psave = p;
1864627f7eb2Smrg   for (; p; p = p->next)
1865627f7eb2Smrg     {
1866627f7eb2Smrg       /* Make sure all symbols in the interface have been defined as
1867627f7eb2Smrg 	 functions or subroutines.  */
1868627f7eb2Smrg       if (((!p->sym->attr.function && !p->sym->attr.subroutine)
1869627f7eb2Smrg 	   || !p->sym->attr.if_source)
1870627f7eb2Smrg 	  && !gfc_fl_struct (p->sym->attr.flavor))
1871627f7eb2Smrg 	{
1872627f7eb2Smrg 	  const char *guessed
1873627f7eb2Smrg 	    = gfc_lookup_function_fuzzy (p->sym->name, p->sym->ns->sym_root);
1874627f7eb2Smrg 
1875627f7eb2Smrg 	  if (p->sym->attr.external)
1876627f7eb2Smrg 	    if (guessed)
1877627f7eb2Smrg 	      gfc_error ("Procedure %qs in %s at %L has no explicit interface"
1878627f7eb2Smrg 			 "; did you mean %qs?",
1879627f7eb2Smrg 			 p->sym->name, interface_name, &p->sym->declared_at,
1880627f7eb2Smrg 			 guessed);
1881627f7eb2Smrg 	    else
1882627f7eb2Smrg 	      gfc_error ("Procedure %qs in %s at %L has no explicit interface",
1883627f7eb2Smrg 			 p->sym->name, interface_name, &p->sym->declared_at);
1884627f7eb2Smrg 	  else
1885627f7eb2Smrg 	    if (guessed)
1886627f7eb2Smrg 	      gfc_error ("Procedure %qs in %s at %L is neither function nor "
1887627f7eb2Smrg 			 "subroutine; did you mean %qs?", p->sym->name,
1888627f7eb2Smrg 			interface_name, &p->sym->declared_at, guessed);
1889627f7eb2Smrg 	    else
1890627f7eb2Smrg 	      gfc_error ("Procedure %qs in %s at %L is neither function nor "
1891627f7eb2Smrg 			 "subroutine", p->sym->name, interface_name,
1892627f7eb2Smrg 			&p->sym->declared_at);
1893627f7eb2Smrg 	  return true;
1894627f7eb2Smrg 	}
1895627f7eb2Smrg 
1896627f7eb2Smrg       /* Verify that procedures are either all SUBROUTINEs or all FUNCTIONs.  */
1897627f7eb2Smrg       if ((psave->sym->attr.function && !p->sym->attr.function
1898627f7eb2Smrg 	   && !gfc_fl_struct (p->sym->attr.flavor))
1899627f7eb2Smrg 	  || (psave->sym->attr.subroutine && !p->sym->attr.subroutine))
1900627f7eb2Smrg 	{
1901627f7eb2Smrg 	  if (!gfc_fl_struct (p->sym->attr.flavor))
1902627f7eb2Smrg 	    gfc_error ("In %s at %L procedures must be either all SUBROUTINEs"
1903627f7eb2Smrg 		       " or all FUNCTIONs", interface_name,
1904627f7eb2Smrg 		       &p->sym->declared_at);
1905627f7eb2Smrg 	  else if (p->sym->attr.flavor == FL_DERIVED)
1906627f7eb2Smrg 	    gfc_error ("In %s at %L procedures must be all FUNCTIONs as the "
1907627f7eb2Smrg 		       "generic name is also the name of a derived type",
1908627f7eb2Smrg 		       interface_name, &p->sym->declared_at);
1909627f7eb2Smrg 	  return true;
1910627f7eb2Smrg 	}
1911627f7eb2Smrg 
1912627f7eb2Smrg       /* F2003, C1207. F2008, C1207.  */
1913627f7eb2Smrg       if (p->sym->attr.proc == PROC_INTERNAL
1914627f7eb2Smrg 	  && !gfc_notify_std (GFC_STD_F2008, "Internal procedure "
1915627f7eb2Smrg 			      "%qs in %s at %L", p->sym->name,
1916627f7eb2Smrg 			      interface_name, &p->sym->declared_at))
1917627f7eb2Smrg 	return true;
1918627f7eb2Smrg     }
1919627f7eb2Smrg   p = psave;
1920627f7eb2Smrg 
1921627f7eb2Smrg   /* Remove duplicate interfaces in this interface list.  */
1922627f7eb2Smrg   for (; p; p = p->next)
1923627f7eb2Smrg     {
1924627f7eb2Smrg       qlast = p;
1925627f7eb2Smrg 
1926627f7eb2Smrg       for (q = p->next; q;)
1927627f7eb2Smrg 	{
1928627f7eb2Smrg 	  if (p->sym != q->sym)
1929627f7eb2Smrg 	    {
1930627f7eb2Smrg 	      qlast = q;
1931627f7eb2Smrg 	      q = q->next;
1932627f7eb2Smrg 	    }
1933627f7eb2Smrg 	  else
1934627f7eb2Smrg 	    {
1935627f7eb2Smrg 	      /* Duplicate interface.  */
1936627f7eb2Smrg 	      qlast->next = q->next;
1937627f7eb2Smrg 	      free (q);
1938627f7eb2Smrg 	      q = qlast->next;
1939627f7eb2Smrg 	    }
1940627f7eb2Smrg 	}
1941627f7eb2Smrg     }
1942627f7eb2Smrg 
1943627f7eb2Smrg   return false;
1944627f7eb2Smrg }
1945627f7eb2Smrg 
1946627f7eb2Smrg 
1947627f7eb2Smrg /* Check lists of interfaces to make sure that no two interfaces are
1948627f7eb2Smrg    ambiguous.  Duplicate interfaces (from the same symbol) are OK here.  */
1949627f7eb2Smrg 
1950627f7eb2Smrg static bool
check_interface1(gfc_interface * p,gfc_interface * q0,int generic_flag,const char * interface_name,bool referenced)1951627f7eb2Smrg check_interface1 (gfc_interface *p, gfc_interface *q0,
1952627f7eb2Smrg 		  int generic_flag, const char *interface_name,
1953627f7eb2Smrg 		  bool referenced)
1954627f7eb2Smrg {
1955627f7eb2Smrg   gfc_interface *q;
1956627f7eb2Smrg   for (; p; p = p->next)
1957627f7eb2Smrg     for (q = q0; q; q = q->next)
1958627f7eb2Smrg       {
1959627f7eb2Smrg 	if (p->sym == q->sym)
1960627f7eb2Smrg 	  continue;		/* Duplicates OK here.  */
1961627f7eb2Smrg 
1962627f7eb2Smrg 	if (p->sym->name == q->sym->name && p->sym->module == q->sym->module)
1963627f7eb2Smrg 	  continue;
1964627f7eb2Smrg 
1965627f7eb2Smrg 	if (!gfc_fl_struct (p->sym->attr.flavor)
1966627f7eb2Smrg 	    && !gfc_fl_struct (q->sym->attr.flavor)
1967627f7eb2Smrg 	    && gfc_compare_interfaces (p->sym, q->sym, q->sym->name,
1968627f7eb2Smrg 				       generic_flag, 0, NULL, 0, NULL, NULL))
1969627f7eb2Smrg 	  {
1970627f7eb2Smrg 	    if (referenced)
1971627f7eb2Smrg 	      gfc_error ("Ambiguous interfaces in %s for %qs at %L "
1972627f7eb2Smrg 			 "and %qs at %L", interface_name,
1973627f7eb2Smrg 			 q->sym->name, &q->sym->declared_at,
1974627f7eb2Smrg 			 p->sym->name, &p->sym->declared_at);
1975627f7eb2Smrg 	    else if (!p->sym->attr.use_assoc && q->sym->attr.use_assoc)
1976627f7eb2Smrg 	      gfc_warning (0, "Ambiguous interfaces in %s for %qs at %L "
1977627f7eb2Smrg 			 "and %qs at %L", interface_name,
1978627f7eb2Smrg 			 q->sym->name, &q->sym->declared_at,
1979627f7eb2Smrg 			 p->sym->name, &p->sym->declared_at);
1980627f7eb2Smrg 	    else
1981627f7eb2Smrg 	      gfc_warning (0, "Although not referenced, %qs has ambiguous "
1982627f7eb2Smrg 			   "interfaces at %L", interface_name, &p->where);
1983627f7eb2Smrg 	    return true;
1984627f7eb2Smrg 	  }
1985627f7eb2Smrg       }
1986627f7eb2Smrg   return false;
1987627f7eb2Smrg }
1988627f7eb2Smrg 
1989627f7eb2Smrg 
1990627f7eb2Smrg /* Check the generic and operator interfaces of symbols to make sure
1991627f7eb2Smrg    that none of the interfaces conflict.  The check has to be done
1992627f7eb2Smrg    after all of the symbols are actually loaded.  */
1993627f7eb2Smrg 
1994627f7eb2Smrg static void
check_sym_interfaces(gfc_symbol * sym)1995627f7eb2Smrg check_sym_interfaces (gfc_symbol *sym)
1996627f7eb2Smrg {
19974c3eb207Smrg   /* Provide sufficient space to hold "generic interface 'symbol.symbol'".  */
19984c3eb207Smrg   char interface_name[2*GFC_MAX_SYMBOL_LEN+2 + sizeof("generic interface ''")];
1999627f7eb2Smrg   gfc_interface *p;
2000627f7eb2Smrg 
2001627f7eb2Smrg   if (sym->ns != gfc_current_ns)
2002627f7eb2Smrg     return;
2003627f7eb2Smrg 
2004627f7eb2Smrg   if (sym->generic != NULL)
2005627f7eb2Smrg     {
20064c3eb207Smrg       size_t len = strlen (sym->name) + sizeof("generic interface ''");
20074c3eb207Smrg       gcc_assert (len < sizeof (interface_name));
2008627f7eb2Smrg       sprintf (interface_name, "generic interface '%s'", sym->name);
2009627f7eb2Smrg       if (check_interface0 (sym->generic, interface_name))
2010627f7eb2Smrg 	return;
2011627f7eb2Smrg 
2012627f7eb2Smrg       for (p = sym->generic; p; p = p->next)
2013627f7eb2Smrg 	{
2014627f7eb2Smrg 	  if (p->sym->attr.mod_proc
2015627f7eb2Smrg 	      && !p->sym->attr.module_procedure
2016627f7eb2Smrg 	      && (p->sym->attr.if_source != IFSRC_DECL
2017627f7eb2Smrg 		  || p->sym->attr.procedure))
2018627f7eb2Smrg 	    {
2019627f7eb2Smrg 	      gfc_error ("%qs at %L is not a module procedure",
2020627f7eb2Smrg 			 p->sym->name, &p->where);
2021627f7eb2Smrg 	      return;
2022627f7eb2Smrg 	    }
2023627f7eb2Smrg 	}
2024627f7eb2Smrg 
2025627f7eb2Smrg       /* Originally, this test was applied to host interfaces too;
2026627f7eb2Smrg 	 this is incorrect since host associated symbols, from any
2027627f7eb2Smrg 	 source, cannot be ambiguous with local symbols.  */
2028627f7eb2Smrg       check_interface1 (sym->generic, sym->generic, 1, interface_name,
2029627f7eb2Smrg 			sym->attr.referenced || !sym->attr.use_assoc);
2030627f7eb2Smrg     }
2031627f7eb2Smrg }
2032627f7eb2Smrg 
2033627f7eb2Smrg 
2034627f7eb2Smrg static void
check_uop_interfaces(gfc_user_op * uop)2035627f7eb2Smrg check_uop_interfaces (gfc_user_op *uop)
2036627f7eb2Smrg {
2037627f7eb2Smrg   char interface_name[GFC_MAX_SYMBOL_LEN + sizeof("operator interface ''")];
2038627f7eb2Smrg   gfc_user_op *uop2;
2039627f7eb2Smrg   gfc_namespace *ns;
2040627f7eb2Smrg 
2041627f7eb2Smrg   sprintf (interface_name, "operator interface '%s'", uop->name);
2042627f7eb2Smrg   if (check_interface0 (uop->op, interface_name))
2043627f7eb2Smrg     return;
2044627f7eb2Smrg 
2045627f7eb2Smrg   for (ns = gfc_current_ns; ns; ns = ns->parent)
2046627f7eb2Smrg     {
2047627f7eb2Smrg       uop2 = gfc_find_uop (uop->name, ns);
2048627f7eb2Smrg       if (uop2 == NULL)
2049627f7eb2Smrg 	continue;
2050627f7eb2Smrg 
2051627f7eb2Smrg       check_interface1 (uop->op, uop2->op, 0,
2052627f7eb2Smrg 			interface_name, true);
2053627f7eb2Smrg     }
2054627f7eb2Smrg }
2055627f7eb2Smrg 
2056627f7eb2Smrg /* Given an intrinsic op, return an equivalent op if one exists,
2057627f7eb2Smrg    or INTRINSIC_NONE otherwise.  */
2058627f7eb2Smrg 
2059627f7eb2Smrg gfc_intrinsic_op
gfc_equivalent_op(gfc_intrinsic_op op)2060627f7eb2Smrg gfc_equivalent_op (gfc_intrinsic_op op)
2061627f7eb2Smrg {
2062627f7eb2Smrg   switch(op)
2063627f7eb2Smrg     {
2064627f7eb2Smrg     case INTRINSIC_EQ:
2065627f7eb2Smrg       return INTRINSIC_EQ_OS;
2066627f7eb2Smrg 
2067627f7eb2Smrg     case INTRINSIC_EQ_OS:
2068627f7eb2Smrg       return INTRINSIC_EQ;
2069627f7eb2Smrg 
2070627f7eb2Smrg     case INTRINSIC_NE:
2071627f7eb2Smrg       return INTRINSIC_NE_OS;
2072627f7eb2Smrg 
2073627f7eb2Smrg     case INTRINSIC_NE_OS:
2074627f7eb2Smrg       return INTRINSIC_NE;
2075627f7eb2Smrg 
2076627f7eb2Smrg     case INTRINSIC_GT:
2077627f7eb2Smrg       return INTRINSIC_GT_OS;
2078627f7eb2Smrg 
2079627f7eb2Smrg     case INTRINSIC_GT_OS:
2080627f7eb2Smrg       return INTRINSIC_GT;
2081627f7eb2Smrg 
2082627f7eb2Smrg     case INTRINSIC_GE:
2083627f7eb2Smrg       return INTRINSIC_GE_OS;
2084627f7eb2Smrg 
2085627f7eb2Smrg     case INTRINSIC_GE_OS:
2086627f7eb2Smrg       return INTRINSIC_GE;
2087627f7eb2Smrg 
2088627f7eb2Smrg     case INTRINSIC_LT:
2089627f7eb2Smrg       return INTRINSIC_LT_OS;
2090627f7eb2Smrg 
2091627f7eb2Smrg     case INTRINSIC_LT_OS:
2092627f7eb2Smrg       return INTRINSIC_LT;
2093627f7eb2Smrg 
2094627f7eb2Smrg     case INTRINSIC_LE:
2095627f7eb2Smrg       return INTRINSIC_LE_OS;
2096627f7eb2Smrg 
2097627f7eb2Smrg     case INTRINSIC_LE_OS:
2098627f7eb2Smrg       return INTRINSIC_LE;
2099627f7eb2Smrg 
2100627f7eb2Smrg     default:
2101627f7eb2Smrg       return INTRINSIC_NONE;
2102627f7eb2Smrg     }
2103627f7eb2Smrg }
2104627f7eb2Smrg 
2105627f7eb2Smrg /* For the namespace, check generic, user operator and intrinsic
2106627f7eb2Smrg    operator interfaces for consistency and to remove duplicate
2107627f7eb2Smrg    interfaces.  We traverse the whole namespace, counting on the fact
2108627f7eb2Smrg    that most symbols will not have generic or operator interfaces.  */
2109627f7eb2Smrg 
2110627f7eb2Smrg void
gfc_check_interfaces(gfc_namespace * ns)2111627f7eb2Smrg gfc_check_interfaces (gfc_namespace *ns)
2112627f7eb2Smrg {
2113627f7eb2Smrg   gfc_namespace *old_ns, *ns2;
2114627f7eb2Smrg   char interface_name[GFC_MAX_SYMBOL_LEN + sizeof("intrinsic '' operator")];
2115627f7eb2Smrg   int i;
2116627f7eb2Smrg 
2117627f7eb2Smrg   old_ns = gfc_current_ns;
2118627f7eb2Smrg   gfc_current_ns = ns;
2119627f7eb2Smrg 
2120627f7eb2Smrg   gfc_traverse_ns (ns, check_sym_interfaces);
2121627f7eb2Smrg 
2122627f7eb2Smrg   gfc_traverse_user_op (ns, check_uop_interfaces);
2123627f7eb2Smrg 
2124627f7eb2Smrg   for (i = GFC_INTRINSIC_BEGIN; i != GFC_INTRINSIC_END; i++)
2125627f7eb2Smrg     {
2126627f7eb2Smrg       if (i == INTRINSIC_USER)
2127627f7eb2Smrg 	continue;
2128627f7eb2Smrg 
2129627f7eb2Smrg       if (i == INTRINSIC_ASSIGN)
2130627f7eb2Smrg 	strcpy (interface_name, "intrinsic assignment operator");
2131627f7eb2Smrg       else
2132627f7eb2Smrg 	sprintf (interface_name, "intrinsic '%s' operator",
2133627f7eb2Smrg 		 gfc_op2string ((gfc_intrinsic_op) i));
2134627f7eb2Smrg 
2135627f7eb2Smrg       if (check_interface0 (ns->op[i], interface_name))
2136627f7eb2Smrg 	continue;
2137627f7eb2Smrg 
2138627f7eb2Smrg       if (ns->op[i])
2139627f7eb2Smrg 	gfc_check_operator_interface (ns->op[i]->sym, (gfc_intrinsic_op) i,
2140627f7eb2Smrg 				      ns->op[i]->where);
2141627f7eb2Smrg 
2142627f7eb2Smrg       for (ns2 = ns; ns2; ns2 = ns2->parent)
2143627f7eb2Smrg 	{
2144627f7eb2Smrg 	  gfc_intrinsic_op other_op;
2145627f7eb2Smrg 
2146627f7eb2Smrg 	  if (check_interface1 (ns->op[i], ns2->op[i], 0,
2147627f7eb2Smrg 				interface_name, true))
2148627f7eb2Smrg 	    goto done;
2149627f7eb2Smrg 
2150627f7eb2Smrg 	  /* i should be gfc_intrinsic_op, but has to be int with this cast
2151627f7eb2Smrg 	     here for stupid C++ compatibility rules.  */
2152627f7eb2Smrg 	  other_op = gfc_equivalent_op ((gfc_intrinsic_op) i);
2153627f7eb2Smrg 	  if (other_op != INTRINSIC_NONE
2154627f7eb2Smrg 	    &&  check_interface1 (ns->op[i], ns2->op[other_op],
2155627f7eb2Smrg 				  0, interface_name, true))
2156627f7eb2Smrg 	    goto done;
2157627f7eb2Smrg 	}
2158627f7eb2Smrg     }
2159627f7eb2Smrg 
2160627f7eb2Smrg done:
2161627f7eb2Smrg   gfc_current_ns = old_ns;
2162627f7eb2Smrg }
2163627f7eb2Smrg 
2164627f7eb2Smrg 
2165627f7eb2Smrg /* Given a symbol of a formal argument list and an expression, if the
2166627f7eb2Smrg    formal argument is allocatable, check that the actual argument is
2167627f7eb2Smrg    allocatable. Returns true if compatible, zero if not compatible.  */
2168627f7eb2Smrg 
2169627f7eb2Smrg static bool
compare_allocatable(gfc_symbol * formal,gfc_expr * actual)2170627f7eb2Smrg compare_allocatable (gfc_symbol *formal, gfc_expr *actual)
2171627f7eb2Smrg {
2172627f7eb2Smrg   if (formal->attr.allocatable
2173627f7eb2Smrg       || (formal->ts.type == BT_CLASS && CLASS_DATA (formal)->attr.allocatable))
2174627f7eb2Smrg     {
2175627f7eb2Smrg       symbol_attribute attr = gfc_expr_attr (actual);
2176627f7eb2Smrg       if (actual->ts.type == BT_CLASS && !attr.class_ok)
2177627f7eb2Smrg 	return true;
2178627f7eb2Smrg       else if (!attr.allocatable)
2179627f7eb2Smrg 	return false;
2180627f7eb2Smrg     }
2181627f7eb2Smrg 
2182627f7eb2Smrg   return true;
2183627f7eb2Smrg }
2184627f7eb2Smrg 
2185627f7eb2Smrg 
2186627f7eb2Smrg /* Given a symbol of a formal argument list and an expression, if the
2187627f7eb2Smrg    formal argument is a pointer, see if the actual argument is a
2188627f7eb2Smrg    pointer. Returns nonzero if compatible, zero if not compatible.  */
2189627f7eb2Smrg 
2190627f7eb2Smrg static int
compare_pointer(gfc_symbol * formal,gfc_expr * actual)2191627f7eb2Smrg compare_pointer (gfc_symbol *formal, gfc_expr *actual)
2192627f7eb2Smrg {
2193627f7eb2Smrg   symbol_attribute attr;
2194627f7eb2Smrg 
2195627f7eb2Smrg   if (formal->attr.pointer
2196627f7eb2Smrg       || (formal->ts.type == BT_CLASS && CLASS_DATA (formal)
2197627f7eb2Smrg 	  && CLASS_DATA (formal)->attr.class_pointer))
2198627f7eb2Smrg     {
2199627f7eb2Smrg       attr = gfc_expr_attr (actual);
2200627f7eb2Smrg 
2201627f7eb2Smrg       /* Fortran 2008 allows non-pointer actual arguments.  */
2202627f7eb2Smrg       if (!attr.pointer && attr.target && formal->attr.intent == INTENT_IN)
2203627f7eb2Smrg 	return 2;
2204627f7eb2Smrg 
2205627f7eb2Smrg       if (!attr.pointer)
2206627f7eb2Smrg 	return 0;
2207627f7eb2Smrg     }
2208627f7eb2Smrg 
2209627f7eb2Smrg   return 1;
2210627f7eb2Smrg }
2211627f7eb2Smrg 
2212627f7eb2Smrg 
2213627f7eb2Smrg /* Emit clear error messages for rank mismatch.  */
2214627f7eb2Smrg 
2215627f7eb2Smrg static void
argument_rank_mismatch(const char * name,locus * where,int rank1,int rank2,locus * where_formal)2216627f7eb2Smrg argument_rank_mismatch (const char *name, locus *where,
22174c3eb207Smrg 			int rank1, int rank2, locus *where_formal)
2218627f7eb2Smrg {
2219627f7eb2Smrg 
2220627f7eb2Smrg   /* TS 29113, C407b.  */
22214c3eb207Smrg   if (where_formal == NULL)
22224c3eb207Smrg     {
2223627f7eb2Smrg       if (rank2 == -1)
22244c3eb207Smrg 	gfc_error ("The assumed-rank array at %L requires that the dummy "
22254c3eb207Smrg 		   "argument %qs has assumed-rank", where, name);
2226627f7eb2Smrg       else if (rank1 == 0)
22274c3eb207Smrg 	gfc_error_opt (0, "Rank mismatch in argument %qs "
2228627f7eb2Smrg 		       "at %L (scalar and rank-%d)", name, where, rank2);
2229627f7eb2Smrg       else if (rank2 == 0)
22304c3eb207Smrg 	gfc_error_opt (0, "Rank mismatch in argument %qs "
2231627f7eb2Smrg 		       "at %L (rank-%d and scalar)", name, where, rank1);
2232627f7eb2Smrg       else
22334c3eb207Smrg 	gfc_error_opt (0, "Rank mismatch in argument %qs "
22344c3eb207Smrg 		       "at %L (rank-%d and rank-%d)", name, where, rank1,
22354c3eb207Smrg 		       rank2);
22364c3eb207Smrg     }
22374c3eb207Smrg   else
22384c3eb207Smrg     {
22394c3eb207Smrg       gcc_assert (rank2 != -1);
22404c3eb207Smrg       if (rank1 == 0)
22414c3eb207Smrg 	gfc_error_opt (0, "Rank mismatch between actual argument at %L "
22424c3eb207Smrg 		       "and actual argument at %L (scalar and rank-%d)",
22434c3eb207Smrg 		       where, where_formal, rank2);
22444c3eb207Smrg       else if (rank2 == 0)
22454c3eb207Smrg 	gfc_error_opt (0, "Rank mismatch between actual argument at %L "
22464c3eb207Smrg 		       "and actual argument at %L (rank-%d and scalar)",
22474c3eb207Smrg 		       where, where_formal, rank1);
22484c3eb207Smrg       else
22494c3eb207Smrg 	gfc_error_opt (0, "Rank mismatch between actual argument at %L "
22504c3eb207Smrg 		       "and actual argument at %L (rank-%d and rank-%d)", where,
22514c3eb207Smrg 		       where_formal, rank1, rank2);
22524c3eb207Smrg     }
2253627f7eb2Smrg }
2254627f7eb2Smrg 
2255627f7eb2Smrg 
22564c3eb207Smrg /* Under certain conditions, a scalar actual argument can be passed
22574c3eb207Smrg    to an array dummy argument - see F2018, 15.5.2.4, paragraph 14.
22584c3eb207Smrg    This function returns true for these conditions so that an error
22594c3eb207Smrg    or warning for this can be suppressed later.  Always return false
22604c3eb207Smrg    for expressions with rank > 0.  */
22614c3eb207Smrg 
22624c3eb207Smrg bool
maybe_dummy_array_arg(gfc_expr * e)22634c3eb207Smrg maybe_dummy_array_arg (gfc_expr *e)
22644c3eb207Smrg {
22654c3eb207Smrg   gfc_symbol *s;
22664c3eb207Smrg   gfc_ref *ref;
22674c3eb207Smrg   bool array_pointer = false;
22684c3eb207Smrg   bool assumed_shape = false;
22694c3eb207Smrg   bool scalar_ref = true;
22704c3eb207Smrg 
22714c3eb207Smrg   if (e->rank > 0)
22724c3eb207Smrg     return false;
22734c3eb207Smrg 
22744c3eb207Smrg   if (e->ts.type == BT_CHARACTER && e->ts.kind == 1)
22754c3eb207Smrg     return true;
22764c3eb207Smrg 
22774c3eb207Smrg   /* If this comes from a constructor, it has been an array element
22784c3eb207Smrg      originally.  */
22794c3eb207Smrg 
22804c3eb207Smrg   if (e->expr_type == EXPR_CONSTANT)
22814c3eb207Smrg     return e->from_constructor;
22824c3eb207Smrg 
22834c3eb207Smrg   if (e->expr_type != EXPR_VARIABLE)
22844c3eb207Smrg     return false;
22854c3eb207Smrg 
22864c3eb207Smrg   s = e->symtree->n.sym;
22874c3eb207Smrg 
22884c3eb207Smrg   if (s->attr.dimension)
22894c3eb207Smrg     {
22904c3eb207Smrg       scalar_ref = false;
22914c3eb207Smrg       array_pointer = s->attr.pointer;
22924c3eb207Smrg     }
22934c3eb207Smrg 
22944c3eb207Smrg   if (s->as && s->as->type == AS_ASSUMED_SHAPE)
22954c3eb207Smrg     assumed_shape = true;
22964c3eb207Smrg 
22974c3eb207Smrg   for (ref=e->ref; ref; ref=ref->next)
22984c3eb207Smrg     {
22994c3eb207Smrg       if (ref->type == REF_COMPONENT)
23004c3eb207Smrg 	{
23014c3eb207Smrg 	  symbol_attribute *attr;
23024c3eb207Smrg 	  attr = &ref->u.c.component->attr;
23034c3eb207Smrg 	  if (attr->dimension)
23044c3eb207Smrg 	    {
23054c3eb207Smrg 	      array_pointer = attr->pointer;
23064c3eb207Smrg 	      assumed_shape = false;
23074c3eb207Smrg 	      scalar_ref = false;
23084c3eb207Smrg 	    }
23094c3eb207Smrg 	  else
23104c3eb207Smrg 	    scalar_ref = true;
23114c3eb207Smrg 	}
23124c3eb207Smrg     }
23134c3eb207Smrg 
23144c3eb207Smrg   return !(scalar_ref || array_pointer || assumed_shape);
23154c3eb207Smrg }
23164c3eb207Smrg 
2317627f7eb2Smrg /* Given a symbol of a formal argument list and an expression, see if
2318627f7eb2Smrg    the two are compatible as arguments.  Returns true if
2319627f7eb2Smrg    compatible, false if not compatible.  */
2320627f7eb2Smrg 
2321627f7eb2Smrg static bool
compare_parameter(gfc_symbol * formal,gfc_expr * actual,int ranks_must_agree,int is_elemental,locus * where)2322627f7eb2Smrg compare_parameter (gfc_symbol *formal, gfc_expr *actual,
2323627f7eb2Smrg 		   int ranks_must_agree, int is_elemental, locus *where)
2324627f7eb2Smrg {
2325627f7eb2Smrg   gfc_ref *ref;
2326627f7eb2Smrg   bool rank_check, is_pointer;
2327627f7eb2Smrg   char err[200];
2328627f7eb2Smrg   gfc_component *ppc;
23294c3eb207Smrg   bool codimension = false;
2330627f7eb2Smrg 
2331627f7eb2Smrg   /* If the formal arg has type BT_VOID, it's to one of the iso_c_binding
2332627f7eb2Smrg      procs c_f_pointer or c_f_procpointer, and we need to accept most
2333627f7eb2Smrg      pointers the user could give us.  This should allow that.  */
2334627f7eb2Smrg   if (formal->ts.type == BT_VOID)
2335627f7eb2Smrg     return true;
2336627f7eb2Smrg 
2337627f7eb2Smrg   if (formal->ts.type == BT_DERIVED
2338627f7eb2Smrg       && formal->ts.u.derived && formal->ts.u.derived->ts.is_iso_c
2339627f7eb2Smrg       && actual->ts.type == BT_DERIVED
2340627f7eb2Smrg       && actual->ts.u.derived && actual->ts.u.derived->ts.is_iso_c)
2341627f7eb2Smrg     return true;
2342627f7eb2Smrg 
2343627f7eb2Smrg   if (formal->ts.type == BT_CLASS && actual->ts.type == BT_DERIVED)
2344627f7eb2Smrg     /* Make sure the vtab symbol is present when
2345627f7eb2Smrg        the module variables are generated.  */
2346627f7eb2Smrg     gfc_find_derived_vtab (actual->ts.u.derived);
2347627f7eb2Smrg 
2348627f7eb2Smrg   if (actual->ts.type == BT_PROCEDURE)
2349627f7eb2Smrg     {
2350627f7eb2Smrg       gfc_symbol *act_sym = actual->symtree->n.sym;
2351627f7eb2Smrg 
2352627f7eb2Smrg       if (formal->attr.flavor != FL_PROCEDURE)
2353627f7eb2Smrg 	{
2354627f7eb2Smrg 	  if (where)
2355627f7eb2Smrg 	    gfc_error ("Invalid procedure argument at %L", &actual->where);
2356627f7eb2Smrg 	  return false;
2357627f7eb2Smrg 	}
2358627f7eb2Smrg 
2359627f7eb2Smrg       if (!gfc_compare_interfaces (formal, act_sym, act_sym->name, 0, 1, err,
2360627f7eb2Smrg 				   sizeof(err), NULL, NULL))
2361627f7eb2Smrg 	{
2362627f7eb2Smrg 	  if (where)
23634c3eb207Smrg 	    gfc_error_opt (0, "Interface mismatch in dummy procedure %qs at %L:"
2364627f7eb2Smrg 			   " %s", formal->name, &actual->where, err);
2365627f7eb2Smrg 	  return false;
2366627f7eb2Smrg 	}
2367627f7eb2Smrg 
2368627f7eb2Smrg       if (formal->attr.function && !act_sym->attr.function)
2369627f7eb2Smrg 	{
2370627f7eb2Smrg 	  gfc_add_function (&act_sym->attr, act_sym->name,
2371627f7eb2Smrg 	  &act_sym->declared_at);
2372627f7eb2Smrg 	  if (act_sym->ts.type == BT_UNKNOWN
2373627f7eb2Smrg 	      && !gfc_set_default_type (act_sym, 1, act_sym->ns))
2374627f7eb2Smrg 	    return false;
2375627f7eb2Smrg 	}
2376627f7eb2Smrg       else if (formal->attr.subroutine && !act_sym->attr.subroutine)
2377627f7eb2Smrg 	gfc_add_subroutine (&act_sym->attr, act_sym->name,
2378627f7eb2Smrg 			    &act_sym->declared_at);
2379627f7eb2Smrg 
2380627f7eb2Smrg       return true;
2381627f7eb2Smrg     }
2382627f7eb2Smrg 
2383627f7eb2Smrg   ppc = gfc_get_proc_ptr_comp (actual);
2384627f7eb2Smrg   if (ppc && ppc->ts.interface)
2385627f7eb2Smrg     {
2386627f7eb2Smrg       if (!gfc_compare_interfaces (formal, ppc->ts.interface, ppc->name, 0, 1,
2387627f7eb2Smrg 				   err, sizeof(err), NULL, NULL))
2388627f7eb2Smrg 	{
2389627f7eb2Smrg 	  if (where)
23904c3eb207Smrg 	    gfc_error_opt (0, "Interface mismatch in dummy procedure %qs at %L:"
2391627f7eb2Smrg 			   " %s", formal->name, &actual->where, err);
2392627f7eb2Smrg 	  return false;
2393627f7eb2Smrg 	}
2394627f7eb2Smrg     }
2395627f7eb2Smrg 
2396627f7eb2Smrg   /* F2008, C1241.  */
2397627f7eb2Smrg   if (formal->attr.pointer && formal->attr.contiguous
2398627f7eb2Smrg       && !gfc_is_simply_contiguous (actual, true, false))
2399627f7eb2Smrg     {
2400627f7eb2Smrg       if (where)
2401627f7eb2Smrg 	gfc_error ("Actual argument to contiguous pointer dummy %qs at %L "
2402627f7eb2Smrg 		   "must be simply contiguous", formal->name, &actual->where);
2403627f7eb2Smrg       return false;
2404627f7eb2Smrg     }
2405627f7eb2Smrg 
2406627f7eb2Smrg   symbol_attribute actual_attr = gfc_expr_attr (actual);
2407627f7eb2Smrg   if (actual->ts.type == BT_CLASS && !actual_attr.class_ok)
2408627f7eb2Smrg     return true;
2409627f7eb2Smrg 
2410627f7eb2Smrg   if ((actual->expr_type != EXPR_NULL || actual->ts.type != BT_UNKNOWN)
2411627f7eb2Smrg       && actual->ts.type != BT_HOLLERITH
2412627f7eb2Smrg       && formal->ts.type != BT_ASSUMED
2413627f7eb2Smrg       && !(formal->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
2414627f7eb2Smrg       && !gfc_compare_types (&formal->ts, &actual->ts)
2415627f7eb2Smrg       && !(formal->ts.type == BT_DERIVED && actual->ts.type == BT_CLASS
2416627f7eb2Smrg 	   && gfc_compare_derived_types (formal->ts.u.derived,
2417627f7eb2Smrg 					 CLASS_DATA (actual)->ts.u.derived)))
2418627f7eb2Smrg     {
2419627f7eb2Smrg       if (where)
24204c3eb207Smrg 	{
24214c3eb207Smrg 	  if (formal->attr.artificial)
24224c3eb207Smrg 	    {
24234c3eb207Smrg 	      if (!flag_allow_argument_mismatch || !formal->error)
24244c3eb207Smrg 		gfc_error_opt (0, "Type mismatch between actual argument at %L "
24254c3eb207Smrg 			       "and actual argument at %L (%s/%s).",
24264c3eb207Smrg 			       &actual->where,
24274c3eb207Smrg 			       &formal->declared_at,
24284c3eb207Smrg 			       gfc_typename (actual),
24294c3eb207Smrg 			       gfc_dummy_typename (&formal->ts));
24304c3eb207Smrg 
24314c3eb207Smrg 	      formal->error = 1;
24324c3eb207Smrg 	    }
24334c3eb207Smrg 	  else
24344c3eb207Smrg 	    gfc_error_opt (0, "Type mismatch in argument %qs at %L; passed %s "
24354c3eb207Smrg 			   "to %s", formal->name, where, gfc_typename (actual),
24364c3eb207Smrg 			   gfc_dummy_typename (&formal->ts));
24374c3eb207Smrg 	}
2438627f7eb2Smrg       return false;
2439627f7eb2Smrg     }
2440627f7eb2Smrg 
2441627f7eb2Smrg   if (actual->ts.type == BT_ASSUMED && formal->ts.type != BT_ASSUMED)
2442627f7eb2Smrg     {
2443627f7eb2Smrg       if (where)
2444627f7eb2Smrg 	gfc_error ("Assumed-type actual argument at %L requires that dummy "
2445627f7eb2Smrg 		   "argument %qs is of assumed type", &actual->where,
2446627f7eb2Smrg 		   formal->name);
2447627f7eb2Smrg       return false;
2448627f7eb2Smrg     }
2449627f7eb2Smrg 
2450627f7eb2Smrg   /* F2008, 12.5.2.5; IR F08/0073.  */
2451627f7eb2Smrg   if (formal->ts.type == BT_CLASS && formal->attr.class_ok
2452627f7eb2Smrg       && actual->expr_type != EXPR_NULL
2453627f7eb2Smrg       && ((CLASS_DATA (formal)->attr.class_pointer
2454627f7eb2Smrg 	   && formal->attr.intent != INTENT_IN)
2455627f7eb2Smrg           || CLASS_DATA (formal)->attr.allocatable))
2456627f7eb2Smrg     {
2457627f7eb2Smrg       if (actual->ts.type != BT_CLASS)
2458627f7eb2Smrg 	{
2459627f7eb2Smrg 	  if (where)
2460627f7eb2Smrg 	    gfc_error ("Actual argument to %qs at %L must be polymorphic",
2461627f7eb2Smrg 			formal->name, &actual->where);
2462627f7eb2Smrg 	  return false;
2463627f7eb2Smrg 	}
2464627f7eb2Smrg 
2465627f7eb2Smrg       if ((!UNLIMITED_POLY (formal) || !UNLIMITED_POLY(actual))
2466627f7eb2Smrg 	  && !gfc_compare_derived_types (CLASS_DATA (actual)->ts.u.derived,
2467627f7eb2Smrg 					 CLASS_DATA (formal)->ts.u.derived))
2468627f7eb2Smrg 	{
2469627f7eb2Smrg 	  if (where)
2470627f7eb2Smrg 	    gfc_error ("Actual argument to %qs at %L must have the same "
2471627f7eb2Smrg 		       "declared type", formal->name, &actual->where);
2472627f7eb2Smrg 	  return false;
2473627f7eb2Smrg 	}
2474627f7eb2Smrg     }
2475627f7eb2Smrg 
2476627f7eb2Smrg   /* F08: 12.5.2.5 Allocatable and pointer dummy variables.  However, this
2477627f7eb2Smrg      is necessary also for F03, so retain error for both.
2478627f7eb2Smrg      NOTE: Other type/kind errors pre-empt this error.  Since they are F03
2479627f7eb2Smrg      compatible, no attempt has been made to channel to this one.  */
2480627f7eb2Smrg   if (UNLIMITED_POLY (formal) && !UNLIMITED_POLY (actual)
2481627f7eb2Smrg       && (CLASS_DATA (formal)->attr.allocatable
2482627f7eb2Smrg 	  ||CLASS_DATA (formal)->attr.class_pointer))
2483627f7eb2Smrg     {
2484627f7eb2Smrg       if (where)
2485627f7eb2Smrg 	gfc_error ("Actual argument to %qs at %L must be unlimited "
2486627f7eb2Smrg 		   "polymorphic since the formal argument is a "
2487627f7eb2Smrg 		   "pointer or allocatable unlimited polymorphic "
2488627f7eb2Smrg 		   "entity [F2008: 12.5.2.5]", formal->name,
2489627f7eb2Smrg 		   &actual->where);
2490627f7eb2Smrg       return false;
2491627f7eb2Smrg     }
2492627f7eb2Smrg 
24934c3eb207Smrg   if (formal->ts.type == BT_CLASS && formal->attr.class_ok)
24944c3eb207Smrg     codimension = CLASS_DATA (formal)->attr.codimension;
24954c3eb207Smrg   else
24964c3eb207Smrg     codimension = formal->attr.codimension;
24974c3eb207Smrg 
24984c3eb207Smrg   if (codimension && !gfc_is_coarray (actual))
2499627f7eb2Smrg     {
2500627f7eb2Smrg       if (where)
2501627f7eb2Smrg 	gfc_error ("Actual argument to %qs at %L must be a coarray",
2502627f7eb2Smrg 		       formal->name, &actual->where);
2503627f7eb2Smrg       return false;
2504627f7eb2Smrg     }
2505627f7eb2Smrg 
25064c3eb207Smrg   if (codimension && formal->attr.allocatable)
2507627f7eb2Smrg     {
2508627f7eb2Smrg       gfc_ref *last = NULL;
2509627f7eb2Smrg 
2510627f7eb2Smrg       for (ref = actual->ref; ref; ref = ref->next)
2511627f7eb2Smrg 	if (ref->type == REF_COMPONENT)
2512627f7eb2Smrg 	  last = ref;
2513627f7eb2Smrg 
2514627f7eb2Smrg       /* F2008, 12.5.2.6.  */
2515627f7eb2Smrg       if ((last && last->u.c.component->as->corank != formal->as->corank)
2516627f7eb2Smrg 	  || (!last
2517627f7eb2Smrg 	      && actual->symtree->n.sym->as->corank != formal->as->corank))
2518627f7eb2Smrg 	{
2519627f7eb2Smrg 	  if (where)
2520627f7eb2Smrg 	    gfc_error ("Corank mismatch in argument %qs at %L (%d and %d)",
2521627f7eb2Smrg 		   formal->name, &actual->where, formal->as->corank,
2522627f7eb2Smrg 		   last ? last->u.c.component->as->corank
2523627f7eb2Smrg 			: actual->symtree->n.sym->as->corank);
2524627f7eb2Smrg 	  return false;
2525627f7eb2Smrg 	}
2526627f7eb2Smrg     }
2527627f7eb2Smrg 
25284c3eb207Smrg   if (codimension)
2529627f7eb2Smrg     {
2530627f7eb2Smrg       /* F2008, 12.5.2.8 + Corrig 2 (IR F08/0048).  */
2531627f7eb2Smrg       /* F2018, 12.5.2.8.  */
2532627f7eb2Smrg       if (formal->attr.dimension
2533627f7eb2Smrg 	  && (formal->attr.contiguous || formal->as->type != AS_ASSUMED_SHAPE)
2534627f7eb2Smrg 	  && actual_attr.dimension
2535627f7eb2Smrg 	  && !gfc_is_simply_contiguous (actual, true, true))
2536627f7eb2Smrg 	{
2537627f7eb2Smrg 	  if (where)
2538627f7eb2Smrg 	    gfc_error ("Actual argument to %qs at %L must be simply "
2539627f7eb2Smrg 		       "contiguous or an element of such an array",
2540627f7eb2Smrg 		       formal->name, &actual->where);
2541627f7eb2Smrg 	  return false;
2542627f7eb2Smrg 	}
2543627f7eb2Smrg 
2544627f7eb2Smrg       /* F2008, C1303 and C1304.  */
2545627f7eb2Smrg       if (formal->attr.intent != INTENT_INOUT
2546627f7eb2Smrg 	  && (((formal->ts.type == BT_DERIVED || formal->ts.type == BT_CLASS)
2547627f7eb2Smrg 	       && formal->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
2548627f7eb2Smrg 	       && formal->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
2549627f7eb2Smrg 	      || formal->attr.lock_comp))
2550627f7eb2Smrg 
2551627f7eb2Smrg     	{
2552627f7eb2Smrg 	  if (where)
2553627f7eb2Smrg 	    gfc_error ("Actual argument to non-INTENT(INOUT) dummy %qs at %L, "
2554627f7eb2Smrg 		       "which is LOCK_TYPE or has a LOCK_TYPE component",
2555627f7eb2Smrg 		       formal->name, &actual->where);
2556627f7eb2Smrg 	  return false;
2557627f7eb2Smrg 	}
2558627f7eb2Smrg 
2559627f7eb2Smrg       /* TS18508, C702/C703.  */
2560627f7eb2Smrg       if (formal->attr.intent != INTENT_INOUT
2561627f7eb2Smrg 	  && (((formal->ts.type == BT_DERIVED || formal->ts.type == BT_CLASS)
2562627f7eb2Smrg 	       && formal->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
2563627f7eb2Smrg 	       && formal->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE)
2564627f7eb2Smrg 	      || formal->attr.event_comp))
2565627f7eb2Smrg 
2566627f7eb2Smrg     	{
2567627f7eb2Smrg 	  if (where)
2568627f7eb2Smrg 	    gfc_error ("Actual argument to non-INTENT(INOUT) dummy %qs at %L, "
2569627f7eb2Smrg 		       "which is EVENT_TYPE or has a EVENT_TYPE component",
2570627f7eb2Smrg 		       formal->name, &actual->where);
2571627f7eb2Smrg 	  return false;
2572627f7eb2Smrg 	}
2573627f7eb2Smrg     }
2574627f7eb2Smrg 
2575627f7eb2Smrg   /* F2008, C1239/C1240.  */
2576627f7eb2Smrg   if (actual->expr_type == EXPR_VARIABLE
2577627f7eb2Smrg       && (actual->symtree->n.sym->attr.asynchronous
2578627f7eb2Smrg          || actual->symtree->n.sym->attr.volatile_)
2579627f7eb2Smrg       &&  (formal->attr.asynchronous || formal->attr.volatile_)
2580627f7eb2Smrg       && actual->rank && formal->as
2581627f7eb2Smrg       && !gfc_is_simply_contiguous (actual, true, false)
2582627f7eb2Smrg       && ((formal->as->type != AS_ASSUMED_SHAPE
2583627f7eb2Smrg 	   && formal->as->type != AS_ASSUMED_RANK && !formal->attr.pointer)
2584627f7eb2Smrg 	  || formal->attr.contiguous))
2585627f7eb2Smrg     {
2586627f7eb2Smrg       if (where)
2587627f7eb2Smrg 	gfc_error ("Dummy argument %qs has to be a pointer, assumed-shape or "
2588627f7eb2Smrg 		   "assumed-rank array without CONTIGUOUS attribute - as actual"
2589627f7eb2Smrg 		   " argument at %L is not simply contiguous and both are "
2590627f7eb2Smrg 		   "ASYNCHRONOUS or VOLATILE", formal->name, &actual->where);
2591627f7eb2Smrg       return false;
2592627f7eb2Smrg     }
2593627f7eb2Smrg 
25944c3eb207Smrg   if (formal->attr.allocatable && !codimension
2595627f7eb2Smrg       && actual_attr.codimension)
2596627f7eb2Smrg     {
2597627f7eb2Smrg       if (formal->attr.intent == INTENT_OUT)
2598627f7eb2Smrg 	{
2599627f7eb2Smrg 	  if (where)
2600627f7eb2Smrg 	    gfc_error ("Passing coarray at %L to allocatable, noncoarray, "
2601627f7eb2Smrg 		       "INTENT(OUT) dummy argument %qs", &actual->where,
2602627f7eb2Smrg 		       formal->name);
2603627f7eb2Smrg 	  return false;
2604627f7eb2Smrg 	}
2605627f7eb2Smrg       else if (warn_surprising && where && formal->attr.intent != INTENT_IN)
2606627f7eb2Smrg 	gfc_warning (OPT_Wsurprising,
2607627f7eb2Smrg 		     "Passing coarray at %L to allocatable, noncoarray dummy "
2608627f7eb2Smrg 		     "argument %qs, which is invalid if the allocation status"
2609627f7eb2Smrg 		     " is modified",  &actual->where, formal->name);
2610627f7eb2Smrg     }
2611627f7eb2Smrg 
2612627f7eb2Smrg   /* If the rank is the same or the formal argument has assumed-rank.  */
2613627f7eb2Smrg   if (symbol_rank (formal) == actual->rank || symbol_rank (formal) == -1)
2614627f7eb2Smrg     return true;
2615627f7eb2Smrg 
2616627f7eb2Smrg   rank_check = where != NULL && !is_elemental && formal->as
2617627f7eb2Smrg 	       && (formal->as->type == AS_ASSUMED_SHAPE
2618627f7eb2Smrg 		   || formal->as->type == AS_DEFERRED)
2619627f7eb2Smrg 	       && actual->expr_type != EXPR_NULL;
2620627f7eb2Smrg 
2621627f7eb2Smrg   /* Skip rank checks for NO_ARG_CHECK.  */
2622627f7eb2Smrg   if (formal->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK))
2623627f7eb2Smrg     return true;
2624627f7eb2Smrg 
2625627f7eb2Smrg   /* Scalar & coindexed, see: F2008, Section 12.5.2.4.  */
2626627f7eb2Smrg   if (rank_check || ranks_must_agree
2627627f7eb2Smrg       || (formal->attr.pointer && actual->expr_type != EXPR_NULL)
2628627f7eb2Smrg       || (actual->rank != 0 && !(is_elemental || formal->attr.dimension))
2629627f7eb2Smrg       || (actual->rank == 0
2630627f7eb2Smrg 	  && ((formal->ts.type == BT_CLASS
2631627f7eb2Smrg 	       && CLASS_DATA (formal)->as->type == AS_ASSUMED_SHAPE)
2632627f7eb2Smrg 	      || (formal->ts.type != BT_CLASS
2633627f7eb2Smrg 		   && formal->as->type == AS_ASSUMED_SHAPE))
2634627f7eb2Smrg 	  && actual->expr_type != EXPR_NULL)
2635627f7eb2Smrg       || (actual->rank == 0 && formal->attr.dimension
2636627f7eb2Smrg 	  && gfc_is_coindexed (actual)))
2637627f7eb2Smrg     {
26384c3eb207Smrg       if (where
26394c3eb207Smrg 	  && (!formal->attr.artificial || (!formal->maybe_array
26404c3eb207Smrg 					   && !maybe_dummy_array_arg (actual))))
26414c3eb207Smrg 	{
26424c3eb207Smrg 	  locus *where_formal;
26434c3eb207Smrg 	  if (formal->attr.artificial)
26444c3eb207Smrg 	    where_formal = &formal->declared_at;
26454c3eb207Smrg 	  else
26464c3eb207Smrg 	    where_formal = NULL;
26474c3eb207Smrg 
2648627f7eb2Smrg 	  argument_rank_mismatch (formal->name, &actual->where,
26494c3eb207Smrg 				  symbol_rank (formal), actual->rank,
26504c3eb207Smrg 				  where_formal);
26514c3eb207Smrg 	}
2652627f7eb2Smrg       return false;
2653627f7eb2Smrg     }
2654627f7eb2Smrg   else if (actual->rank != 0 && (is_elemental || formal->attr.dimension))
2655627f7eb2Smrg     return true;
2656627f7eb2Smrg 
2657627f7eb2Smrg   /* At this point, we are considering a scalar passed to an array.   This
2658627f7eb2Smrg      is valid (cf. F95 12.4.1.1, F2003 12.4.1.2, and F2008 12.5.2.4),
2659627f7eb2Smrg      - if the actual argument is (a substring of) an element of a
2660627f7eb2Smrg        non-assumed-shape/non-pointer/non-polymorphic array; or
2661627f7eb2Smrg      - (F2003) if the actual argument is of type character of default/c_char
2662627f7eb2Smrg        kind.  */
2663627f7eb2Smrg 
2664627f7eb2Smrg   is_pointer = actual->expr_type == EXPR_VARIABLE
2665627f7eb2Smrg 	       ? actual->symtree->n.sym->attr.pointer : false;
2666627f7eb2Smrg 
2667627f7eb2Smrg   for (ref = actual->ref; ref; ref = ref->next)
2668627f7eb2Smrg     {
2669627f7eb2Smrg       if (ref->type == REF_COMPONENT)
2670627f7eb2Smrg 	is_pointer = ref->u.c.component->attr.pointer;
2671627f7eb2Smrg       else if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT
2672627f7eb2Smrg 	       && ref->u.ar.dimen > 0
2673627f7eb2Smrg 	       && (!ref->next
2674627f7eb2Smrg 		   || (ref->next->type == REF_SUBSTRING && !ref->next->next)))
2675627f7eb2Smrg         break;
2676627f7eb2Smrg     }
2677627f7eb2Smrg 
2678627f7eb2Smrg   if (actual->ts.type == BT_CLASS && actual->expr_type != EXPR_NULL)
2679627f7eb2Smrg     {
2680627f7eb2Smrg       if (where)
2681627f7eb2Smrg 	gfc_error ("Polymorphic scalar passed to array dummy argument %qs "
2682627f7eb2Smrg 		   "at %L", formal->name, &actual->where);
2683627f7eb2Smrg       return false;
2684627f7eb2Smrg     }
2685627f7eb2Smrg 
2686627f7eb2Smrg   if (actual->expr_type != EXPR_NULL && ref && actual->ts.type != BT_CHARACTER
2687627f7eb2Smrg       && (is_pointer || ref->u.ar.as->type == AS_ASSUMED_SHAPE))
2688627f7eb2Smrg     {
2689627f7eb2Smrg       if (where)
26904c3eb207Smrg 	{
26914c3eb207Smrg 	  if (formal->attr.artificial)
26924c3eb207Smrg 	    gfc_error ("Element of assumed-shape or pointer array "
26934c3eb207Smrg 		       "as actual argument at %L cannot correspond to "
26944c3eb207Smrg 		       "actual argument at %L",
26954c3eb207Smrg 		       &actual->where, &formal->declared_at);
26964c3eb207Smrg 	  else
26974c3eb207Smrg 	    gfc_error ("Element of assumed-shape or pointer "
2698627f7eb2Smrg 		       "array passed to array dummy argument %qs at %L",
2699627f7eb2Smrg 		       formal->name, &actual->where);
27004c3eb207Smrg 	}
2701627f7eb2Smrg       return false;
2702627f7eb2Smrg     }
2703627f7eb2Smrg 
2704627f7eb2Smrg   if (actual->ts.type == BT_CHARACTER && actual->expr_type != EXPR_NULL
2705627f7eb2Smrg       && (!ref || is_pointer || ref->u.ar.as->type == AS_ASSUMED_SHAPE))
2706627f7eb2Smrg     {
2707627f7eb2Smrg       if (formal->ts.kind != 1 && (gfc_option.allow_std & GFC_STD_GNU) == 0)
2708627f7eb2Smrg 	{
2709627f7eb2Smrg 	  if (where)
2710627f7eb2Smrg 	    gfc_error ("Extension: Scalar non-default-kind, non-C_CHAR-kind "
2711627f7eb2Smrg 		       "CHARACTER actual argument with array dummy argument "
2712627f7eb2Smrg 		       "%qs at %L", formal->name, &actual->where);
2713627f7eb2Smrg 	  return false;
2714627f7eb2Smrg 	}
2715627f7eb2Smrg 
2716627f7eb2Smrg       if (where && (gfc_option.allow_std & GFC_STD_F2003) == 0)
2717627f7eb2Smrg 	{
2718627f7eb2Smrg 	  gfc_error ("Fortran 2003: Scalar CHARACTER actual argument with "
2719627f7eb2Smrg 		     "array dummy argument %qs at %L",
2720627f7eb2Smrg 		     formal->name, &actual->where);
2721627f7eb2Smrg 	  return false;
2722627f7eb2Smrg 	}
2723627f7eb2Smrg       else
2724627f7eb2Smrg 	return ((gfc_option.allow_std & GFC_STD_F2003) != 0);
2725627f7eb2Smrg     }
2726627f7eb2Smrg 
2727627f7eb2Smrg   if (ref == NULL && actual->expr_type != EXPR_NULL)
2728627f7eb2Smrg     {
27294c3eb207Smrg       if (where
27304c3eb207Smrg 	  && (!formal->attr.artificial || (!formal->maybe_array
27314c3eb207Smrg 					   && !maybe_dummy_array_arg (actual))))
27324c3eb207Smrg 	{
27334c3eb207Smrg 	  locus *where_formal;
27344c3eb207Smrg 	  if (formal->attr.artificial)
27354c3eb207Smrg 	    where_formal = &formal->declared_at;
27364c3eb207Smrg 	  else
27374c3eb207Smrg 	    where_formal = NULL;
27384c3eb207Smrg 
2739627f7eb2Smrg 	  argument_rank_mismatch (formal->name, &actual->where,
27404c3eb207Smrg 				  symbol_rank (formal), actual->rank,
27414c3eb207Smrg 				  where_formal);
27424c3eb207Smrg 	}
2743627f7eb2Smrg       return false;
2744627f7eb2Smrg     }
2745627f7eb2Smrg 
2746627f7eb2Smrg   return true;
2747627f7eb2Smrg }
2748627f7eb2Smrg 
2749627f7eb2Smrg 
2750627f7eb2Smrg /* Returns the storage size of a symbol (formal argument) or
2751627f7eb2Smrg    zero if it cannot be determined.  */
2752627f7eb2Smrg 
2753627f7eb2Smrg static unsigned long
get_sym_storage_size(gfc_symbol * sym)2754627f7eb2Smrg get_sym_storage_size (gfc_symbol *sym)
2755627f7eb2Smrg {
2756627f7eb2Smrg   int i;
2757627f7eb2Smrg   unsigned long strlen, elements;
2758627f7eb2Smrg 
2759627f7eb2Smrg   if (sym->ts.type == BT_CHARACTER)
2760627f7eb2Smrg     {
2761627f7eb2Smrg       if (sym->ts.u.cl && sym->ts.u.cl->length
2762*4ac76180Smrg 	  && sym->ts.u.cl->length->expr_type == EXPR_CONSTANT
2763*4ac76180Smrg 	  && sym->ts.u.cl->length->ts.type == BT_INTEGER)
2764627f7eb2Smrg 	strlen = mpz_get_ui (sym->ts.u.cl->length->value.integer);
2765627f7eb2Smrg       else
2766627f7eb2Smrg 	return 0;
2767627f7eb2Smrg     }
2768627f7eb2Smrg   else
2769627f7eb2Smrg     strlen = 1;
2770627f7eb2Smrg 
2771627f7eb2Smrg   if (symbol_rank (sym) == 0)
2772627f7eb2Smrg     return strlen;
2773627f7eb2Smrg 
2774627f7eb2Smrg   elements = 1;
2775627f7eb2Smrg   if (sym->as->type != AS_EXPLICIT)
2776627f7eb2Smrg     return 0;
2777627f7eb2Smrg   for (i = 0; i < sym->as->rank; i++)
2778627f7eb2Smrg     {
2779627f7eb2Smrg       if (sym->as->upper[i]->expr_type != EXPR_CONSTANT
2780*4ac76180Smrg 	  || sym->as->lower[i]->expr_type != EXPR_CONSTANT
2781*4ac76180Smrg 	  || sym->as->upper[i]->ts.type != BT_INTEGER
2782*4ac76180Smrg 	  || sym->as->lower[i]->ts.type != BT_INTEGER)
2783627f7eb2Smrg 	return 0;
2784627f7eb2Smrg 
2785627f7eb2Smrg       elements *= mpz_get_si (sym->as->upper[i]->value.integer)
2786627f7eb2Smrg 		  - mpz_get_si (sym->as->lower[i]->value.integer) + 1L;
2787627f7eb2Smrg     }
2788627f7eb2Smrg 
2789627f7eb2Smrg   return strlen*elements;
2790627f7eb2Smrg }
2791627f7eb2Smrg 
2792627f7eb2Smrg 
2793627f7eb2Smrg /* Returns the storage size of an expression (actual argument) or
2794627f7eb2Smrg    zero if it cannot be determined. For an array element, it returns
2795627f7eb2Smrg    the remaining size as the element sequence consists of all storage
2796627f7eb2Smrg    units of the actual argument up to the end of the array.  */
2797627f7eb2Smrg 
2798627f7eb2Smrg static unsigned long
get_expr_storage_size(gfc_expr * e)2799627f7eb2Smrg get_expr_storage_size (gfc_expr *e)
2800627f7eb2Smrg {
2801627f7eb2Smrg   int i;
2802627f7eb2Smrg   long int strlen, elements;
2803627f7eb2Smrg   long int substrlen = 0;
2804627f7eb2Smrg   bool is_str_storage = false;
2805627f7eb2Smrg   gfc_ref *ref;
2806627f7eb2Smrg 
2807627f7eb2Smrg   if (e == NULL)
2808627f7eb2Smrg     return 0;
2809627f7eb2Smrg 
2810627f7eb2Smrg   if (e->ts.type == BT_CHARACTER)
2811627f7eb2Smrg     {
2812627f7eb2Smrg       if (e->ts.u.cl && e->ts.u.cl->length
2813*4ac76180Smrg 	  && e->ts.u.cl->length->expr_type == EXPR_CONSTANT
2814*4ac76180Smrg 	  && e->ts.u.cl->length->ts.type == BT_INTEGER)
2815627f7eb2Smrg 	strlen = mpz_get_si (e->ts.u.cl->length->value.integer);
2816627f7eb2Smrg       else if (e->expr_type == EXPR_CONSTANT
2817627f7eb2Smrg 	       && (e->ts.u.cl == NULL || e->ts.u.cl->length == NULL))
2818627f7eb2Smrg 	strlen = e->value.character.length;
2819627f7eb2Smrg       else
2820627f7eb2Smrg 	return 0;
2821627f7eb2Smrg     }
2822627f7eb2Smrg   else
2823627f7eb2Smrg     strlen = 1; /* Length per element.  */
2824627f7eb2Smrg 
2825627f7eb2Smrg   if (e->rank == 0 && !e->ref)
2826627f7eb2Smrg     return strlen;
2827627f7eb2Smrg 
2828627f7eb2Smrg   elements = 1;
2829627f7eb2Smrg   if (!e->ref)
2830627f7eb2Smrg     {
2831627f7eb2Smrg       if (!e->shape)
2832627f7eb2Smrg 	return 0;
2833627f7eb2Smrg       for (i = 0; i < e->rank; i++)
2834627f7eb2Smrg 	elements *= mpz_get_si (e->shape[i]);
2835627f7eb2Smrg       return elements*strlen;
2836627f7eb2Smrg     }
2837627f7eb2Smrg 
2838627f7eb2Smrg   for (ref = e->ref; ref; ref = ref->next)
2839627f7eb2Smrg     {
2840627f7eb2Smrg       if (ref->type == REF_SUBSTRING && ref->u.ss.start
2841627f7eb2Smrg 	  && ref->u.ss.start->expr_type == EXPR_CONSTANT)
2842627f7eb2Smrg 	{
2843627f7eb2Smrg 	  if (is_str_storage)
2844627f7eb2Smrg 	    {
2845627f7eb2Smrg 	      /* The string length is the substring length.
2846627f7eb2Smrg 		 Set now to full string length.  */
2847627f7eb2Smrg 	      if (!ref->u.ss.length || !ref->u.ss.length->length
2848627f7eb2Smrg 		  || ref->u.ss.length->length->expr_type != EXPR_CONSTANT)
2849627f7eb2Smrg 		return 0;
2850627f7eb2Smrg 
2851627f7eb2Smrg 	      strlen = mpz_get_ui (ref->u.ss.length->length->value.integer);
2852627f7eb2Smrg 	    }
2853627f7eb2Smrg 	  substrlen = strlen - mpz_get_ui (ref->u.ss.start->value.integer) + 1;
2854627f7eb2Smrg 	  continue;
2855627f7eb2Smrg 	}
2856627f7eb2Smrg 
2857627f7eb2Smrg       if (ref->type == REF_ARRAY && ref->u.ar.type == AR_SECTION)
2858627f7eb2Smrg 	for (i = 0; i < ref->u.ar.dimen; i++)
2859627f7eb2Smrg 	  {
2860627f7eb2Smrg 	    long int start, end, stride;
2861627f7eb2Smrg 	    stride = 1;
2862627f7eb2Smrg 
2863627f7eb2Smrg 	    if (ref->u.ar.stride[i])
2864627f7eb2Smrg 	      {
2865*4ac76180Smrg 		if (ref->u.ar.stride[i]->expr_type == EXPR_CONSTANT
2866*4ac76180Smrg 		    && ref->u.ar.stride[i]->ts.type == BT_INTEGER)
2867627f7eb2Smrg 		  stride = mpz_get_si (ref->u.ar.stride[i]->value.integer);
2868627f7eb2Smrg 		else
2869627f7eb2Smrg 		  return 0;
2870627f7eb2Smrg 	      }
2871627f7eb2Smrg 
2872627f7eb2Smrg 	    if (ref->u.ar.start[i])
2873627f7eb2Smrg 	      {
2874*4ac76180Smrg 		if (ref->u.ar.start[i]->expr_type == EXPR_CONSTANT
2875*4ac76180Smrg 		    && ref->u.ar.start[i]->ts.type == BT_INTEGER)
2876627f7eb2Smrg 		  start = mpz_get_si (ref->u.ar.start[i]->value.integer);
2877627f7eb2Smrg 		else
2878627f7eb2Smrg 		  return 0;
2879627f7eb2Smrg 	      }
2880627f7eb2Smrg 	    else if (ref->u.ar.as->lower[i]
2881*4ac76180Smrg 		     && ref->u.ar.as->lower[i]->expr_type == EXPR_CONSTANT
2882*4ac76180Smrg 		     && ref->u.ar.as->lower[i]->ts.type == BT_INTEGER)
2883627f7eb2Smrg 	      start = mpz_get_si (ref->u.ar.as->lower[i]->value.integer);
2884627f7eb2Smrg 	    else
2885627f7eb2Smrg 	      return 0;
2886627f7eb2Smrg 
2887627f7eb2Smrg 	    if (ref->u.ar.end[i])
2888627f7eb2Smrg 	      {
2889*4ac76180Smrg 		if (ref->u.ar.end[i]->expr_type == EXPR_CONSTANT
2890*4ac76180Smrg 		    && ref->u.ar.end[i]->ts.type == BT_INTEGER)
2891627f7eb2Smrg 		  end = mpz_get_si (ref->u.ar.end[i]->value.integer);
2892627f7eb2Smrg 		else
2893627f7eb2Smrg 		  return 0;
2894627f7eb2Smrg 	      }
2895627f7eb2Smrg 	    else if (ref->u.ar.as->upper[i]
2896*4ac76180Smrg 		     && ref->u.ar.as->upper[i]->expr_type == EXPR_CONSTANT
2897*4ac76180Smrg 		     && ref->u.ar.as->upper[i]->ts.type == BT_INTEGER)
2898627f7eb2Smrg 	      end = mpz_get_si (ref->u.ar.as->upper[i]->value.integer);
2899627f7eb2Smrg 	    else
2900627f7eb2Smrg 	      return 0;
2901627f7eb2Smrg 
2902627f7eb2Smrg 	    elements *= (end - start)/stride + 1L;
2903627f7eb2Smrg 	  }
2904627f7eb2Smrg       else if (ref->type == REF_ARRAY && ref->u.ar.type == AR_FULL)
2905627f7eb2Smrg 	for (i = 0; i < ref->u.ar.as->rank; i++)
2906627f7eb2Smrg 	  {
2907627f7eb2Smrg 	    if (ref->u.ar.as->lower[i] && ref->u.ar.as->upper[i]
2908627f7eb2Smrg 		&& ref->u.ar.as->lower[i]->expr_type == EXPR_CONSTANT
2909627f7eb2Smrg 		&& ref->u.ar.as->lower[i]->ts.type == BT_INTEGER
2910627f7eb2Smrg 		&& ref->u.ar.as->upper[i]->expr_type == EXPR_CONSTANT
2911627f7eb2Smrg 		&& ref->u.ar.as->upper[i]->ts.type == BT_INTEGER)
2912627f7eb2Smrg 	      elements *= mpz_get_si (ref->u.ar.as->upper[i]->value.integer)
2913627f7eb2Smrg 			  - mpz_get_si (ref->u.ar.as->lower[i]->value.integer)
2914627f7eb2Smrg 			  + 1L;
2915627f7eb2Smrg 	    else
2916627f7eb2Smrg 	      return 0;
2917627f7eb2Smrg 	  }
2918627f7eb2Smrg       else if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT
2919627f7eb2Smrg 	       && e->expr_type == EXPR_VARIABLE)
2920627f7eb2Smrg 	{
2921627f7eb2Smrg 	  if (ref->u.ar.as->type == AS_ASSUMED_SHAPE
2922627f7eb2Smrg 	      || e->symtree->n.sym->attr.pointer)
2923627f7eb2Smrg 	    {
2924627f7eb2Smrg 	      elements = 1;
2925627f7eb2Smrg 	      continue;
2926627f7eb2Smrg 	    }
2927627f7eb2Smrg 
2928627f7eb2Smrg 	  /* Determine the number of remaining elements in the element
2929627f7eb2Smrg 	     sequence for array element designators.  */
2930627f7eb2Smrg 	  is_str_storage = true;
2931627f7eb2Smrg 	  for (i = ref->u.ar.dimen - 1; i >= 0; i--)
2932627f7eb2Smrg 	    {
2933627f7eb2Smrg 	      if (ref->u.ar.start[i] == NULL
2934627f7eb2Smrg 		  || ref->u.ar.start[i]->expr_type != EXPR_CONSTANT
2935627f7eb2Smrg 		  || ref->u.ar.as->upper[i] == NULL
2936627f7eb2Smrg 		  || ref->u.ar.as->lower[i] == NULL
2937627f7eb2Smrg 		  || ref->u.ar.as->upper[i]->expr_type != EXPR_CONSTANT
2938*4ac76180Smrg 		  || ref->u.ar.as->lower[i]->expr_type != EXPR_CONSTANT
2939*4ac76180Smrg 		  || ref->u.ar.as->upper[i]->ts.type != BT_INTEGER
2940*4ac76180Smrg 		  || ref->u.ar.as->lower[i]->ts.type != BT_INTEGER)
2941627f7eb2Smrg 		return 0;
2942627f7eb2Smrg 
2943627f7eb2Smrg 	      elements
2944627f7eb2Smrg 		   = elements
2945627f7eb2Smrg 		     * (mpz_get_si (ref->u.ar.as->upper[i]->value.integer)
2946627f7eb2Smrg 			- mpz_get_si (ref->u.ar.as->lower[i]->value.integer)
2947627f7eb2Smrg 			+ 1L)
2948627f7eb2Smrg 		     - (mpz_get_si (ref->u.ar.start[i]->value.integer)
2949627f7eb2Smrg 			- mpz_get_si (ref->u.ar.as->lower[i]->value.integer));
2950627f7eb2Smrg 	    }
2951627f7eb2Smrg         }
2952627f7eb2Smrg       else if (ref->type == REF_COMPONENT && ref->u.c.component->attr.function
2953627f7eb2Smrg 	       && ref->u.c.component->attr.proc_pointer
2954627f7eb2Smrg 	       && ref->u.c.component->attr.dimension)
2955627f7eb2Smrg 	{
2956627f7eb2Smrg 	  /* Array-valued procedure-pointer components.  */
2957627f7eb2Smrg 	  gfc_array_spec *as = ref->u.c.component->as;
2958627f7eb2Smrg 	  for (i = 0; i < as->rank; i++)
2959627f7eb2Smrg 	    {
2960627f7eb2Smrg 	      if (!as->upper[i] || !as->lower[i]
2961627f7eb2Smrg 		  || as->upper[i]->expr_type != EXPR_CONSTANT
2962*4ac76180Smrg 		  || as->lower[i]->expr_type != EXPR_CONSTANT
2963*4ac76180Smrg 		  || as->upper[i]->ts.type != BT_INTEGER
2964*4ac76180Smrg 		  || as->lower[i]->ts.type != BT_INTEGER)
2965627f7eb2Smrg 		return 0;
2966627f7eb2Smrg 
2967627f7eb2Smrg 	      elements = elements
2968627f7eb2Smrg 			 * (mpz_get_si (as->upper[i]->value.integer)
2969627f7eb2Smrg 			    - mpz_get_si (as->lower[i]->value.integer) + 1L);
2970627f7eb2Smrg 	    }
2971627f7eb2Smrg 	}
2972627f7eb2Smrg     }
2973627f7eb2Smrg 
2974627f7eb2Smrg   if (substrlen)
2975627f7eb2Smrg     return (is_str_storage) ? substrlen + (elements-1)*strlen
2976627f7eb2Smrg 			    : elements*strlen;
2977627f7eb2Smrg   else
2978627f7eb2Smrg     return elements*strlen;
2979627f7eb2Smrg }
2980627f7eb2Smrg 
2981627f7eb2Smrg 
2982627f7eb2Smrg /* Given an expression, check whether it is an array section
2983627f7eb2Smrg    which has a vector subscript.  */
2984627f7eb2Smrg 
2985627f7eb2Smrg bool
gfc_has_vector_subscript(gfc_expr * e)2986627f7eb2Smrg gfc_has_vector_subscript (gfc_expr *e)
2987627f7eb2Smrg {
2988627f7eb2Smrg   int i;
2989627f7eb2Smrg   gfc_ref *ref;
2990627f7eb2Smrg 
2991627f7eb2Smrg   if (e == NULL || e->rank == 0 || e->expr_type != EXPR_VARIABLE)
2992627f7eb2Smrg     return false;
2993627f7eb2Smrg 
2994627f7eb2Smrg   for (ref = e->ref; ref; ref = ref->next)
2995627f7eb2Smrg     if (ref->type == REF_ARRAY && ref->u.ar.type == AR_SECTION)
2996627f7eb2Smrg       for (i = 0; i < ref->u.ar.dimen; i++)
2997627f7eb2Smrg 	if (ref->u.ar.dimen_type[i] == DIMEN_VECTOR)
2998627f7eb2Smrg 	  return true;
2999627f7eb2Smrg 
3000627f7eb2Smrg   return false;
3001627f7eb2Smrg }
3002627f7eb2Smrg 
3003627f7eb2Smrg 
3004627f7eb2Smrg static bool
is_procptr_result(gfc_expr * expr)3005627f7eb2Smrg is_procptr_result (gfc_expr *expr)
3006627f7eb2Smrg {
3007627f7eb2Smrg   gfc_component *c = gfc_get_proc_ptr_comp (expr);
3008627f7eb2Smrg   if (c)
3009627f7eb2Smrg     return (c->ts.interface && (c->ts.interface->attr.proc_pointer == 1));
3010627f7eb2Smrg   else
3011627f7eb2Smrg     return ((expr->symtree->n.sym->result != expr->symtree->n.sym)
3012627f7eb2Smrg 	    && (expr->symtree->n.sym->result->attr.proc_pointer == 1));
3013627f7eb2Smrg }
3014627f7eb2Smrg 
3015627f7eb2Smrg 
3016627f7eb2Smrg /* Recursively append candidate argument ARG to CANDIDATES.  Store the
3017627f7eb2Smrg    number of total candidates in CANDIDATES_LEN.  */
3018627f7eb2Smrg 
3019627f7eb2Smrg static void
lookup_arg_fuzzy_find_candidates(gfc_formal_arglist * arg,char ** & candidates,size_t & candidates_len)3020627f7eb2Smrg lookup_arg_fuzzy_find_candidates (gfc_formal_arglist *arg,
3021627f7eb2Smrg 				  char **&candidates,
3022627f7eb2Smrg 				  size_t &candidates_len)
3023627f7eb2Smrg {
3024627f7eb2Smrg   for (gfc_formal_arglist *p = arg; p && p->sym; p = p->next)
3025627f7eb2Smrg     vec_push (candidates, candidates_len, p->sym->name);
3026627f7eb2Smrg }
3027627f7eb2Smrg 
3028627f7eb2Smrg 
3029627f7eb2Smrg /* Lookup argument ARG fuzzily, taking names in ARGUMENTS into account.  */
3030627f7eb2Smrg 
3031627f7eb2Smrg static const char*
lookup_arg_fuzzy(const char * arg,gfc_formal_arglist * arguments)3032627f7eb2Smrg lookup_arg_fuzzy (const char *arg, gfc_formal_arglist *arguments)
3033627f7eb2Smrg {
3034627f7eb2Smrg   char **candidates = NULL;
3035627f7eb2Smrg   size_t candidates_len = 0;
3036627f7eb2Smrg   lookup_arg_fuzzy_find_candidates (arguments, candidates, candidates_len);
3037627f7eb2Smrg   return gfc_closest_fuzzy_match (arg, candidates);
3038627f7eb2Smrg }
3039627f7eb2Smrg 
3040627f7eb2Smrg 
3041627f7eb2Smrg /* Given formal and actual argument lists, see if they are compatible.
3042627f7eb2Smrg    If they are compatible, the actual argument list is sorted to
3043627f7eb2Smrg    correspond with the formal list, and elements for missing optional
3044627f7eb2Smrg    arguments are inserted. If WHERE pointer is nonnull, then we issue
3045627f7eb2Smrg    errors when things don't match instead of just returning the status
3046627f7eb2Smrg    code.  */
3047627f7eb2Smrg 
30484c3eb207Smrg bool
gfc_compare_actual_formal(gfc_actual_arglist ** ap,gfc_formal_arglist * formal,int ranks_must_agree,int is_elemental,bool in_statement_function,locus * where)30494c3eb207Smrg gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
3050627f7eb2Smrg 			   int ranks_must_agree, int is_elemental,
3051627f7eb2Smrg 			   bool in_statement_function, locus *where)
3052627f7eb2Smrg {
3053627f7eb2Smrg   gfc_actual_arglist **new_arg, *a, *actual;
3054627f7eb2Smrg   gfc_formal_arglist *f;
3055627f7eb2Smrg   int i, n, na;
3056627f7eb2Smrg   unsigned long actual_size, formal_size;
3057627f7eb2Smrg   bool full_array = false;
3058627f7eb2Smrg   gfc_array_ref *actual_arr_ref;
3059627f7eb2Smrg 
3060627f7eb2Smrg   actual = *ap;
3061627f7eb2Smrg 
3062627f7eb2Smrg   if (actual == NULL && formal == NULL)
3063627f7eb2Smrg     return true;
3064627f7eb2Smrg 
3065627f7eb2Smrg   n = 0;
3066627f7eb2Smrg   for (f = formal; f; f = f->next)
3067627f7eb2Smrg     n++;
3068627f7eb2Smrg 
3069627f7eb2Smrg   new_arg = XALLOCAVEC (gfc_actual_arglist *, n);
3070627f7eb2Smrg 
3071627f7eb2Smrg   for (i = 0; i < n; i++)
3072627f7eb2Smrg     new_arg[i] = NULL;
3073627f7eb2Smrg 
3074627f7eb2Smrg   na = 0;
3075627f7eb2Smrg   f = formal;
3076627f7eb2Smrg   i = 0;
3077627f7eb2Smrg 
3078627f7eb2Smrg   for (a = actual; a; a = a->next, f = f->next)
3079627f7eb2Smrg     {
3080627f7eb2Smrg       if (a->name != NULL && in_statement_function)
3081627f7eb2Smrg 	{
3082627f7eb2Smrg 	  gfc_error ("Keyword argument %qs at %L is invalid in "
3083627f7eb2Smrg 		     "a statement function", a->name, &a->expr->where);
3084627f7eb2Smrg 	  return false;
3085627f7eb2Smrg 	}
3086627f7eb2Smrg 
3087627f7eb2Smrg       /* Look for keywords but ignore g77 extensions like %VAL.  */
3088627f7eb2Smrg       if (a->name != NULL && a->name[0] != '%')
3089627f7eb2Smrg 	{
3090627f7eb2Smrg 	  i = 0;
3091627f7eb2Smrg 	  for (f = formal; f; f = f->next, i++)
3092627f7eb2Smrg 	    {
3093627f7eb2Smrg 	      if (f->sym == NULL)
3094627f7eb2Smrg 		continue;
3095627f7eb2Smrg 	      if (strcmp (f->sym->name, a->name) == 0)
3096627f7eb2Smrg 		break;
3097627f7eb2Smrg 	    }
3098627f7eb2Smrg 
3099627f7eb2Smrg 	  if (f == NULL)
3100627f7eb2Smrg 	    {
3101627f7eb2Smrg 	      if (where)
3102627f7eb2Smrg 		{
3103627f7eb2Smrg 		  const char *guessed = lookup_arg_fuzzy (a->name, formal);
3104627f7eb2Smrg 		  if (guessed)
3105627f7eb2Smrg 		    gfc_error ("Keyword argument %qs at %L is not in "
3106627f7eb2Smrg 			       "the procedure; did you mean %qs?",
3107627f7eb2Smrg 			       a->name, &a->expr->where, guessed);
3108627f7eb2Smrg 		  else
3109627f7eb2Smrg 		    gfc_error ("Keyword argument %qs at %L is not in "
3110627f7eb2Smrg 			       "the procedure", a->name, &a->expr->where);
3111627f7eb2Smrg 		}
3112627f7eb2Smrg 	      return false;
3113627f7eb2Smrg 	    }
3114627f7eb2Smrg 
3115627f7eb2Smrg 	  if (new_arg[i] != NULL)
3116627f7eb2Smrg 	    {
3117627f7eb2Smrg 	      if (where)
3118627f7eb2Smrg 		gfc_error ("Keyword argument %qs at %L is already associated "
3119627f7eb2Smrg 			   "with another actual argument", a->name,
3120627f7eb2Smrg 			   &a->expr->where);
3121627f7eb2Smrg 	      return false;
3122627f7eb2Smrg 	    }
3123627f7eb2Smrg 	}
3124627f7eb2Smrg 
3125627f7eb2Smrg       if (f == NULL)
3126627f7eb2Smrg 	{
3127627f7eb2Smrg 	  if (where)
3128627f7eb2Smrg 	    gfc_error ("More actual than formal arguments in procedure "
3129627f7eb2Smrg 		       "call at %L", where);
3130627f7eb2Smrg 
3131627f7eb2Smrg 	  return false;
3132627f7eb2Smrg 	}
3133627f7eb2Smrg 
3134627f7eb2Smrg       if (f->sym == NULL && a->expr == NULL)
3135627f7eb2Smrg 	goto match;
3136627f7eb2Smrg 
3137627f7eb2Smrg       if (f->sym == NULL)
3138627f7eb2Smrg 	{
3139627f7eb2Smrg 	  /* These errors have to be issued, otherwise an ICE can occur.
3140627f7eb2Smrg 	     See PR 78865.  */
3141627f7eb2Smrg 	  if (where)
3142627f7eb2Smrg 	    gfc_error_now ("Missing alternate return specifier in subroutine "
3143627f7eb2Smrg 			   "call at %L", where);
3144627f7eb2Smrg 	  return false;
3145627f7eb2Smrg 	}
3146627f7eb2Smrg 
3147627f7eb2Smrg       if (a->expr == NULL)
3148627f7eb2Smrg 	{
31494c3eb207Smrg 	  if (f->sym->attr.optional)
31504c3eb207Smrg 	    continue;
31514c3eb207Smrg 	  else
31524c3eb207Smrg 	    {
3153627f7eb2Smrg 	      if (where)
3154627f7eb2Smrg 		gfc_error_now ("Unexpected alternate return specifier in "
3155627f7eb2Smrg 			       "subroutine call at %L", where);
3156627f7eb2Smrg 	      return false;
3157627f7eb2Smrg 	    }
31584c3eb207Smrg 	}
3159627f7eb2Smrg 
3160627f7eb2Smrg       /* Make sure that intrinsic vtables exist for calls to unlimited
3161627f7eb2Smrg 	 polymorphic formal arguments.  */
3162627f7eb2Smrg       if (UNLIMITED_POLY (f->sym)
3163627f7eb2Smrg 	  && a->expr->ts.type != BT_DERIVED
31644c3eb207Smrg 	  && a->expr->ts.type != BT_CLASS
31654c3eb207Smrg 	  && a->expr->ts.type != BT_ASSUMED)
3166627f7eb2Smrg 	gfc_find_vtab (&a->expr->ts);
3167627f7eb2Smrg 
3168627f7eb2Smrg       if (a->expr->expr_type == EXPR_NULL
3169627f7eb2Smrg 	  && ((f->sym->ts.type != BT_CLASS && !f->sym->attr.pointer
3170627f7eb2Smrg 	       && (f->sym->attr.allocatable || !f->sym->attr.optional
3171627f7eb2Smrg 		   || (gfc_option.allow_std & GFC_STD_F2008) == 0))
3172627f7eb2Smrg 	      || (f->sym->ts.type == BT_CLASS
3173627f7eb2Smrg 		  && !CLASS_DATA (f->sym)->attr.class_pointer
3174627f7eb2Smrg 		  && (CLASS_DATA (f->sym)->attr.allocatable
3175627f7eb2Smrg 		      || !f->sym->attr.optional
3176627f7eb2Smrg 		      || (gfc_option.allow_std & GFC_STD_F2008) == 0))))
3177627f7eb2Smrg 	{
3178627f7eb2Smrg 	  if (where
3179627f7eb2Smrg 	      && (!f->sym->attr.optional
3180627f7eb2Smrg 		  || (f->sym->ts.type != BT_CLASS && f->sym->attr.allocatable)
3181627f7eb2Smrg 		  || (f->sym->ts.type == BT_CLASS
3182627f7eb2Smrg 			 && CLASS_DATA (f->sym)->attr.allocatable)))
3183627f7eb2Smrg 	    gfc_error ("Unexpected NULL() intrinsic at %L to dummy %qs",
3184627f7eb2Smrg 		       where, f->sym->name);
3185627f7eb2Smrg 	  else if (where)
3186627f7eb2Smrg 	    gfc_error ("Fortran 2008: Null pointer at %L to non-pointer "
3187627f7eb2Smrg 		       "dummy %qs", where, f->sym->name);
3188627f7eb2Smrg 
3189627f7eb2Smrg 	  return false;
3190627f7eb2Smrg 	}
3191627f7eb2Smrg 
3192627f7eb2Smrg       if (!compare_parameter (f->sym, a->expr, ranks_must_agree,
3193627f7eb2Smrg 			      is_elemental, where))
3194627f7eb2Smrg 	return false;
3195627f7eb2Smrg 
3196627f7eb2Smrg       /* TS 29113, 6.3p2.  */
3197627f7eb2Smrg       if (f->sym->ts.type == BT_ASSUMED
3198627f7eb2Smrg 	  && (a->expr->ts.type == BT_DERIVED
3199627f7eb2Smrg 	      || (a->expr->ts.type == BT_CLASS && CLASS_DATA (a->expr))))
3200627f7eb2Smrg 	{
3201627f7eb2Smrg 	  gfc_namespace *f2k_derived;
3202627f7eb2Smrg 
3203627f7eb2Smrg 	  f2k_derived = a->expr->ts.type == BT_DERIVED
3204627f7eb2Smrg 			? a->expr->ts.u.derived->f2k_derived
3205627f7eb2Smrg 			: CLASS_DATA (a->expr)->ts.u.derived->f2k_derived;
3206627f7eb2Smrg 
3207627f7eb2Smrg 	  if (f2k_derived
3208627f7eb2Smrg 	      && (f2k_derived->finalizers || f2k_derived->tb_sym_root))
3209627f7eb2Smrg 	    {
3210627f7eb2Smrg 	      gfc_error ("Actual argument at %L to assumed-type dummy is of "
3211627f7eb2Smrg 			 "derived type with type-bound or FINAL procedures",
3212627f7eb2Smrg 			 &a->expr->where);
3213627f7eb2Smrg 	      return false;
3214627f7eb2Smrg 	    }
3215627f7eb2Smrg 	}
3216627f7eb2Smrg 
3217627f7eb2Smrg       /* Special case for character arguments.  For allocatable, pointer
3218627f7eb2Smrg 	 and assumed-shape dummies, the string length needs to match
3219627f7eb2Smrg 	 exactly.  */
3220627f7eb2Smrg       if (a->expr->ts.type == BT_CHARACTER
3221627f7eb2Smrg 	  && a->expr->ts.u.cl && a->expr->ts.u.cl->length
3222627f7eb2Smrg 	  && a->expr->ts.u.cl->length->expr_type == EXPR_CONSTANT
3223627f7eb2Smrg 	  && f->sym->ts.type == BT_CHARACTER && f->sym->ts.u.cl
3224627f7eb2Smrg 	  && f->sym->ts.u.cl->length
3225627f7eb2Smrg 	  && f->sym->ts.u.cl->length->expr_type == EXPR_CONSTANT
3226627f7eb2Smrg 	  && (f->sym->attr.pointer || f->sym->attr.allocatable
3227627f7eb2Smrg 	      || (f->sym->as && f->sym->as->type == AS_ASSUMED_SHAPE))
3228627f7eb2Smrg 	  && (mpz_cmp (a->expr->ts.u.cl->length->value.integer,
3229627f7eb2Smrg 		       f->sym->ts.u.cl->length->value.integer) != 0))
3230627f7eb2Smrg 	{
3231627f7eb2Smrg 	  if (where && (f->sym->attr.pointer || f->sym->attr.allocatable))
32324c3eb207Smrg 	    gfc_warning (0, "Character length mismatch (%ld/%ld) between actual "
3233627f7eb2Smrg 			 "argument and pointer or allocatable dummy argument "
3234627f7eb2Smrg 			 "%qs at %L",
3235627f7eb2Smrg 			 mpz_get_si (a->expr->ts.u.cl->length->value.integer),
3236627f7eb2Smrg 			 mpz_get_si (f->sym->ts.u.cl->length->value.integer),
3237627f7eb2Smrg 			 f->sym->name, &a->expr->where);
3238627f7eb2Smrg 	  else if (where)
32394c3eb207Smrg 	    gfc_warning (0, "Character length mismatch (%ld/%ld) between actual "
3240627f7eb2Smrg 			 "argument and assumed-shape dummy argument %qs "
3241627f7eb2Smrg 			 "at %L",
3242627f7eb2Smrg 			 mpz_get_si (a->expr->ts.u.cl->length->value.integer),
3243627f7eb2Smrg 			 mpz_get_si (f->sym->ts.u.cl->length->value.integer),
3244627f7eb2Smrg 			 f->sym->name, &a->expr->where);
3245627f7eb2Smrg 	  return false;
3246627f7eb2Smrg 	}
3247627f7eb2Smrg 
3248627f7eb2Smrg       if ((f->sym->attr.pointer || f->sym->attr.allocatable)
3249627f7eb2Smrg 	  && f->sym->ts.deferred != a->expr->ts.deferred
3250627f7eb2Smrg 	  && a->expr->ts.type == BT_CHARACTER)
3251627f7eb2Smrg 	{
3252627f7eb2Smrg 	  if (where)
3253627f7eb2Smrg 	    gfc_error ("Actual argument at %L to allocatable or "
3254627f7eb2Smrg 		       "pointer dummy argument %qs must have a deferred "
3255627f7eb2Smrg 		       "length type parameter if and only if the dummy has one",
3256627f7eb2Smrg 		       &a->expr->where, f->sym->name);
3257627f7eb2Smrg 	  return false;
3258627f7eb2Smrg 	}
3259627f7eb2Smrg 
3260627f7eb2Smrg       if (f->sym->ts.type == BT_CLASS)
3261627f7eb2Smrg 	goto skip_size_check;
3262627f7eb2Smrg 
3263627f7eb2Smrg       actual_size = get_expr_storage_size (a->expr);
3264627f7eb2Smrg       formal_size = get_sym_storage_size (f->sym);
3265627f7eb2Smrg       if (actual_size != 0 && actual_size < formal_size
3266627f7eb2Smrg 	  && a->expr->ts.type != BT_PROCEDURE
3267627f7eb2Smrg 	  && f->sym->attr.flavor != FL_PROCEDURE)
3268627f7eb2Smrg 	{
3269627f7eb2Smrg 	  if (a->expr->ts.type == BT_CHARACTER && !f->sym->as && where)
32704c3eb207Smrg 	    {
32714c3eb207Smrg 	      gfc_warning (0, "Character length of actual argument shorter "
3272627f7eb2Smrg 			   "than of dummy argument %qs (%lu/%lu) at %L",
3273627f7eb2Smrg 			   f->sym->name, actual_size, formal_size,
3274627f7eb2Smrg 			   &a->expr->where);
32754c3eb207Smrg 	      goto skip_size_check;
32764c3eb207Smrg 	    }
3277627f7eb2Smrg           else if (where)
3278627f7eb2Smrg 	    {
3279627f7eb2Smrg 	      /* Emit a warning for -std=legacy and an error otherwise. */
3280627f7eb2Smrg 	      if (gfc_option.warn_std == 0)
32814c3eb207Smrg 	        gfc_warning (0, "Actual argument contains too few "
3282627f7eb2Smrg 			     "elements for dummy argument %qs (%lu/%lu) "
3283627f7eb2Smrg 			     "at %L", f->sym->name, actual_size,
3284627f7eb2Smrg 			     formal_size, &a->expr->where);
3285627f7eb2Smrg 	      else
3286627f7eb2Smrg 	        gfc_error_now ("Actual argument contains too few "
3287627f7eb2Smrg 			       "elements for dummy argument %qs (%lu/%lu) "
3288627f7eb2Smrg 			       "at %L", f->sym->name, actual_size,
3289627f7eb2Smrg 			       formal_size, &a->expr->where);
3290627f7eb2Smrg 	    }
3291627f7eb2Smrg 	  return false;
3292627f7eb2Smrg 	}
3293627f7eb2Smrg 
3294627f7eb2Smrg      skip_size_check:
3295627f7eb2Smrg 
3296627f7eb2Smrg       /* Satisfy F03:12.4.1.3 by ensuring that a procedure pointer actual
3297627f7eb2Smrg          argument is provided for a procedure pointer formal argument.  */
3298627f7eb2Smrg       if (f->sym->attr.proc_pointer
3299627f7eb2Smrg 	  && !((a->expr->expr_type == EXPR_VARIABLE
3300627f7eb2Smrg 		&& (a->expr->symtree->n.sym->attr.proc_pointer
3301627f7eb2Smrg 		    || gfc_is_proc_ptr_comp (a->expr)))
3302627f7eb2Smrg 	       || (a->expr->expr_type == EXPR_FUNCTION
3303627f7eb2Smrg 		   && is_procptr_result (a->expr))))
3304627f7eb2Smrg 	{
3305627f7eb2Smrg 	  if (where)
3306627f7eb2Smrg 	    gfc_error ("Expected a procedure pointer for argument %qs at %L",
3307627f7eb2Smrg 		       f->sym->name, &a->expr->where);
3308627f7eb2Smrg 	  return false;
3309627f7eb2Smrg 	}
3310627f7eb2Smrg 
3311627f7eb2Smrg       /* Satisfy F03:12.4.1.3 by ensuring that a procedure actual argument is
3312627f7eb2Smrg 	 provided for a procedure formal argument.  */
3313627f7eb2Smrg       if (f->sym->attr.flavor == FL_PROCEDURE
3314627f7eb2Smrg 	  && !((a->expr->expr_type == EXPR_VARIABLE
3315627f7eb2Smrg 		&& (a->expr->symtree->n.sym->attr.flavor == FL_PROCEDURE
3316627f7eb2Smrg 		    || a->expr->symtree->n.sym->attr.proc_pointer
3317627f7eb2Smrg 		    || gfc_is_proc_ptr_comp (a->expr)))
3318627f7eb2Smrg 	       || (a->expr->expr_type == EXPR_FUNCTION
3319627f7eb2Smrg 		   && is_procptr_result (a->expr))))
3320627f7eb2Smrg 	{
3321627f7eb2Smrg 	  if (where)
3322627f7eb2Smrg 	    gfc_error ("Expected a procedure for argument %qs at %L",
3323627f7eb2Smrg 		       f->sym->name, &a->expr->where);
3324627f7eb2Smrg 	  return false;
3325627f7eb2Smrg 	}
3326627f7eb2Smrg 
3327627f7eb2Smrg       if (f->sym->as && f->sym->as->type == AS_ASSUMED_SHAPE
3328627f7eb2Smrg 	  && a->expr->expr_type == EXPR_VARIABLE
3329627f7eb2Smrg 	  && a->expr->symtree->n.sym->as
3330627f7eb2Smrg 	  && a->expr->symtree->n.sym->as->type == AS_ASSUMED_SIZE
3331627f7eb2Smrg 	  && (a->expr->ref == NULL
3332627f7eb2Smrg 	      || (a->expr->ref->type == REF_ARRAY
3333627f7eb2Smrg 		  && a->expr->ref->u.ar.type == AR_FULL)))
3334627f7eb2Smrg 	{
3335627f7eb2Smrg 	  if (where)
3336627f7eb2Smrg 	    gfc_error ("Actual argument for %qs cannot be an assumed-size"
3337627f7eb2Smrg 		       " array at %L", f->sym->name, where);
3338627f7eb2Smrg 	  return false;
3339627f7eb2Smrg 	}
3340627f7eb2Smrg 
3341627f7eb2Smrg       if (a->expr->expr_type != EXPR_NULL
3342627f7eb2Smrg 	  && compare_pointer (f->sym, a->expr) == 0)
3343627f7eb2Smrg 	{
3344627f7eb2Smrg 	  if (where)
3345627f7eb2Smrg 	    gfc_error ("Actual argument for %qs must be a pointer at %L",
3346627f7eb2Smrg 		       f->sym->name, &a->expr->where);
3347627f7eb2Smrg 	  return false;
3348627f7eb2Smrg 	}
3349627f7eb2Smrg 
3350627f7eb2Smrg       if (a->expr->expr_type != EXPR_NULL
3351627f7eb2Smrg 	  && (gfc_option.allow_std & GFC_STD_F2008) == 0
3352627f7eb2Smrg 	  && compare_pointer (f->sym, a->expr) == 2)
3353627f7eb2Smrg 	{
3354627f7eb2Smrg 	  if (where)
3355627f7eb2Smrg 	    gfc_error ("Fortran 2008: Non-pointer actual argument at %L to "
3356627f7eb2Smrg 		       "pointer dummy %qs", &a->expr->where,f->sym->name);
3357627f7eb2Smrg 	  return false;
3358627f7eb2Smrg 	}
3359627f7eb2Smrg 
3360627f7eb2Smrg 
3361627f7eb2Smrg       /* Fortran 2008, C1242.  */
3362627f7eb2Smrg       if (f->sym->attr.pointer && gfc_is_coindexed (a->expr))
3363627f7eb2Smrg 	{
3364627f7eb2Smrg 	  if (where)
3365627f7eb2Smrg 	    gfc_error ("Coindexed actual argument at %L to pointer "
3366627f7eb2Smrg 		       "dummy %qs",
3367627f7eb2Smrg 		       &a->expr->where, f->sym->name);
3368627f7eb2Smrg 	  return false;
3369627f7eb2Smrg 	}
3370627f7eb2Smrg 
3371627f7eb2Smrg       /* Fortran 2008, 12.5.2.5 (no constraint).  */
3372627f7eb2Smrg       if (a->expr->expr_type == EXPR_VARIABLE
3373627f7eb2Smrg 	  && f->sym->attr.intent != INTENT_IN
3374627f7eb2Smrg 	  && f->sym->attr.allocatable
3375627f7eb2Smrg 	  && gfc_is_coindexed (a->expr))
3376627f7eb2Smrg 	{
3377627f7eb2Smrg 	  if (where)
3378627f7eb2Smrg 	    gfc_error ("Coindexed actual argument at %L to allocatable "
3379627f7eb2Smrg 		       "dummy %qs requires INTENT(IN)",
3380627f7eb2Smrg 		       &a->expr->where, f->sym->name);
3381627f7eb2Smrg 	  return false;
3382627f7eb2Smrg 	}
3383627f7eb2Smrg 
3384627f7eb2Smrg       /* Fortran 2008, C1237.  */
3385627f7eb2Smrg       if (a->expr->expr_type == EXPR_VARIABLE
3386627f7eb2Smrg 	  && (f->sym->attr.asynchronous || f->sym->attr.volatile_)
3387627f7eb2Smrg 	  && gfc_is_coindexed (a->expr)
3388627f7eb2Smrg 	  && (a->expr->symtree->n.sym->attr.volatile_
3389627f7eb2Smrg 	      || a->expr->symtree->n.sym->attr.asynchronous))
3390627f7eb2Smrg 	{
3391627f7eb2Smrg 	  if (where)
3392627f7eb2Smrg 	    gfc_error ("Coindexed ASYNCHRONOUS or VOLATILE actual argument at "
3393627f7eb2Smrg 		       "%L requires that dummy %qs has neither "
3394627f7eb2Smrg 		       "ASYNCHRONOUS nor VOLATILE", &a->expr->where,
3395627f7eb2Smrg 		       f->sym->name);
3396627f7eb2Smrg 	  return false;
3397627f7eb2Smrg 	}
3398627f7eb2Smrg 
3399627f7eb2Smrg       /* Fortran 2008, 12.5.2.4 (no constraint).  */
3400627f7eb2Smrg       if (a->expr->expr_type == EXPR_VARIABLE
3401627f7eb2Smrg 	  && f->sym->attr.intent != INTENT_IN && !f->sym->attr.value
3402627f7eb2Smrg 	  && gfc_is_coindexed (a->expr)
3403627f7eb2Smrg 	  && gfc_has_ultimate_allocatable (a->expr))
3404627f7eb2Smrg 	{
3405627f7eb2Smrg 	  if (where)
3406627f7eb2Smrg 	    gfc_error ("Coindexed actual argument at %L with allocatable "
3407627f7eb2Smrg 		       "ultimate component to dummy %qs requires either VALUE "
3408627f7eb2Smrg 		       "or INTENT(IN)", &a->expr->where, f->sym->name);
3409627f7eb2Smrg 	  return false;
3410627f7eb2Smrg 	}
3411627f7eb2Smrg 
3412627f7eb2Smrg      if (f->sym->ts.type == BT_CLASS
3413627f7eb2Smrg 	   && CLASS_DATA (f->sym)->attr.allocatable
3414627f7eb2Smrg 	   && gfc_is_class_array_ref (a->expr, &full_array)
3415627f7eb2Smrg 	   && !full_array)
3416627f7eb2Smrg 	{
3417627f7eb2Smrg 	  if (where)
3418627f7eb2Smrg 	    gfc_error ("Actual CLASS array argument for %qs must be a full "
3419627f7eb2Smrg 		       "array at %L", f->sym->name, &a->expr->where);
3420627f7eb2Smrg 	  return false;
3421627f7eb2Smrg 	}
3422627f7eb2Smrg 
3423627f7eb2Smrg 
3424627f7eb2Smrg       if (a->expr->expr_type != EXPR_NULL
3425627f7eb2Smrg 	  && !compare_allocatable (f->sym, a->expr))
3426627f7eb2Smrg 	{
3427627f7eb2Smrg 	  if (where)
3428627f7eb2Smrg 	    gfc_error ("Actual argument for %qs must be ALLOCATABLE at %L",
3429627f7eb2Smrg 		       f->sym->name, &a->expr->where);
3430627f7eb2Smrg 	  return false;
3431627f7eb2Smrg 	}
3432627f7eb2Smrg 
3433627f7eb2Smrg       /* Check intent = OUT/INOUT for definable actual argument.  */
3434627f7eb2Smrg       if (!in_statement_function
3435627f7eb2Smrg 	  && (f->sym->attr.intent == INTENT_OUT
3436627f7eb2Smrg 	      || f->sym->attr.intent == INTENT_INOUT))
3437627f7eb2Smrg 	{
3438627f7eb2Smrg 	  const char* context = (where
3439627f7eb2Smrg 				 ? _("actual argument to INTENT = OUT/INOUT")
3440627f7eb2Smrg 				 : NULL);
3441627f7eb2Smrg 
3442627f7eb2Smrg 	  if (((f->sym->ts.type == BT_CLASS && f->sym->attr.class_ok
3443627f7eb2Smrg 		&& CLASS_DATA (f->sym)->attr.class_pointer)
3444627f7eb2Smrg 	       || (f->sym->ts.type != BT_CLASS && f->sym->attr.pointer))
3445627f7eb2Smrg 	      && !gfc_check_vardef_context (a->expr, true, false, false, context))
3446627f7eb2Smrg 	    return false;
3447627f7eb2Smrg 	  if (!gfc_check_vardef_context (a->expr, false, false, false, context))
3448627f7eb2Smrg 	    return false;
3449627f7eb2Smrg 	}
3450627f7eb2Smrg 
3451627f7eb2Smrg       if ((f->sym->attr.intent == INTENT_OUT
3452627f7eb2Smrg 	   || f->sym->attr.intent == INTENT_INOUT
3453627f7eb2Smrg 	   || f->sym->attr.volatile_
3454627f7eb2Smrg 	   || f->sym->attr.asynchronous)
3455627f7eb2Smrg 	  && gfc_has_vector_subscript (a->expr))
3456627f7eb2Smrg 	{
3457627f7eb2Smrg 	  if (where)
3458627f7eb2Smrg 	    gfc_error ("Array-section actual argument with vector "
3459627f7eb2Smrg 		       "subscripts at %L is incompatible with INTENT(OUT), "
3460627f7eb2Smrg 		       "INTENT(INOUT), VOLATILE or ASYNCHRONOUS attribute "
3461627f7eb2Smrg 		       "of the dummy argument %qs",
3462627f7eb2Smrg 		       &a->expr->where, f->sym->name);
3463627f7eb2Smrg 	  return false;
3464627f7eb2Smrg 	}
3465627f7eb2Smrg 
3466627f7eb2Smrg       /* C1232 (R1221) For an actual argument which is an array section or
3467627f7eb2Smrg 	 an assumed-shape array, the dummy argument shall be an assumed-
3468627f7eb2Smrg 	 shape array, if the dummy argument has the VOLATILE attribute.  */
3469627f7eb2Smrg 
3470627f7eb2Smrg       if (f->sym->attr.volatile_
3471627f7eb2Smrg 	  && a->expr->expr_type == EXPR_VARIABLE
3472627f7eb2Smrg 	  && a->expr->symtree->n.sym->as
3473627f7eb2Smrg 	  && a->expr->symtree->n.sym->as->type == AS_ASSUMED_SHAPE
3474627f7eb2Smrg 	  && !(f->sym->as && f->sym->as->type == AS_ASSUMED_SHAPE))
3475627f7eb2Smrg 	{
3476627f7eb2Smrg 	  if (where)
3477627f7eb2Smrg 	    gfc_error ("Assumed-shape actual argument at %L is "
3478627f7eb2Smrg 		       "incompatible with the non-assumed-shape "
3479627f7eb2Smrg 		       "dummy argument %qs due to VOLATILE attribute",
3480627f7eb2Smrg 		       &a->expr->where,f->sym->name);
3481627f7eb2Smrg 	  return false;
3482627f7eb2Smrg 	}
3483627f7eb2Smrg 
3484627f7eb2Smrg       /* Find the last array_ref.  */
3485627f7eb2Smrg       actual_arr_ref = NULL;
3486627f7eb2Smrg       if (a->expr->ref)
3487627f7eb2Smrg 	actual_arr_ref = gfc_find_array_ref (a->expr, true);
3488627f7eb2Smrg 
3489627f7eb2Smrg       if (f->sym->attr.volatile_
3490627f7eb2Smrg 	  && actual_arr_ref && actual_arr_ref->type == AR_SECTION
3491627f7eb2Smrg 	  && !(f->sym->as && f->sym->as->type == AS_ASSUMED_SHAPE))
3492627f7eb2Smrg 	{
3493627f7eb2Smrg 	  if (where)
3494627f7eb2Smrg 	    gfc_error ("Array-section actual argument at %L is "
3495627f7eb2Smrg 		       "incompatible with the non-assumed-shape "
3496627f7eb2Smrg 		       "dummy argument %qs due to VOLATILE attribute",
3497627f7eb2Smrg 		       &a->expr->where, f->sym->name);
3498627f7eb2Smrg 	  return false;
3499627f7eb2Smrg 	}
3500627f7eb2Smrg 
3501627f7eb2Smrg       /* C1233 (R1221) For an actual argument which is a pointer array, the
3502627f7eb2Smrg 	 dummy argument shall be an assumed-shape or pointer array, if the
3503627f7eb2Smrg 	 dummy argument has the VOLATILE attribute.  */
3504627f7eb2Smrg 
3505627f7eb2Smrg       if (f->sym->attr.volatile_
3506627f7eb2Smrg 	  && a->expr->expr_type == EXPR_VARIABLE
3507627f7eb2Smrg 	  && a->expr->symtree->n.sym->attr.pointer
3508627f7eb2Smrg 	  && a->expr->symtree->n.sym->as
3509627f7eb2Smrg 	  && !(f->sym->as
3510627f7eb2Smrg 	       && (f->sym->as->type == AS_ASSUMED_SHAPE
3511627f7eb2Smrg 		   || f->sym->attr.pointer)))
3512627f7eb2Smrg 	{
3513627f7eb2Smrg 	  if (where)
3514627f7eb2Smrg 	    gfc_error ("Pointer-array actual argument at %L requires "
3515627f7eb2Smrg 		       "an assumed-shape or pointer-array dummy "
3516627f7eb2Smrg 		       "argument %qs due to VOLATILE attribute",
3517627f7eb2Smrg 		       &a->expr->where,f->sym->name);
3518627f7eb2Smrg 	  return false;
3519627f7eb2Smrg 	}
3520627f7eb2Smrg 
3521627f7eb2Smrg     match:
3522627f7eb2Smrg       if (a == actual)
3523627f7eb2Smrg 	na = i;
3524627f7eb2Smrg 
3525627f7eb2Smrg       new_arg[i++] = a;
3526627f7eb2Smrg     }
3527627f7eb2Smrg 
3528627f7eb2Smrg   /* Make sure missing actual arguments are optional.  */
3529627f7eb2Smrg   i = 0;
3530627f7eb2Smrg   for (f = formal; f; f = f->next, i++)
3531627f7eb2Smrg     {
3532627f7eb2Smrg       if (new_arg[i] != NULL)
3533627f7eb2Smrg 	continue;
3534627f7eb2Smrg       if (f->sym == NULL)
3535627f7eb2Smrg 	{
3536627f7eb2Smrg 	  if (where)
3537627f7eb2Smrg 	    gfc_error ("Missing alternate return spec in subroutine call "
3538627f7eb2Smrg 		       "at %L", where);
3539627f7eb2Smrg 	  return false;
3540627f7eb2Smrg 	}
3541627f7eb2Smrg       if (!f->sym->attr.optional
3542627f7eb2Smrg 	  || (in_statement_function && f->sym->attr.optional))
3543627f7eb2Smrg 	{
3544627f7eb2Smrg 	  if (where)
3545627f7eb2Smrg 	    gfc_error ("Missing actual argument for argument %qs at %L",
3546627f7eb2Smrg 		       f->sym->name, where);
3547627f7eb2Smrg 	  return false;
3548627f7eb2Smrg 	}
3549627f7eb2Smrg     }
3550627f7eb2Smrg 
3551627f7eb2Smrg   /* The argument lists are compatible.  We now relink a new actual
3552627f7eb2Smrg      argument list with null arguments in the right places.  The head
3553627f7eb2Smrg      of the list remains the head.  */
3554627f7eb2Smrg   for (i = 0; i < n; i++)
3555627f7eb2Smrg     if (new_arg[i] == NULL)
3556627f7eb2Smrg       new_arg[i] = gfc_get_actual_arglist ();
3557627f7eb2Smrg 
3558627f7eb2Smrg   if (na != 0)
3559627f7eb2Smrg     {
3560627f7eb2Smrg       std::swap (*new_arg[0], *actual);
3561627f7eb2Smrg       std::swap (new_arg[0], new_arg[na]);
3562627f7eb2Smrg     }
3563627f7eb2Smrg 
3564627f7eb2Smrg   for (i = 0; i < n - 1; i++)
3565627f7eb2Smrg     new_arg[i]->next = new_arg[i + 1];
3566627f7eb2Smrg 
3567627f7eb2Smrg   new_arg[i]->next = NULL;
3568627f7eb2Smrg 
3569627f7eb2Smrg   if (*ap == NULL && n > 0)
3570627f7eb2Smrg     *ap = new_arg[0];
3571627f7eb2Smrg 
3572627f7eb2Smrg   /* Note the types of omitted optional arguments.  */
3573627f7eb2Smrg   for (a = *ap, f = formal; a; a = a->next, f = f->next)
3574627f7eb2Smrg     if (a->expr == NULL && a->label == NULL)
3575627f7eb2Smrg       a->missing_arg_type = f->sym->ts.type;
3576627f7eb2Smrg 
3577627f7eb2Smrg   return true;
3578627f7eb2Smrg }
3579627f7eb2Smrg 
3580627f7eb2Smrg 
3581627f7eb2Smrg typedef struct
3582627f7eb2Smrg {
3583627f7eb2Smrg   gfc_formal_arglist *f;
3584627f7eb2Smrg   gfc_actual_arglist *a;
3585627f7eb2Smrg }
3586627f7eb2Smrg argpair;
3587627f7eb2Smrg 
3588627f7eb2Smrg /* qsort comparison function for argument pairs, with the following
3589627f7eb2Smrg    order:
3590627f7eb2Smrg     - p->a->expr == NULL
3591627f7eb2Smrg     - p->a->expr->expr_type != EXPR_VARIABLE
3592627f7eb2Smrg     - by gfc_symbol pointer value (larger first).  */
3593627f7eb2Smrg 
3594627f7eb2Smrg static int
pair_cmp(const void * p1,const void * p2)3595627f7eb2Smrg pair_cmp (const void *p1, const void *p2)
3596627f7eb2Smrg {
3597627f7eb2Smrg   const gfc_actual_arglist *a1, *a2;
3598627f7eb2Smrg 
3599627f7eb2Smrg   /* *p1 and *p2 are elements of the to-be-sorted array.  */
3600627f7eb2Smrg   a1 = ((const argpair *) p1)->a;
3601627f7eb2Smrg   a2 = ((const argpair *) p2)->a;
3602627f7eb2Smrg   if (!a1->expr)
3603627f7eb2Smrg     {
3604627f7eb2Smrg       if (!a2->expr)
3605627f7eb2Smrg 	return 0;
3606627f7eb2Smrg       return -1;
3607627f7eb2Smrg     }
3608627f7eb2Smrg   if (!a2->expr)
3609627f7eb2Smrg     return 1;
3610627f7eb2Smrg   if (a1->expr->expr_type != EXPR_VARIABLE)
3611627f7eb2Smrg     {
3612627f7eb2Smrg       if (a2->expr->expr_type != EXPR_VARIABLE)
3613627f7eb2Smrg 	return 0;
3614627f7eb2Smrg       return -1;
3615627f7eb2Smrg     }
3616627f7eb2Smrg   if (a2->expr->expr_type != EXPR_VARIABLE)
3617627f7eb2Smrg     return 1;
3618627f7eb2Smrg   if (a1->expr->symtree->n.sym > a2->expr->symtree->n.sym)
3619627f7eb2Smrg     return -1;
3620627f7eb2Smrg   return a1->expr->symtree->n.sym < a2->expr->symtree->n.sym;
3621627f7eb2Smrg }
3622627f7eb2Smrg 
3623627f7eb2Smrg 
3624627f7eb2Smrg /* Given two expressions from some actual arguments, test whether they
3625627f7eb2Smrg    refer to the same expression. The analysis is conservative.
3626627f7eb2Smrg    Returning false will produce no warning.  */
3627627f7eb2Smrg 
3628627f7eb2Smrg static bool
compare_actual_expr(gfc_expr * e1,gfc_expr * e2)3629627f7eb2Smrg compare_actual_expr (gfc_expr *e1, gfc_expr *e2)
3630627f7eb2Smrg {
3631627f7eb2Smrg   const gfc_ref *r1, *r2;
3632627f7eb2Smrg 
3633627f7eb2Smrg   if (!e1 || !e2
3634627f7eb2Smrg       || e1->expr_type != EXPR_VARIABLE
3635627f7eb2Smrg       || e2->expr_type != EXPR_VARIABLE
3636627f7eb2Smrg       || e1->symtree->n.sym != e2->symtree->n.sym)
3637627f7eb2Smrg     return false;
3638627f7eb2Smrg 
3639627f7eb2Smrg   /* TODO: improve comparison, see expr.c:show_ref().  */
3640627f7eb2Smrg   for (r1 = e1->ref, r2 = e2->ref; r1 && r2; r1 = r1->next, r2 = r2->next)
3641627f7eb2Smrg     {
3642627f7eb2Smrg       if (r1->type != r2->type)
3643627f7eb2Smrg 	return false;
3644627f7eb2Smrg       switch (r1->type)
3645627f7eb2Smrg 	{
3646627f7eb2Smrg 	case REF_ARRAY:
3647627f7eb2Smrg 	  if (r1->u.ar.type != r2->u.ar.type)
3648627f7eb2Smrg 	    return false;
3649627f7eb2Smrg 	  /* TODO: At the moment, consider only full arrays;
3650627f7eb2Smrg 	     we could do better.  */
3651627f7eb2Smrg 	  if (r1->u.ar.type != AR_FULL || r2->u.ar.type != AR_FULL)
3652627f7eb2Smrg 	    return false;
3653627f7eb2Smrg 	  break;
3654627f7eb2Smrg 
3655627f7eb2Smrg 	case REF_COMPONENT:
3656627f7eb2Smrg 	  if (r1->u.c.component != r2->u.c.component)
3657627f7eb2Smrg 	    return false;
3658627f7eb2Smrg 	  break;
3659627f7eb2Smrg 
3660627f7eb2Smrg 	case REF_SUBSTRING:
3661627f7eb2Smrg 	  return false;
3662627f7eb2Smrg 
3663627f7eb2Smrg 	case REF_INQUIRY:
3664627f7eb2Smrg 	  if (e1->symtree->n.sym->ts.type == BT_COMPLEX
3665627f7eb2Smrg 	      && e1->ts.type == BT_REAL && e2->ts.type == BT_REAL
3666627f7eb2Smrg 	      && r1->u.i != r2->u.i)
3667627f7eb2Smrg 	    return false;
3668627f7eb2Smrg 	  break;
3669627f7eb2Smrg 
3670627f7eb2Smrg 	default:
3671627f7eb2Smrg 	  gfc_internal_error ("compare_actual_expr(): Bad component code");
3672627f7eb2Smrg 	}
3673627f7eb2Smrg     }
3674627f7eb2Smrg   if (!r1 && !r2)
3675627f7eb2Smrg     return true;
3676627f7eb2Smrg   return false;
3677627f7eb2Smrg }
3678627f7eb2Smrg 
3679627f7eb2Smrg 
3680627f7eb2Smrg /* Given formal and actual argument lists that correspond to one
3681627f7eb2Smrg    another, check that identical actual arguments aren't not
3682627f7eb2Smrg    associated with some incompatible INTENTs.  */
3683627f7eb2Smrg 
3684627f7eb2Smrg static bool
check_some_aliasing(gfc_formal_arglist * f,gfc_actual_arglist * a)3685627f7eb2Smrg check_some_aliasing (gfc_formal_arglist *f, gfc_actual_arglist *a)
3686627f7eb2Smrg {
3687627f7eb2Smrg   sym_intent f1_intent, f2_intent;
3688627f7eb2Smrg   gfc_formal_arglist *f1;
3689627f7eb2Smrg   gfc_actual_arglist *a1;
3690627f7eb2Smrg   size_t n, i, j;
3691627f7eb2Smrg   argpair *p;
3692627f7eb2Smrg   bool t = true;
3693627f7eb2Smrg 
3694627f7eb2Smrg   n = 0;
3695627f7eb2Smrg   for (f1 = f, a1 = a;; f1 = f1->next, a1 = a1->next)
3696627f7eb2Smrg     {
3697627f7eb2Smrg       if (f1 == NULL && a1 == NULL)
3698627f7eb2Smrg 	break;
3699627f7eb2Smrg       if (f1 == NULL || a1 == NULL)
3700627f7eb2Smrg 	gfc_internal_error ("check_some_aliasing(): List mismatch");
3701627f7eb2Smrg       n++;
3702627f7eb2Smrg     }
3703627f7eb2Smrg   if (n == 0)
3704627f7eb2Smrg     return t;
3705627f7eb2Smrg   p = XALLOCAVEC (argpair, n);
3706627f7eb2Smrg 
3707627f7eb2Smrg   for (i = 0, f1 = f, a1 = a; i < n; i++, f1 = f1->next, a1 = a1->next)
3708627f7eb2Smrg     {
3709627f7eb2Smrg       p[i].f = f1;
3710627f7eb2Smrg       p[i].a = a1;
3711627f7eb2Smrg     }
3712627f7eb2Smrg 
3713627f7eb2Smrg   qsort (p, n, sizeof (argpair), pair_cmp);
3714627f7eb2Smrg 
3715627f7eb2Smrg   for (i = 0; i < n; i++)
3716627f7eb2Smrg     {
3717627f7eb2Smrg       if (!p[i].a->expr
3718627f7eb2Smrg 	  || p[i].a->expr->expr_type != EXPR_VARIABLE
3719627f7eb2Smrg 	  || p[i].a->expr->ts.type == BT_PROCEDURE)
3720627f7eb2Smrg 	continue;
3721627f7eb2Smrg       f1_intent = p[i].f->sym->attr.intent;
3722627f7eb2Smrg       for (j = i + 1; j < n; j++)
3723627f7eb2Smrg 	{
3724627f7eb2Smrg 	  /* Expected order after the sort.  */
3725627f7eb2Smrg 	  if (!p[j].a->expr || p[j].a->expr->expr_type != EXPR_VARIABLE)
3726627f7eb2Smrg 	    gfc_internal_error ("check_some_aliasing(): corrupted data");
3727627f7eb2Smrg 
3728627f7eb2Smrg 	  /* Are the expression the same?  */
3729627f7eb2Smrg 	  if (!compare_actual_expr (p[i].a->expr, p[j].a->expr))
3730627f7eb2Smrg 	    break;
3731627f7eb2Smrg 	  f2_intent = p[j].f->sym->attr.intent;
3732627f7eb2Smrg 	  if ((f1_intent == INTENT_IN && f2_intent == INTENT_OUT)
3733627f7eb2Smrg 	      || (f1_intent == INTENT_OUT && f2_intent == INTENT_IN)
3734627f7eb2Smrg 	      || (f1_intent == INTENT_OUT && f2_intent == INTENT_OUT))
3735627f7eb2Smrg 	    {
3736627f7eb2Smrg 	      gfc_warning (0, "Same actual argument associated with INTENT(%s) "
3737627f7eb2Smrg 			   "argument %qs and INTENT(%s) argument %qs at %L",
3738627f7eb2Smrg 			   gfc_intent_string (f1_intent), p[i].f->sym->name,
3739627f7eb2Smrg 			   gfc_intent_string (f2_intent), p[j].f->sym->name,
3740627f7eb2Smrg 			   &p[i].a->expr->where);
3741627f7eb2Smrg 	      t = false;
3742627f7eb2Smrg 	    }
3743627f7eb2Smrg 	}
3744627f7eb2Smrg     }
3745627f7eb2Smrg 
3746627f7eb2Smrg   return t;
3747627f7eb2Smrg }
3748627f7eb2Smrg 
3749627f7eb2Smrg 
3750627f7eb2Smrg /* Given formal and actual argument lists that correspond to one
3751627f7eb2Smrg    another, check that they are compatible in the sense that intents
3752627f7eb2Smrg    are not mismatched.  */
3753627f7eb2Smrg 
3754627f7eb2Smrg static bool
check_intents(gfc_formal_arglist * f,gfc_actual_arglist * a)3755627f7eb2Smrg check_intents (gfc_formal_arglist *f, gfc_actual_arglist *a)
3756627f7eb2Smrg {
3757627f7eb2Smrg   sym_intent f_intent;
3758627f7eb2Smrg 
3759627f7eb2Smrg   for (;; f = f->next, a = a->next)
3760627f7eb2Smrg     {
3761627f7eb2Smrg       gfc_expr *expr;
3762627f7eb2Smrg 
3763627f7eb2Smrg       if (f == NULL && a == NULL)
3764627f7eb2Smrg 	break;
3765627f7eb2Smrg       if (f == NULL || a == NULL)
3766627f7eb2Smrg 	gfc_internal_error ("check_intents(): List mismatch");
3767627f7eb2Smrg 
3768627f7eb2Smrg       if (a->expr && a->expr->expr_type == EXPR_FUNCTION
3769627f7eb2Smrg 	  && a->expr->value.function.isym
3770627f7eb2Smrg 	  && a->expr->value.function.isym->id == GFC_ISYM_CAF_GET)
3771627f7eb2Smrg 	expr = a->expr->value.function.actual->expr;
3772627f7eb2Smrg       else
3773627f7eb2Smrg 	expr = a->expr;
3774627f7eb2Smrg 
3775627f7eb2Smrg       if (expr == NULL || expr->expr_type != EXPR_VARIABLE)
3776627f7eb2Smrg 	continue;
3777627f7eb2Smrg 
3778627f7eb2Smrg       f_intent = f->sym->attr.intent;
3779627f7eb2Smrg 
3780627f7eb2Smrg       if (gfc_pure (NULL) && gfc_impure_variable (expr->symtree->n.sym))
3781627f7eb2Smrg 	{
3782627f7eb2Smrg 	  if ((f->sym->ts.type == BT_CLASS && f->sym->attr.class_ok
3783627f7eb2Smrg 	       && CLASS_DATA (f->sym)->attr.class_pointer)
3784627f7eb2Smrg 	      || (f->sym->ts.type != BT_CLASS && f->sym->attr.pointer))
3785627f7eb2Smrg 	    {
3786627f7eb2Smrg 	      gfc_error ("Procedure argument at %L is local to a PURE "
3787627f7eb2Smrg 			 "procedure and has the POINTER attribute",
3788627f7eb2Smrg 			 &expr->where);
3789627f7eb2Smrg 	      return false;
3790627f7eb2Smrg 	    }
3791627f7eb2Smrg 	}
3792627f7eb2Smrg 
3793627f7eb2Smrg        /* Fortran 2008, C1283.  */
3794627f7eb2Smrg        if (gfc_pure (NULL) && gfc_is_coindexed (expr))
3795627f7eb2Smrg 	{
3796627f7eb2Smrg 	  if (f_intent == INTENT_INOUT || f_intent == INTENT_OUT)
3797627f7eb2Smrg 	    {
3798627f7eb2Smrg 	      gfc_error ("Coindexed actual argument at %L in PURE procedure "
3799627f7eb2Smrg 			 "is passed to an INTENT(%s) argument",
3800627f7eb2Smrg 			 &expr->where, gfc_intent_string (f_intent));
3801627f7eb2Smrg 	      return false;
3802627f7eb2Smrg 	    }
3803627f7eb2Smrg 
3804627f7eb2Smrg 	  if ((f->sym->ts.type == BT_CLASS && f->sym->attr.class_ok
3805627f7eb2Smrg                && CLASS_DATA (f->sym)->attr.class_pointer)
3806627f7eb2Smrg               || (f->sym->ts.type != BT_CLASS && f->sym->attr.pointer))
3807627f7eb2Smrg 	    {
3808627f7eb2Smrg 	      gfc_error ("Coindexed actual argument at %L in PURE procedure "
3809627f7eb2Smrg 			 "is passed to a POINTER dummy argument",
3810627f7eb2Smrg 			 &expr->where);
3811627f7eb2Smrg 	      return false;
3812627f7eb2Smrg 	    }
3813627f7eb2Smrg 	}
3814627f7eb2Smrg 
3815627f7eb2Smrg        /* F2008, Section 12.5.2.4.  */
3816627f7eb2Smrg        if (expr->ts.type == BT_CLASS && f->sym->ts.type == BT_CLASS
3817627f7eb2Smrg 	   && gfc_is_coindexed (expr))
3818627f7eb2Smrg 	 {
3819627f7eb2Smrg 	   gfc_error ("Coindexed polymorphic actual argument at %L is passed "
3820627f7eb2Smrg 		      "polymorphic dummy argument %qs",
3821627f7eb2Smrg 			 &expr->where, f->sym->name);
3822627f7eb2Smrg 	   return false;
3823627f7eb2Smrg 	 }
3824627f7eb2Smrg     }
3825627f7eb2Smrg 
3826627f7eb2Smrg   return true;
3827627f7eb2Smrg }
3828627f7eb2Smrg 
3829627f7eb2Smrg 
3830627f7eb2Smrg /* Check how a procedure is used against its interface.  If all goes
3831627f7eb2Smrg    well, the actual argument list will also end up being properly
3832627f7eb2Smrg    sorted.  */
3833627f7eb2Smrg 
3834627f7eb2Smrg bool
gfc_procedure_use(gfc_symbol * sym,gfc_actual_arglist ** ap,locus * where)3835627f7eb2Smrg gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
3836627f7eb2Smrg {
3837627f7eb2Smrg   gfc_actual_arglist *a;
3838627f7eb2Smrg   gfc_formal_arglist *dummy_args;
38394c3eb207Smrg   bool implicit = false;
3840627f7eb2Smrg 
3841627f7eb2Smrg   /* Warn about calls with an implicit interface.  Special case
3842627f7eb2Smrg      for calling a ISO_C_BINDING because c_loc and c_funloc
3843627f7eb2Smrg      are pseudo-unknown.  Additionally, warn about procedures not
3844627f7eb2Smrg      explicitly declared at all if requested.  */
3845627f7eb2Smrg   if (sym->attr.if_source == IFSRC_UNKNOWN && !sym->attr.is_iso_c)
3846627f7eb2Smrg     {
3847627f7eb2Smrg       bool has_implicit_none_export = false;
38484c3eb207Smrg       implicit = true;
3849627f7eb2Smrg       if (sym->attr.proc == PROC_UNKNOWN)
3850627f7eb2Smrg 	for (gfc_namespace *ns = sym->ns; ns; ns = ns->parent)
3851627f7eb2Smrg 	  if (ns->has_implicit_none_export)
38524c3eb207Smrg 	    {
3853627f7eb2Smrg 	      has_implicit_none_export = true;
38544c3eb207Smrg 	      break;
38554c3eb207Smrg 	    }
3856627f7eb2Smrg       if (has_implicit_none_export)
3857627f7eb2Smrg 	{
3858627f7eb2Smrg 	  const char *guessed
3859627f7eb2Smrg 	    = gfc_lookup_function_fuzzy (sym->name, sym->ns->sym_root);
3860627f7eb2Smrg 	  if (guessed)
3861627f7eb2Smrg 	    gfc_error ("Procedure %qs called at %L is not explicitly declared"
3862627f7eb2Smrg 		       "; did you mean %qs?",
3863627f7eb2Smrg 		       sym->name, where, guessed);
3864627f7eb2Smrg 	  else
3865627f7eb2Smrg 	    gfc_error ("Procedure %qs called at %L is not explicitly declared",
3866627f7eb2Smrg 		       sym->name, where);
3867627f7eb2Smrg 	  return false;
3868627f7eb2Smrg 	}
3869627f7eb2Smrg       if (warn_implicit_interface)
3870627f7eb2Smrg 	gfc_warning (OPT_Wimplicit_interface,
3871627f7eb2Smrg 		     "Procedure %qs called with an implicit interface at %L",
3872627f7eb2Smrg 		     sym->name, where);
3873627f7eb2Smrg       else if (warn_implicit_procedure && sym->attr.proc == PROC_UNKNOWN)
3874627f7eb2Smrg 	gfc_warning (OPT_Wimplicit_procedure,
3875627f7eb2Smrg 		     "Procedure %qs called at %L is not explicitly declared",
3876627f7eb2Smrg 		     sym->name, where);
3877627f7eb2Smrg       gfc_find_proc_namespace (sym->ns)->implicit_interface_calls = 1;
3878627f7eb2Smrg     }
3879627f7eb2Smrg 
3880627f7eb2Smrg   if (sym->attr.if_source == IFSRC_UNKNOWN)
3881627f7eb2Smrg     {
3882627f7eb2Smrg       if (sym->attr.pointer)
3883627f7eb2Smrg 	{
3884627f7eb2Smrg 	  gfc_error ("The pointer object %qs at %L must have an explicit "
3885627f7eb2Smrg 		     "function interface or be declared as array",
3886627f7eb2Smrg 		     sym->name, where);
3887627f7eb2Smrg 	  return false;
3888627f7eb2Smrg 	}
3889627f7eb2Smrg 
3890627f7eb2Smrg       if (sym->attr.allocatable && !sym->attr.external)
3891627f7eb2Smrg 	{
3892627f7eb2Smrg 	  gfc_error ("The allocatable object %qs at %L must have an explicit "
3893627f7eb2Smrg 		     "function interface or be declared as array",
3894627f7eb2Smrg 		     sym->name, where);
3895627f7eb2Smrg 	  return false;
3896627f7eb2Smrg 	}
3897627f7eb2Smrg 
3898627f7eb2Smrg       if (sym->attr.allocatable)
3899627f7eb2Smrg 	{
3900627f7eb2Smrg 	  gfc_error ("Allocatable function %qs at %L must have an explicit "
3901627f7eb2Smrg 		     "function interface", sym->name, where);
3902627f7eb2Smrg 	  return false;
3903627f7eb2Smrg 	}
3904627f7eb2Smrg 
3905627f7eb2Smrg       for (a = *ap; a; a = a->next)
3906627f7eb2Smrg 	{
39074c3eb207Smrg 	  if (a->expr && a->expr->error)
39084c3eb207Smrg 	    return false;
39094c3eb207Smrg 
39104c3eb207Smrg 	  /* F2018, 15.4.2.2 Explicit interface is required for a
39114c3eb207Smrg 	     polymorphic dummy argument, so there is no way to
39124c3eb207Smrg 	     legally have a class appear in an argument with an
39134c3eb207Smrg 	     implicit interface.  */
39144c3eb207Smrg 
39154c3eb207Smrg 	  if (implicit && a->expr && a->expr->ts.type == BT_CLASS)
39164c3eb207Smrg 	    {
39174c3eb207Smrg 	      gfc_error ("Explicit interface required for polymorphic "
39184c3eb207Smrg 			 "argument at %L",&a->expr->where);
39194c3eb207Smrg 	      a->expr->error = 1;
39204c3eb207Smrg 	      break;
39214c3eb207Smrg 	    }
39224c3eb207Smrg 
3923627f7eb2Smrg 	  /* Skip g77 keyword extensions like %VAL, %REF, %LOC.  */
3924627f7eb2Smrg 	  if (a->name != NULL && a->name[0] != '%')
3925627f7eb2Smrg 	    {
3926627f7eb2Smrg 	      gfc_error ("Keyword argument requires explicit interface "
3927627f7eb2Smrg 			 "for procedure %qs at %L", sym->name, &a->expr->where);
3928627f7eb2Smrg 	      break;
3929627f7eb2Smrg 	    }
3930627f7eb2Smrg 
3931627f7eb2Smrg 	  /* TS 29113, 6.2.  */
3932627f7eb2Smrg 	  if (a->expr && a->expr->ts.type == BT_ASSUMED
3933627f7eb2Smrg 	      && sym->intmod_sym_id != ISOCBINDING_LOC)
3934627f7eb2Smrg 	    {
3935627f7eb2Smrg 	      gfc_error ("Assumed-type argument %s at %L requires an explicit "
3936627f7eb2Smrg 			 "interface", a->expr->symtree->n.sym->name,
3937627f7eb2Smrg 			 &a->expr->where);
39384c3eb207Smrg 	      a->expr->error = 1;
3939627f7eb2Smrg 	      break;
3940627f7eb2Smrg 	    }
3941627f7eb2Smrg 
3942627f7eb2Smrg 	  /* F2008, C1303 and C1304.  */
3943627f7eb2Smrg 	  if (a->expr
3944627f7eb2Smrg 	      && (a->expr->ts.type == BT_DERIVED || a->expr->ts.type == BT_CLASS)
39454c3eb207Smrg 	      && a->expr->ts.u.derived
3946627f7eb2Smrg 	      && ((a->expr->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
3947627f7eb2Smrg 		   && a->expr->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE)
3948627f7eb2Smrg 		  || gfc_expr_attr (a->expr).lock_comp))
3949627f7eb2Smrg 	    {
3950627f7eb2Smrg 	      gfc_error ("Actual argument of LOCK_TYPE or with LOCK_TYPE "
3951627f7eb2Smrg 			 "component at %L requires an explicit interface for "
3952627f7eb2Smrg 			 "procedure %qs", &a->expr->where, sym->name);
39534c3eb207Smrg 	      a->expr->error = 1;
3954627f7eb2Smrg 	      break;
3955627f7eb2Smrg 	    }
3956627f7eb2Smrg 
3957627f7eb2Smrg 	  if (a->expr
3958627f7eb2Smrg 	      && (a->expr->ts.type == BT_DERIVED || a->expr->ts.type == BT_CLASS)
39594c3eb207Smrg 	      && a->expr->ts.u.derived
3960627f7eb2Smrg 	      && ((a->expr->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV
3961627f7eb2Smrg 		   && a->expr->ts.u.derived->intmod_sym_id
3962627f7eb2Smrg 		      == ISOFORTRAN_EVENT_TYPE)
3963627f7eb2Smrg 		  || gfc_expr_attr (a->expr).event_comp))
3964627f7eb2Smrg 	    {
3965627f7eb2Smrg 	      gfc_error ("Actual argument of EVENT_TYPE or with EVENT_TYPE "
3966627f7eb2Smrg 			 "component at %L requires an explicit interface for "
3967627f7eb2Smrg 			 "procedure %qs", &a->expr->where, sym->name);
39684c3eb207Smrg 	      a->expr->error = 1;
3969627f7eb2Smrg 	      break;
3970627f7eb2Smrg 	    }
3971627f7eb2Smrg 
3972627f7eb2Smrg 	  if (a->expr && a->expr->expr_type == EXPR_NULL
3973627f7eb2Smrg 	      && a->expr->ts.type == BT_UNKNOWN)
3974627f7eb2Smrg 	    {
39754c3eb207Smrg 	      gfc_error ("MOLD argument to NULL required at %L",
39764c3eb207Smrg 			 &a->expr->where);
39774c3eb207Smrg 	      a->expr->error = 1;
3978627f7eb2Smrg 	      return false;
3979627f7eb2Smrg 	    }
3980627f7eb2Smrg 
3981*4ac76180Smrg 	  if (a->expr && a->expr->expr_type == EXPR_NULL)
3982*4ac76180Smrg 	    {
3983*4ac76180Smrg 	      gfc_error ("Passing intrinsic NULL as actual argument at %L "
3984*4ac76180Smrg 			 "requires an explicit interface", &a->expr->where);
3985*4ac76180Smrg 	      a->expr->error = 1;
3986*4ac76180Smrg 	      return false;
3987*4ac76180Smrg 	    }
3988*4ac76180Smrg 
3989627f7eb2Smrg 	  /* TS 29113, C407b.  */
3990627f7eb2Smrg 	  if (a->expr && a->expr->expr_type == EXPR_VARIABLE
3991627f7eb2Smrg 	      && symbol_rank (a->expr->symtree->n.sym) == -1)
3992627f7eb2Smrg 	    {
3993627f7eb2Smrg 	      gfc_error ("Assumed-rank argument requires an explicit interface "
3994627f7eb2Smrg 			 "at %L", &a->expr->where);
39954c3eb207Smrg 	      a->expr->error = 1;
3996627f7eb2Smrg 	      return false;
3997627f7eb2Smrg 	    }
3998627f7eb2Smrg 	}
3999627f7eb2Smrg 
4000627f7eb2Smrg       return true;
4001627f7eb2Smrg     }
4002627f7eb2Smrg 
4003627f7eb2Smrg   dummy_args = gfc_sym_get_dummy_args (sym);
4004627f7eb2Smrg 
4005627f7eb2Smrg   /* For a statement function, check that types and type parameters of actual
4006627f7eb2Smrg      arguments and dummy arguments match.  */
40074c3eb207Smrg   if (!gfc_compare_actual_formal (ap, dummy_args, 0, sym->attr.elemental,
4008627f7eb2Smrg 				  sym->attr.proc == PROC_ST_FUNCTION, where))
4009627f7eb2Smrg     return false;
4010627f7eb2Smrg 
4011627f7eb2Smrg   if (!check_intents (dummy_args, *ap))
4012627f7eb2Smrg     return false;
4013627f7eb2Smrg 
4014627f7eb2Smrg   if (warn_aliasing)
4015627f7eb2Smrg     check_some_aliasing (dummy_args, *ap);
4016627f7eb2Smrg 
4017627f7eb2Smrg   return true;
4018627f7eb2Smrg }
4019627f7eb2Smrg 
4020627f7eb2Smrg 
4021627f7eb2Smrg /* Check how a procedure pointer component is used against its interface.
4022627f7eb2Smrg    If all goes well, the actual argument list will also end up being properly
4023627f7eb2Smrg    sorted. Completely analogous to gfc_procedure_use.  */
4024627f7eb2Smrg 
4025627f7eb2Smrg void
gfc_ppc_use(gfc_component * comp,gfc_actual_arglist ** ap,locus * where)4026627f7eb2Smrg gfc_ppc_use (gfc_component *comp, gfc_actual_arglist **ap, locus *where)
4027627f7eb2Smrg {
4028627f7eb2Smrg   /* Warn about calls with an implicit interface.  Special case
4029627f7eb2Smrg      for calling a ISO_C_BINDING because c_loc and c_funloc
4030627f7eb2Smrg      are pseudo-unknown.  */
4031627f7eb2Smrg   if (warn_implicit_interface
4032627f7eb2Smrg       && comp->attr.if_source == IFSRC_UNKNOWN
4033627f7eb2Smrg       && !comp->attr.is_iso_c)
4034627f7eb2Smrg     gfc_warning (OPT_Wimplicit_interface,
4035627f7eb2Smrg 		 "Procedure pointer component %qs called with an implicit "
4036627f7eb2Smrg 		 "interface at %L", comp->name, where);
4037627f7eb2Smrg 
4038627f7eb2Smrg   if (comp->attr.if_source == IFSRC_UNKNOWN)
4039627f7eb2Smrg     {
4040627f7eb2Smrg       gfc_actual_arglist *a;
4041627f7eb2Smrg       for (a = *ap; a; a = a->next)
4042627f7eb2Smrg 	{
4043627f7eb2Smrg 	  /* Skip g77 keyword extensions like %VAL, %REF, %LOC.  */
4044627f7eb2Smrg 	  if (a->name != NULL && a->name[0] != '%')
4045627f7eb2Smrg 	    {
4046627f7eb2Smrg 	      gfc_error ("Keyword argument requires explicit interface "
4047627f7eb2Smrg 			 "for procedure pointer component %qs at %L",
4048627f7eb2Smrg 			 comp->name, &a->expr->where);
4049627f7eb2Smrg 	      break;
4050627f7eb2Smrg 	    }
4051627f7eb2Smrg 	}
4052627f7eb2Smrg 
4053627f7eb2Smrg       return;
4054627f7eb2Smrg     }
4055627f7eb2Smrg 
40564c3eb207Smrg   if (!gfc_compare_actual_formal (ap, comp->ts.interface->formal, 0,
4057627f7eb2Smrg 			      comp->attr.elemental, false, where))
4058627f7eb2Smrg     return;
4059627f7eb2Smrg 
4060627f7eb2Smrg   check_intents (comp->ts.interface->formal, *ap);
4061627f7eb2Smrg   if (warn_aliasing)
4062627f7eb2Smrg     check_some_aliasing (comp->ts.interface->formal, *ap);
4063627f7eb2Smrg }
4064627f7eb2Smrg 
4065627f7eb2Smrg 
4066627f7eb2Smrg /* Try if an actual argument list matches the formal list of a symbol,
4067627f7eb2Smrg    respecting the symbol's attributes like ELEMENTAL.  This is used for
4068627f7eb2Smrg    GENERIC resolution.  */
4069627f7eb2Smrg 
4070627f7eb2Smrg bool
gfc_arglist_matches_symbol(gfc_actual_arglist ** args,gfc_symbol * sym)4071627f7eb2Smrg gfc_arglist_matches_symbol (gfc_actual_arglist** args, gfc_symbol* sym)
4072627f7eb2Smrg {
4073627f7eb2Smrg   gfc_formal_arglist *dummy_args;
4074627f7eb2Smrg   bool r;
4075627f7eb2Smrg 
4076627f7eb2Smrg   if (sym->attr.flavor != FL_PROCEDURE)
4077627f7eb2Smrg     return false;
4078627f7eb2Smrg 
4079627f7eb2Smrg   dummy_args = gfc_sym_get_dummy_args (sym);
4080627f7eb2Smrg 
4081627f7eb2Smrg   r = !sym->attr.elemental;
40824c3eb207Smrg   if (gfc_compare_actual_formal (args, dummy_args, r, !r, false, NULL))
4083627f7eb2Smrg     {
4084627f7eb2Smrg       check_intents (dummy_args, *args);
4085627f7eb2Smrg       if (warn_aliasing)
4086627f7eb2Smrg 	check_some_aliasing (dummy_args, *args);
4087627f7eb2Smrg       return true;
4088627f7eb2Smrg     }
4089627f7eb2Smrg 
4090627f7eb2Smrg   return false;
4091627f7eb2Smrg }
4092627f7eb2Smrg 
4093627f7eb2Smrg 
4094627f7eb2Smrg /* Given an interface pointer and an actual argument list, search for
4095627f7eb2Smrg    a formal argument list that matches the actual.  If found, returns
4096627f7eb2Smrg    a pointer to the symbol of the correct interface.  Returns NULL if
4097627f7eb2Smrg    not found.  */
4098627f7eb2Smrg 
4099627f7eb2Smrg gfc_symbol *
gfc_search_interface(gfc_interface * intr,int sub_flag,gfc_actual_arglist ** ap)4100627f7eb2Smrg gfc_search_interface (gfc_interface *intr, int sub_flag,
4101627f7eb2Smrg 		      gfc_actual_arglist **ap)
4102627f7eb2Smrg {
4103627f7eb2Smrg   gfc_symbol *elem_sym = NULL;
4104627f7eb2Smrg   gfc_symbol *null_sym = NULL;
4105627f7eb2Smrg   locus null_expr_loc;
4106627f7eb2Smrg   gfc_actual_arglist *a;
4107627f7eb2Smrg   bool has_null_arg = false;
4108627f7eb2Smrg 
4109627f7eb2Smrg   for (a = *ap; a; a = a->next)
4110627f7eb2Smrg     if (a->expr && a->expr->expr_type == EXPR_NULL
4111627f7eb2Smrg 	&& a->expr->ts.type == BT_UNKNOWN)
4112627f7eb2Smrg       {
4113627f7eb2Smrg 	has_null_arg = true;
4114627f7eb2Smrg 	null_expr_loc = a->expr->where;
4115627f7eb2Smrg 	break;
4116627f7eb2Smrg       }
4117627f7eb2Smrg 
4118627f7eb2Smrg   for (; intr; intr = intr->next)
4119627f7eb2Smrg     {
4120627f7eb2Smrg       if (gfc_fl_struct (intr->sym->attr.flavor))
4121627f7eb2Smrg 	continue;
4122627f7eb2Smrg       if (sub_flag && intr->sym->attr.function)
4123627f7eb2Smrg 	continue;
4124627f7eb2Smrg       if (!sub_flag && intr->sym->attr.subroutine)
4125627f7eb2Smrg 	continue;
4126627f7eb2Smrg 
4127627f7eb2Smrg       if (gfc_arglist_matches_symbol (ap, intr->sym))
4128627f7eb2Smrg 	{
4129627f7eb2Smrg 	  if (has_null_arg && null_sym)
4130627f7eb2Smrg 	    {
4131627f7eb2Smrg 	      gfc_error ("MOLD= required in NULL() argument at %L: Ambiguity "
4132627f7eb2Smrg 			 "between specific functions %s and %s",
4133627f7eb2Smrg 			 &null_expr_loc, null_sym->name, intr->sym->name);
4134627f7eb2Smrg 	      return NULL;
4135627f7eb2Smrg 	    }
4136627f7eb2Smrg 	  else if (has_null_arg)
4137627f7eb2Smrg 	    {
4138627f7eb2Smrg 	      null_sym = intr->sym;
4139627f7eb2Smrg 	      continue;
4140627f7eb2Smrg 	    }
4141627f7eb2Smrg 
4142627f7eb2Smrg 	  /* Satisfy 12.4.4.1 such that an elemental match has lower
4143627f7eb2Smrg 	     weight than a non-elemental match.  */
4144627f7eb2Smrg 	  if (intr->sym->attr.elemental)
4145627f7eb2Smrg 	    {
4146627f7eb2Smrg 	      elem_sym = intr->sym;
4147627f7eb2Smrg 	      continue;
4148627f7eb2Smrg 	    }
4149627f7eb2Smrg 	  return intr->sym;
4150627f7eb2Smrg 	}
4151627f7eb2Smrg     }
4152627f7eb2Smrg 
4153627f7eb2Smrg   if (null_sym)
4154627f7eb2Smrg     return null_sym;
4155627f7eb2Smrg 
4156627f7eb2Smrg   return elem_sym ? elem_sym : NULL;
4157627f7eb2Smrg }
4158627f7eb2Smrg 
4159627f7eb2Smrg 
4160627f7eb2Smrg /* Do a brute force recursive search for a symbol.  */
4161627f7eb2Smrg 
4162627f7eb2Smrg static gfc_symtree *
find_symtree0(gfc_symtree * root,gfc_symbol * sym)4163627f7eb2Smrg find_symtree0 (gfc_symtree *root, gfc_symbol *sym)
4164627f7eb2Smrg {
4165627f7eb2Smrg   gfc_symtree * st;
4166627f7eb2Smrg 
4167627f7eb2Smrg   if (root->n.sym == sym)
4168627f7eb2Smrg     return root;
4169627f7eb2Smrg 
4170627f7eb2Smrg   st = NULL;
4171627f7eb2Smrg   if (root->left)
4172627f7eb2Smrg     st = find_symtree0 (root->left, sym);
4173627f7eb2Smrg   if (root->right && ! st)
4174627f7eb2Smrg     st = find_symtree0 (root->right, sym);
4175627f7eb2Smrg   return st;
4176627f7eb2Smrg }
4177627f7eb2Smrg 
4178627f7eb2Smrg 
4179627f7eb2Smrg /* Find a symtree for a symbol.  */
4180627f7eb2Smrg 
4181627f7eb2Smrg gfc_symtree *
gfc_find_sym_in_symtree(gfc_symbol * sym)4182627f7eb2Smrg gfc_find_sym_in_symtree (gfc_symbol *sym)
4183627f7eb2Smrg {
4184627f7eb2Smrg   gfc_symtree *st;
4185627f7eb2Smrg   gfc_namespace *ns;
4186627f7eb2Smrg 
4187627f7eb2Smrg   /* First try to find it by name.  */
4188627f7eb2Smrg   gfc_find_sym_tree (sym->name, gfc_current_ns, 1, &st);
4189627f7eb2Smrg   if (st && st->n.sym == sym)
4190627f7eb2Smrg     return st;
4191627f7eb2Smrg 
4192627f7eb2Smrg   /* If it's been renamed, resort to a brute-force search.  */
4193627f7eb2Smrg   /* TODO: avoid having to do this search.  If the symbol doesn't exist
4194627f7eb2Smrg      in the symtree for the current namespace, it should probably be added.  */
4195627f7eb2Smrg   for (ns = gfc_current_ns; ns; ns = ns->parent)
4196627f7eb2Smrg     {
4197627f7eb2Smrg       st = find_symtree0 (ns->sym_root, sym);
4198627f7eb2Smrg       if (st)
4199627f7eb2Smrg 	return st;
4200627f7eb2Smrg     }
4201627f7eb2Smrg   gfc_internal_error ("Unable to find symbol %qs", sym->name);
4202627f7eb2Smrg   /* Not reached.  */
4203627f7eb2Smrg }
4204627f7eb2Smrg 
4205627f7eb2Smrg 
4206627f7eb2Smrg /* See if the arglist to an operator-call contains a derived-type argument
4207627f7eb2Smrg    with a matching type-bound operator.  If so, return the matching specific
4208627f7eb2Smrg    procedure defined as operator-target as well as the base-object to use
4209627f7eb2Smrg    (which is the found derived-type argument with operator).  The generic
4210627f7eb2Smrg    name, if any, is transmitted to the final expression via 'gname'.  */
4211627f7eb2Smrg 
4212627f7eb2Smrg static gfc_typebound_proc*
matching_typebound_op(gfc_expr ** tb_base,gfc_actual_arglist * args,gfc_intrinsic_op op,const char * uop,const char ** gname)4213627f7eb2Smrg matching_typebound_op (gfc_expr** tb_base,
4214627f7eb2Smrg 		       gfc_actual_arglist* args,
4215627f7eb2Smrg 		       gfc_intrinsic_op op, const char* uop,
4216627f7eb2Smrg 		       const char ** gname)
4217627f7eb2Smrg {
4218627f7eb2Smrg   gfc_actual_arglist* base;
4219627f7eb2Smrg 
4220627f7eb2Smrg   for (base = args; base; base = base->next)
4221627f7eb2Smrg     if (base->expr->ts.type == BT_DERIVED || base->expr->ts.type == BT_CLASS)
4222627f7eb2Smrg       {
4223627f7eb2Smrg 	gfc_typebound_proc* tb;
4224627f7eb2Smrg 	gfc_symbol* derived;
4225627f7eb2Smrg 	bool result;
4226627f7eb2Smrg 
4227627f7eb2Smrg 	while (base->expr->expr_type == EXPR_OP
4228627f7eb2Smrg 	       && base->expr->value.op.op == INTRINSIC_PARENTHESES)
4229627f7eb2Smrg 	  base->expr = base->expr->value.op.op1;
4230627f7eb2Smrg 
4231627f7eb2Smrg 	if (base->expr->ts.type == BT_CLASS)
4232627f7eb2Smrg 	  {
4233627f7eb2Smrg 	    if (!base->expr->ts.u.derived || CLASS_DATA (base->expr) == NULL
4234627f7eb2Smrg 		|| !gfc_expr_attr (base->expr).class_ok)
4235627f7eb2Smrg 	      continue;
4236627f7eb2Smrg 	    derived = CLASS_DATA (base->expr)->ts.u.derived;
4237627f7eb2Smrg 	  }
4238627f7eb2Smrg 	else
4239627f7eb2Smrg 	  derived = base->expr->ts.u.derived;
4240627f7eb2Smrg 
4241627f7eb2Smrg 	if (op == INTRINSIC_USER)
4242627f7eb2Smrg 	  {
4243627f7eb2Smrg 	    gfc_symtree* tb_uop;
4244627f7eb2Smrg 
4245627f7eb2Smrg 	    gcc_assert (uop);
4246627f7eb2Smrg 	    tb_uop = gfc_find_typebound_user_op (derived, &result, uop,
4247627f7eb2Smrg 						 false, NULL);
4248627f7eb2Smrg 
4249627f7eb2Smrg 	    if (tb_uop)
4250627f7eb2Smrg 	      tb = tb_uop->n.tb;
4251627f7eb2Smrg 	    else
4252627f7eb2Smrg 	      tb = NULL;
4253627f7eb2Smrg 	  }
4254627f7eb2Smrg 	else
4255627f7eb2Smrg 	  tb = gfc_find_typebound_intrinsic_op (derived, &result, op,
4256627f7eb2Smrg 						false, NULL);
4257627f7eb2Smrg 
4258627f7eb2Smrg 	/* This means we hit a PRIVATE operator which is use-associated and
4259627f7eb2Smrg 	   should thus not be seen.  */
4260627f7eb2Smrg 	if (!result)
4261627f7eb2Smrg 	  tb = NULL;
4262627f7eb2Smrg 
4263627f7eb2Smrg 	/* Look through the super-type hierarchy for a matching specific
4264627f7eb2Smrg 	   binding.  */
4265627f7eb2Smrg 	for (; tb; tb = tb->overridden)
4266627f7eb2Smrg 	  {
4267627f7eb2Smrg 	    gfc_tbp_generic* g;
4268627f7eb2Smrg 
4269627f7eb2Smrg 	    gcc_assert (tb->is_generic);
4270627f7eb2Smrg 	    for (g = tb->u.generic; g; g = g->next)
4271627f7eb2Smrg 	      {
4272627f7eb2Smrg 		gfc_symbol* target;
4273627f7eb2Smrg 		gfc_actual_arglist* argcopy;
4274627f7eb2Smrg 		bool matches;
4275627f7eb2Smrg 
4276627f7eb2Smrg 		gcc_assert (g->specific);
4277627f7eb2Smrg 		if (g->specific->error)
4278627f7eb2Smrg 		  continue;
4279627f7eb2Smrg 
4280627f7eb2Smrg 		target = g->specific->u.specific->n.sym;
4281627f7eb2Smrg 
4282627f7eb2Smrg 		/* Check if this arglist matches the formal.  */
4283627f7eb2Smrg 		argcopy = gfc_copy_actual_arglist (args);
4284627f7eb2Smrg 		matches = gfc_arglist_matches_symbol (&argcopy, target);
4285627f7eb2Smrg 		gfc_free_actual_arglist (argcopy);
4286627f7eb2Smrg 
4287627f7eb2Smrg 		/* Return if we found a match.  */
4288627f7eb2Smrg 		if (matches)
4289627f7eb2Smrg 		  {
4290627f7eb2Smrg 		    *tb_base = base->expr;
4291627f7eb2Smrg 		    *gname = g->specific_st->name;
4292627f7eb2Smrg 		    return g->specific;
4293627f7eb2Smrg 		  }
4294627f7eb2Smrg 	      }
4295627f7eb2Smrg 	  }
4296627f7eb2Smrg       }
4297627f7eb2Smrg 
4298627f7eb2Smrg   return NULL;
4299627f7eb2Smrg }
4300627f7eb2Smrg 
4301627f7eb2Smrg 
4302627f7eb2Smrg /* For the 'actual arglist' of an operator call and a specific typebound
4303627f7eb2Smrg    procedure that has been found the target of a type-bound operator, build the
4304627f7eb2Smrg    appropriate EXPR_COMPCALL and resolve it.  We take this indirection over
4305627f7eb2Smrg    type-bound procedures rather than resolving type-bound operators 'directly'
4306627f7eb2Smrg    so that we can reuse the existing logic.  */
4307627f7eb2Smrg 
4308627f7eb2Smrg static void
build_compcall_for_operator(gfc_expr * e,gfc_actual_arglist * actual,gfc_expr * base,gfc_typebound_proc * target,const char * gname)4309627f7eb2Smrg build_compcall_for_operator (gfc_expr* e, gfc_actual_arglist* actual,
4310627f7eb2Smrg 			     gfc_expr* base, gfc_typebound_proc* target,
4311627f7eb2Smrg 			     const char *gname)
4312627f7eb2Smrg {
4313627f7eb2Smrg   e->expr_type = EXPR_COMPCALL;
4314627f7eb2Smrg   e->value.compcall.tbp = target;
4315627f7eb2Smrg   e->value.compcall.name = gname ? gname : "$op";
4316627f7eb2Smrg   e->value.compcall.actual = actual;
4317627f7eb2Smrg   e->value.compcall.base_object = base;
4318627f7eb2Smrg   e->value.compcall.ignore_pass = 1;
4319627f7eb2Smrg   e->value.compcall.assign = 0;
4320627f7eb2Smrg   if (e->ts.type == BT_UNKNOWN
4321627f7eb2Smrg 	&& target->function)
4322627f7eb2Smrg     {
4323627f7eb2Smrg       if (target->is_generic)
4324627f7eb2Smrg 	e->ts = target->u.generic->specific->u.specific->n.sym->ts;
4325627f7eb2Smrg       else
4326627f7eb2Smrg 	e->ts = target->u.specific->n.sym->ts;
4327627f7eb2Smrg     }
4328627f7eb2Smrg }
4329627f7eb2Smrg 
4330627f7eb2Smrg 
4331627f7eb2Smrg /* This subroutine is called when an expression is being resolved.
4332627f7eb2Smrg    The expression node in question is either a user defined operator
4333627f7eb2Smrg    or an intrinsic operator with arguments that aren't compatible
4334627f7eb2Smrg    with the operator.  This subroutine builds an actual argument list
4335627f7eb2Smrg    corresponding to the operands, then searches for a compatible
4336627f7eb2Smrg    interface.  If one is found, the expression node is replaced with
4337627f7eb2Smrg    the appropriate function call. We use the 'match' enum to specify
4338627f7eb2Smrg    whether a replacement has been made or not, or if an error occurred.  */
4339627f7eb2Smrg 
4340627f7eb2Smrg match
gfc_extend_expr(gfc_expr * e)4341627f7eb2Smrg gfc_extend_expr (gfc_expr *e)
4342627f7eb2Smrg {
4343627f7eb2Smrg   gfc_actual_arglist *actual;
4344627f7eb2Smrg   gfc_symbol *sym;
4345627f7eb2Smrg   gfc_namespace *ns;
4346627f7eb2Smrg   gfc_user_op *uop;
4347627f7eb2Smrg   gfc_intrinsic_op i;
4348627f7eb2Smrg   const char *gname;
4349627f7eb2Smrg   gfc_typebound_proc* tbo;
4350627f7eb2Smrg   gfc_expr* tb_base;
4351627f7eb2Smrg 
4352627f7eb2Smrg   sym = NULL;
4353627f7eb2Smrg 
4354627f7eb2Smrg   actual = gfc_get_actual_arglist ();
4355627f7eb2Smrg   actual->expr = e->value.op.op1;
4356627f7eb2Smrg 
4357627f7eb2Smrg   gname = NULL;
4358627f7eb2Smrg 
4359627f7eb2Smrg   if (e->value.op.op2 != NULL)
4360627f7eb2Smrg     {
4361627f7eb2Smrg       actual->next = gfc_get_actual_arglist ();
4362627f7eb2Smrg       actual->next->expr = e->value.op.op2;
4363627f7eb2Smrg     }
4364627f7eb2Smrg 
4365627f7eb2Smrg   i = fold_unary_intrinsic (e->value.op.op);
4366627f7eb2Smrg 
4367627f7eb2Smrg   /* See if we find a matching type-bound operator.  */
4368627f7eb2Smrg   if (i == INTRINSIC_USER)
4369627f7eb2Smrg     tbo = matching_typebound_op (&tb_base, actual,
4370627f7eb2Smrg 				  i, e->value.op.uop->name, &gname);
4371627f7eb2Smrg   else
4372627f7eb2Smrg     switch (i)
4373627f7eb2Smrg       {
4374627f7eb2Smrg #define CHECK_OS_COMPARISON(comp) \
4375627f7eb2Smrg   case INTRINSIC_##comp: \
4376627f7eb2Smrg   case INTRINSIC_##comp##_OS: \
4377627f7eb2Smrg     tbo = matching_typebound_op (&tb_base, actual, \
4378627f7eb2Smrg 				 INTRINSIC_##comp, NULL, &gname); \
4379627f7eb2Smrg     if (!tbo) \
4380627f7eb2Smrg       tbo = matching_typebound_op (&tb_base, actual, \
4381627f7eb2Smrg 				   INTRINSIC_##comp##_OS, NULL, &gname); \
4382627f7eb2Smrg     break;
4383627f7eb2Smrg 	CHECK_OS_COMPARISON(EQ)
4384627f7eb2Smrg 	CHECK_OS_COMPARISON(NE)
4385627f7eb2Smrg 	CHECK_OS_COMPARISON(GT)
4386627f7eb2Smrg 	CHECK_OS_COMPARISON(GE)
4387627f7eb2Smrg 	CHECK_OS_COMPARISON(LT)
4388627f7eb2Smrg 	CHECK_OS_COMPARISON(LE)
4389627f7eb2Smrg #undef CHECK_OS_COMPARISON
4390627f7eb2Smrg 
4391627f7eb2Smrg 	default:
4392627f7eb2Smrg 	  tbo = matching_typebound_op (&tb_base, actual, i, NULL, &gname);
4393627f7eb2Smrg 	  break;
4394627f7eb2Smrg       }
4395627f7eb2Smrg 
4396627f7eb2Smrg   /* If there is a matching typebound-operator, replace the expression with
4397627f7eb2Smrg       a call to it and succeed.  */
4398627f7eb2Smrg   if (tbo)
4399627f7eb2Smrg     {
4400627f7eb2Smrg       gcc_assert (tb_base);
4401627f7eb2Smrg       build_compcall_for_operator (e, actual, tb_base, tbo, gname);
4402627f7eb2Smrg 
4403627f7eb2Smrg       if (!gfc_resolve_expr (e))
4404627f7eb2Smrg 	return MATCH_ERROR;
4405627f7eb2Smrg       else
4406627f7eb2Smrg 	return MATCH_YES;
4407627f7eb2Smrg     }
4408627f7eb2Smrg 
4409627f7eb2Smrg   if (i == INTRINSIC_USER)
4410627f7eb2Smrg     {
4411627f7eb2Smrg       for (ns = gfc_current_ns; ns; ns = ns->parent)
4412627f7eb2Smrg 	{
4413627f7eb2Smrg 	  uop = gfc_find_uop (e->value.op.uop->name, ns);
4414627f7eb2Smrg 	  if (uop == NULL)
4415627f7eb2Smrg 	    continue;
4416627f7eb2Smrg 
4417627f7eb2Smrg 	  sym = gfc_search_interface (uop->op, 0, &actual);
4418627f7eb2Smrg 	  if (sym != NULL)
4419627f7eb2Smrg 	    break;
4420627f7eb2Smrg 	}
4421627f7eb2Smrg     }
4422627f7eb2Smrg   else
4423627f7eb2Smrg     {
4424627f7eb2Smrg       for (ns = gfc_current_ns; ns; ns = ns->parent)
4425627f7eb2Smrg 	{
4426627f7eb2Smrg 	  /* Due to the distinction between '==' and '.eq.' and friends, one has
4427627f7eb2Smrg 	     to check if either is defined.  */
4428627f7eb2Smrg 	  switch (i)
4429627f7eb2Smrg 	    {
4430627f7eb2Smrg #define CHECK_OS_COMPARISON(comp) \
4431627f7eb2Smrg   case INTRINSIC_##comp: \
4432627f7eb2Smrg   case INTRINSIC_##comp##_OS: \
4433627f7eb2Smrg     sym = gfc_search_interface (ns->op[INTRINSIC_##comp], 0, &actual); \
4434627f7eb2Smrg     if (!sym) \
4435627f7eb2Smrg       sym = gfc_search_interface (ns->op[INTRINSIC_##comp##_OS], 0, &actual); \
4436627f7eb2Smrg     break;
4437627f7eb2Smrg 	      CHECK_OS_COMPARISON(EQ)
4438627f7eb2Smrg 	      CHECK_OS_COMPARISON(NE)
4439627f7eb2Smrg 	      CHECK_OS_COMPARISON(GT)
4440627f7eb2Smrg 	      CHECK_OS_COMPARISON(GE)
4441627f7eb2Smrg 	      CHECK_OS_COMPARISON(LT)
4442627f7eb2Smrg 	      CHECK_OS_COMPARISON(LE)
4443627f7eb2Smrg #undef CHECK_OS_COMPARISON
4444627f7eb2Smrg 
4445627f7eb2Smrg 	      default:
4446627f7eb2Smrg 		sym = gfc_search_interface (ns->op[i], 0, &actual);
4447627f7eb2Smrg 	    }
4448627f7eb2Smrg 
4449627f7eb2Smrg 	  if (sym != NULL)
4450627f7eb2Smrg 	    break;
4451627f7eb2Smrg 	}
4452627f7eb2Smrg     }
4453627f7eb2Smrg 
4454627f7eb2Smrg   /* TODO: Do an ambiguity-check and error if multiple matching interfaces are
4455627f7eb2Smrg      found rather than just taking the first one and not checking further.  */
4456627f7eb2Smrg 
4457627f7eb2Smrg   if (sym == NULL)
4458627f7eb2Smrg     {
4459627f7eb2Smrg       /* Don't use gfc_free_actual_arglist().  */
4460627f7eb2Smrg       free (actual->next);
4461627f7eb2Smrg       free (actual);
4462627f7eb2Smrg       return MATCH_NO;
4463627f7eb2Smrg     }
4464627f7eb2Smrg 
4465627f7eb2Smrg   /* Change the expression node to a function call.  */
4466627f7eb2Smrg   e->expr_type = EXPR_FUNCTION;
4467627f7eb2Smrg   e->symtree = gfc_find_sym_in_symtree (sym);
4468627f7eb2Smrg   e->value.function.actual = actual;
4469627f7eb2Smrg   e->value.function.esym = NULL;
4470627f7eb2Smrg   e->value.function.isym = NULL;
4471627f7eb2Smrg   e->value.function.name = NULL;
4472627f7eb2Smrg   e->user_operator = 1;
4473627f7eb2Smrg 
4474627f7eb2Smrg   if (!gfc_resolve_expr (e))
4475627f7eb2Smrg     return MATCH_ERROR;
4476627f7eb2Smrg 
4477627f7eb2Smrg   return MATCH_YES;
4478627f7eb2Smrg }
4479627f7eb2Smrg 
4480627f7eb2Smrg 
4481627f7eb2Smrg /* Tries to replace an assignment code node with a subroutine call to the
4482627f7eb2Smrg    subroutine associated with the assignment operator. Return true if the node
4483627f7eb2Smrg    was replaced. On false, no error is generated.  */
4484627f7eb2Smrg 
4485627f7eb2Smrg bool
gfc_extend_assign(gfc_code * c,gfc_namespace * ns)4486627f7eb2Smrg gfc_extend_assign (gfc_code *c, gfc_namespace *ns)
4487627f7eb2Smrg {
4488627f7eb2Smrg   gfc_actual_arglist *actual;
4489627f7eb2Smrg   gfc_expr *lhs, *rhs, *tb_base;
4490627f7eb2Smrg   gfc_symbol *sym = NULL;
4491627f7eb2Smrg   const char *gname = NULL;
4492627f7eb2Smrg   gfc_typebound_proc* tbo;
4493627f7eb2Smrg 
4494627f7eb2Smrg   lhs = c->expr1;
4495627f7eb2Smrg   rhs = c->expr2;
4496627f7eb2Smrg 
44974c3eb207Smrg   /* Don't allow an intrinsic assignment with a BOZ rhs to be replaced.  */
44984c3eb207Smrg   if (c->op == EXEC_ASSIGN
44994c3eb207Smrg       && c->expr1->expr_type == EXPR_VARIABLE
45004c3eb207Smrg       && c->expr2->expr_type == EXPR_CONSTANT && c->expr2->ts.type == BT_BOZ)
45014c3eb207Smrg     return false;
45024c3eb207Smrg 
4503627f7eb2Smrg   /* Don't allow an intrinsic assignment to be replaced.  */
4504627f7eb2Smrg   if (lhs->ts.type != BT_DERIVED && lhs->ts.type != BT_CLASS
4505627f7eb2Smrg       && (rhs->rank == 0 || rhs->rank == lhs->rank)
4506627f7eb2Smrg       && (lhs->ts.type == rhs->ts.type
4507627f7eb2Smrg 	  || (gfc_numeric_ts (&lhs->ts) && gfc_numeric_ts (&rhs->ts))))
4508627f7eb2Smrg     return false;
4509627f7eb2Smrg 
4510627f7eb2Smrg   actual = gfc_get_actual_arglist ();
4511627f7eb2Smrg   actual->expr = lhs;
4512627f7eb2Smrg 
4513627f7eb2Smrg   actual->next = gfc_get_actual_arglist ();
4514627f7eb2Smrg   actual->next->expr = rhs;
4515627f7eb2Smrg 
4516627f7eb2Smrg   /* TODO: Ambiguity-check, see above for gfc_extend_expr.  */
4517627f7eb2Smrg 
4518627f7eb2Smrg   /* See if we find a matching type-bound assignment.  */
4519627f7eb2Smrg   tbo = matching_typebound_op (&tb_base, actual, INTRINSIC_ASSIGN,
4520627f7eb2Smrg 			       NULL, &gname);
4521627f7eb2Smrg 
4522627f7eb2Smrg   if (tbo)
4523627f7eb2Smrg     {
4524627f7eb2Smrg       /* Success: Replace the expression with a type-bound call.  */
4525627f7eb2Smrg       gcc_assert (tb_base);
4526627f7eb2Smrg       c->expr1 = gfc_get_expr ();
4527627f7eb2Smrg       build_compcall_for_operator (c->expr1, actual, tb_base, tbo, gname);
4528627f7eb2Smrg       c->expr1->value.compcall.assign = 1;
4529627f7eb2Smrg       c->expr1->where = c->loc;
4530627f7eb2Smrg       c->expr2 = NULL;
4531627f7eb2Smrg       c->op = EXEC_COMPCALL;
4532627f7eb2Smrg       return true;
4533627f7eb2Smrg     }
4534627f7eb2Smrg 
4535627f7eb2Smrg   /* See if we find an 'ordinary' (non-typebound) assignment procedure.  */
4536627f7eb2Smrg   for (; ns; ns = ns->parent)
4537627f7eb2Smrg     {
4538627f7eb2Smrg       sym = gfc_search_interface (ns->op[INTRINSIC_ASSIGN], 1, &actual);
4539627f7eb2Smrg       if (sym != NULL)
4540627f7eb2Smrg 	break;
4541627f7eb2Smrg     }
4542627f7eb2Smrg 
4543627f7eb2Smrg   if (sym)
4544627f7eb2Smrg     {
4545627f7eb2Smrg       /* Success: Replace the assignment with the call.  */
4546627f7eb2Smrg       c->op = EXEC_ASSIGN_CALL;
4547627f7eb2Smrg       c->symtree = gfc_find_sym_in_symtree (sym);
4548627f7eb2Smrg       c->expr1 = NULL;
4549627f7eb2Smrg       c->expr2 = NULL;
4550627f7eb2Smrg       c->ext.actual = actual;
4551627f7eb2Smrg       return true;
4552627f7eb2Smrg     }
4553627f7eb2Smrg 
4554627f7eb2Smrg   /* Failure: No assignment procedure found.  */
4555627f7eb2Smrg   free (actual->next);
4556627f7eb2Smrg   free (actual);
4557627f7eb2Smrg   return false;
4558627f7eb2Smrg }
4559627f7eb2Smrg 
4560627f7eb2Smrg 
4561627f7eb2Smrg /* Make sure that the interface just parsed is not already present in
4562627f7eb2Smrg    the given interface list.  Ambiguity isn't checked yet since module
4563627f7eb2Smrg    procedures can be present without interfaces.  */
4564627f7eb2Smrg 
4565627f7eb2Smrg bool
gfc_check_new_interface(gfc_interface * base,gfc_symbol * new_sym,locus loc)4566627f7eb2Smrg gfc_check_new_interface (gfc_interface *base, gfc_symbol *new_sym, locus loc)
4567627f7eb2Smrg {
4568627f7eb2Smrg   gfc_interface *ip;
4569627f7eb2Smrg 
4570627f7eb2Smrg   for (ip = base; ip; ip = ip->next)
4571627f7eb2Smrg     {
4572627f7eb2Smrg       if (ip->sym == new_sym)
4573627f7eb2Smrg 	{
4574627f7eb2Smrg 	  gfc_error ("Entity %qs at %L is already present in the interface",
4575627f7eb2Smrg 		     new_sym->name, &loc);
4576627f7eb2Smrg 	  return false;
4577627f7eb2Smrg 	}
4578627f7eb2Smrg     }
4579627f7eb2Smrg 
4580627f7eb2Smrg   return true;
4581627f7eb2Smrg }
4582627f7eb2Smrg 
4583627f7eb2Smrg 
4584627f7eb2Smrg /* Add a symbol to the current interface.  */
4585627f7eb2Smrg 
4586627f7eb2Smrg bool
gfc_add_interface(gfc_symbol * new_sym)4587627f7eb2Smrg gfc_add_interface (gfc_symbol *new_sym)
4588627f7eb2Smrg {
4589627f7eb2Smrg   gfc_interface **head, *intr;
4590627f7eb2Smrg   gfc_namespace *ns;
4591627f7eb2Smrg   gfc_symbol *sym;
4592627f7eb2Smrg 
4593627f7eb2Smrg   switch (current_interface.type)
4594627f7eb2Smrg     {
4595627f7eb2Smrg     case INTERFACE_NAMELESS:
4596627f7eb2Smrg     case INTERFACE_ABSTRACT:
4597627f7eb2Smrg       return true;
4598627f7eb2Smrg 
4599627f7eb2Smrg     case INTERFACE_INTRINSIC_OP:
4600627f7eb2Smrg       for (ns = current_interface.ns; ns; ns = ns->parent)
4601627f7eb2Smrg 	switch (current_interface.op)
4602627f7eb2Smrg 	  {
4603627f7eb2Smrg 	    case INTRINSIC_EQ:
4604627f7eb2Smrg 	    case INTRINSIC_EQ_OS:
4605627f7eb2Smrg 	      if (!gfc_check_new_interface (ns->op[INTRINSIC_EQ], new_sym,
4606627f7eb2Smrg 					    gfc_current_locus)
4607627f7eb2Smrg 	          || !gfc_check_new_interface (ns->op[INTRINSIC_EQ_OS],
4608627f7eb2Smrg 					       new_sym, gfc_current_locus))
4609627f7eb2Smrg 		return false;
4610627f7eb2Smrg 	      break;
4611627f7eb2Smrg 
4612627f7eb2Smrg 	    case INTRINSIC_NE:
4613627f7eb2Smrg 	    case INTRINSIC_NE_OS:
4614627f7eb2Smrg 	      if (!gfc_check_new_interface (ns->op[INTRINSIC_NE], new_sym,
4615627f7eb2Smrg 					    gfc_current_locus)
4616627f7eb2Smrg 	          || !gfc_check_new_interface (ns->op[INTRINSIC_NE_OS],
4617627f7eb2Smrg 					       new_sym, gfc_current_locus))
4618627f7eb2Smrg 		return false;
4619627f7eb2Smrg 	      break;
4620627f7eb2Smrg 
4621627f7eb2Smrg 	    case INTRINSIC_GT:
4622627f7eb2Smrg 	    case INTRINSIC_GT_OS:
4623627f7eb2Smrg 	      if (!gfc_check_new_interface (ns->op[INTRINSIC_GT],
4624627f7eb2Smrg 					    new_sym, gfc_current_locus)
4625627f7eb2Smrg 	          || !gfc_check_new_interface (ns->op[INTRINSIC_GT_OS],
4626627f7eb2Smrg 					       new_sym, gfc_current_locus))
4627627f7eb2Smrg 		return false;
4628627f7eb2Smrg 	      break;
4629627f7eb2Smrg 
4630627f7eb2Smrg 	    case INTRINSIC_GE:
4631627f7eb2Smrg 	    case INTRINSIC_GE_OS:
4632627f7eb2Smrg 	      if (!gfc_check_new_interface (ns->op[INTRINSIC_GE],
4633627f7eb2Smrg 					    new_sym, gfc_current_locus)
4634627f7eb2Smrg 	          || !gfc_check_new_interface (ns->op[INTRINSIC_GE_OS],
4635627f7eb2Smrg 					       new_sym, gfc_current_locus))
4636627f7eb2Smrg 		return false;
4637627f7eb2Smrg 	      break;
4638627f7eb2Smrg 
4639627f7eb2Smrg 	    case INTRINSIC_LT:
4640627f7eb2Smrg 	    case INTRINSIC_LT_OS:
4641627f7eb2Smrg 	      if (!gfc_check_new_interface (ns->op[INTRINSIC_LT],
4642627f7eb2Smrg 					    new_sym, gfc_current_locus)
4643627f7eb2Smrg 	          || !gfc_check_new_interface (ns->op[INTRINSIC_LT_OS],
4644627f7eb2Smrg 					       new_sym, gfc_current_locus))
4645627f7eb2Smrg 		return false;
4646627f7eb2Smrg 	      break;
4647627f7eb2Smrg 
4648627f7eb2Smrg 	    case INTRINSIC_LE:
4649627f7eb2Smrg 	    case INTRINSIC_LE_OS:
4650627f7eb2Smrg 	      if (!gfc_check_new_interface (ns->op[INTRINSIC_LE],
4651627f7eb2Smrg 					    new_sym, gfc_current_locus)
4652627f7eb2Smrg 	          || !gfc_check_new_interface (ns->op[INTRINSIC_LE_OS],
4653627f7eb2Smrg 					       new_sym, gfc_current_locus))
4654627f7eb2Smrg 		return false;
4655627f7eb2Smrg 	      break;
4656627f7eb2Smrg 
4657627f7eb2Smrg 	    default:
4658627f7eb2Smrg 	      if (!gfc_check_new_interface (ns->op[current_interface.op],
4659627f7eb2Smrg 					    new_sym, gfc_current_locus))
4660627f7eb2Smrg 		return false;
4661627f7eb2Smrg 	  }
4662627f7eb2Smrg 
4663627f7eb2Smrg       head = &current_interface.ns->op[current_interface.op];
4664627f7eb2Smrg       break;
4665627f7eb2Smrg 
4666627f7eb2Smrg     case INTERFACE_GENERIC:
4667627f7eb2Smrg     case INTERFACE_DTIO:
4668627f7eb2Smrg       for (ns = current_interface.ns; ns; ns = ns->parent)
4669627f7eb2Smrg 	{
4670627f7eb2Smrg 	  gfc_find_symbol (current_interface.sym->name, ns, 0, &sym);
4671627f7eb2Smrg 	  if (sym == NULL)
4672627f7eb2Smrg 	    continue;
4673627f7eb2Smrg 
4674627f7eb2Smrg 	  if (!gfc_check_new_interface (sym->generic,
4675627f7eb2Smrg 					new_sym, gfc_current_locus))
4676627f7eb2Smrg 	    return false;
4677627f7eb2Smrg 	}
4678627f7eb2Smrg 
4679627f7eb2Smrg       head = &current_interface.sym->generic;
4680627f7eb2Smrg       break;
4681627f7eb2Smrg 
4682627f7eb2Smrg     case INTERFACE_USER_OP:
4683627f7eb2Smrg       if (!gfc_check_new_interface (current_interface.uop->op,
4684627f7eb2Smrg 				    new_sym, gfc_current_locus))
4685627f7eb2Smrg 	return false;
4686627f7eb2Smrg 
4687627f7eb2Smrg       head = &current_interface.uop->op;
4688627f7eb2Smrg       break;
4689627f7eb2Smrg 
4690627f7eb2Smrg     default:
4691627f7eb2Smrg       gfc_internal_error ("gfc_add_interface(): Bad interface type");
4692627f7eb2Smrg     }
4693627f7eb2Smrg 
4694627f7eb2Smrg   intr = gfc_get_interface ();
4695627f7eb2Smrg   intr->sym = new_sym;
4696627f7eb2Smrg   intr->where = gfc_current_locus;
4697627f7eb2Smrg 
4698627f7eb2Smrg   intr->next = *head;
4699627f7eb2Smrg   *head = intr;
4700627f7eb2Smrg 
4701627f7eb2Smrg   return true;
4702627f7eb2Smrg }
4703627f7eb2Smrg 
4704627f7eb2Smrg 
4705627f7eb2Smrg gfc_interface *
gfc_current_interface_head(void)4706627f7eb2Smrg gfc_current_interface_head (void)
4707627f7eb2Smrg {
4708627f7eb2Smrg   switch (current_interface.type)
4709627f7eb2Smrg     {
4710627f7eb2Smrg       case INTERFACE_INTRINSIC_OP:
4711627f7eb2Smrg 	return current_interface.ns->op[current_interface.op];
4712627f7eb2Smrg 
4713627f7eb2Smrg       case INTERFACE_GENERIC:
4714627f7eb2Smrg       case INTERFACE_DTIO:
4715627f7eb2Smrg 	return current_interface.sym->generic;
4716627f7eb2Smrg 
4717627f7eb2Smrg       case INTERFACE_USER_OP:
4718627f7eb2Smrg 	return current_interface.uop->op;
4719627f7eb2Smrg 
4720627f7eb2Smrg       default:
4721627f7eb2Smrg 	gcc_unreachable ();
4722627f7eb2Smrg     }
4723627f7eb2Smrg }
4724627f7eb2Smrg 
4725627f7eb2Smrg 
4726627f7eb2Smrg void
gfc_set_current_interface_head(gfc_interface * i)4727627f7eb2Smrg gfc_set_current_interface_head (gfc_interface *i)
4728627f7eb2Smrg {
4729627f7eb2Smrg   switch (current_interface.type)
4730627f7eb2Smrg     {
4731627f7eb2Smrg       case INTERFACE_INTRINSIC_OP:
4732627f7eb2Smrg 	current_interface.ns->op[current_interface.op] = i;
4733627f7eb2Smrg 	break;
4734627f7eb2Smrg 
4735627f7eb2Smrg       case INTERFACE_GENERIC:
4736627f7eb2Smrg       case INTERFACE_DTIO:
4737627f7eb2Smrg 	current_interface.sym->generic = i;
4738627f7eb2Smrg 	break;
4739627f7eb2Smrg 
4740627f7eb2Smrg       case INTERFACE_USER_OP:
4741627f7eb2Smrg 	current_interface.uop->op = i;
4742627f7eb2Smrg 	break;
4743627f7eb2Smrg 
4744627f7eb2Smrg       default:
4745627f7eb2Smrg 	gcc_unreachable ();
4746627f7eb2Smrg     }
4747627f7eb2Smrg }
4748627f7eb2Smrg 
4749627f7eb2Smrg 
4750627f7eb2Smrg /* Gets rid of a formal argument list.  We do not free symbols.
4751627f7eb2Smrg    Symbols are freed when a namespace is freed.  */
4752627f7eb2Smrg 
4753627f7eb2Smrg void
gfc_free_formal_arglist(gfc_formal_arglist * p)4754627f7eb2Smrg gfc_free_formal_arglist (gfc_formal_arglist *p)
4755627f7eb2Smrg {
4756627f7eb2Smrg   gfc_formal_arglist *q;
4757627f7eb2Smrg 
4758627f7eb2Smrg   for (; p; p = q)
4759627f7eb2Smrg     {
4760627f7eb2Smrg       q = p->next;
4761627f7eb2Smrg       free (p);
4762627f7eb2Smrg     }
4763627f7eb2Smrg }
4764627f7eb2Smrg 
4765627f7eb2Smrg 
4766627f7eb2Smrg /* Check that it is ok for the type-bound procedure 'proc' to override the
4767627f7eb2Smrg    procedure 'old', cf. F08:4.5.7.3.  */
4768627f7eb2Smrg 
4769627f7eb2Smrg bool
gfc_check_typebound_override(gfc_symtree * proc,gfc_symtree * old)4770627f7eb2Smrg gfc_check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
4771627f7eb2Smrg {
4772627f7eb2Smrg   locus where;
4773627f7eb2Smrg   gfc_symbol *proc_target, *old_target;
4774627f7eb2Smrg   unsigned proc_pass_arg, old_pass_arg, argpos;
4775627f7eb2Smrg   gfc_formal_arglist *proc_formal, *old_formal;
4776627f7eb2Smrg   bool check_type;
4777627f7eb2Smrg   char err[200];
4778627f7eb2Smrg 
4779627f7eb2Smrg   /* This procedure should only be called for non-GENERIC proc.  */
4780627f7eb2Smrg   gcc_assert (!proc->n.tb->is_generic);
4781627f7eb2Smrg 
4782627f7eb2Smrg   /* If the overwritten procedure is GENERIC, this is an error.  */
4783627f7eb2Smrg   if (old->n.tb->is_generic)
4784627f7eb2Smrg     {
4785627f7eb2Smrg       gfc_error ("Cannot overwrite GENERIC %qs at %L",
4786627f7eb2Smrg 		 old->name, &proc->n.tb->where);
4787627f7eb2Smrg       return false;
4788627f7eb2Smrg     }
4789627f7eb2Smrg 
4790627f7eb2Smrg   where = proc->n.tb->where;
4791627f7eb2Smrg   proc_target = proc->n.tb->u.specific->n.sym;
4792627f7eb2Smrg   old_target = old->n.tb->u.specific->n.sym;
4793627f7eb2Smrg 
4794627f7eb2Smrg   /* Check that overridden binding is not NON_OVERRIDABLE.  */
4795627f7eb2Smrg   if (old->n.tb->non_overridable)
4796627f7eb2Smrg     {
4797627f7eb2Smrg       gfc_error ("%qs at %L overrides a procedure binding declared"
4798627f7eb2Smrg 		 " NON_OVERRIDABLE", proc->name, &where);
4799627f7eb2Smrg       return false;
4800627f7eb2Smrg     }
4801627f7eb2Smrg 
4802627f7eb2Smrg   /* It's an error to override a non-DEFERRED procedure with a DEFERRED one.  */
4803627f7eb2Smrg   if (!old->n.tb->deferred && proc->n.tb->deferred)
4804627f7eb2Smrg     {
4805627f7eb2Smrg       gfc_error ("%qs at %L must not be DEFERRED as it overrides a"
4806627f7eb2Smrg 		 " non-DEFERRED binding", proc->name, &where);
4807627f7eb2Smrg       return false;
4808627f7eb2Smrg     }
4809627f7eb2Smrg 
4810627f7eb2Smrg   /* If the overridden binding is PURE, the overriding must be, too.  */
4811627f7eb2Smrg   if (old_target->attr.pure && !proc_target->attr.pure)
4812627f7eb2Smrg     {
4813627f7eb2Smrg       gfc_error ("%qs at %L overrides a PURE procedure and must also be PURE",
4814627f7eb2Smrg 		 proc->name, &where);
4815627f7eb2Smrg       return false;
4816627f7eb2Smrg     }
4817627f7eb2Smrg 
4818627f7eb2Smrg   /* If the overridden binding is ELEMENTAL, the overriding must be, too.  If it
4819627f7eb2Smrg      is not, the overriding must not be either.  */
4820627f7eb2Smrg   if (old_target->attr.elemental && !proc_target->attr.elemental)
4821627f7eb2Smrg     {
4822627f7eb2Smrg       gfc_error ("%qs at %L overrides an ELEMENTAL procedure and must also be"
4823627f7eb2Smrg 		 " ELEMENTAL", proc->name, &where);
4824627f7eb2Smrg       return false;
4825627f7eb2Smrg     }
4826627f7eb2Smrg   if (!old_target->attr.elemental && proc_target->attr.elemental)
4827627f7eb2Smrg     {
4828627f7eb2Smrg       gfc_error ("%qs at %L overrides a non-ELEMENTAL procedure and must not"
4829627f7eb2Smrg 		 " be ELEMENTAL, either", proc->name, &where);
4830627f7eb2Smrg       return false;
4831627f7eb2Smrg     }
4832627f7eb2Smrg 
4833627f7eb2Smrg   /* If the overridden binding is a SUBROUTINE, the overriding must also be a
4834627f7eb2Smrg      SUBROUTINE.  */
4835627f7eb2Smrg   if (old_target->attr.subroutine && !proc_target->attr.subroutine)
4836627f7eb2Smrg     {
4837627f7eb2Smrg       gfc_error ("%qs at %L overrides a SUBROUTINE and must also be a"
4838627f7eb2Smrg 		 " SUBROUTINE", proc->name, &where);
4839627f7eb2Smrg       return false;
4840627f7eb2Smrg     }
4841627f7eb2Smrg 
4842627f7eb2Smrg   /* If the overridden binding is a FUNCTION, the overriding must also be a
4843627f7eb2Smrg      FUNCTION and have the same characteristics.  */
4844627f7eb2Smrg   if (old_target->attr.function)
4845627f7eb2Smrg     {
4846627f7eb2Smrg       if (!proc_target->attr.function)
4847627f7eb2Smrg 	{
4848627f7eb2Smrg 	  gfc_error ("%qs at %L overrides a FUNCTION and must also be a"
4849627f7eb2Smrg 		     " FUNCTION", proc->name, &where);
4850627f7eb2Smrg 	  return false;
4851627f7eb2Smrg 	}
4852627f7eb2Smrg 
4853627f7eb2Smrg       if (!gfc_check_result_characteristics (proc_target, old_target,
4854627f7eb2Smrg 					     err, sizeof(err)))
4855627f7eb2Smrg 	{
4856627f7eb2Smrg 	  gfc_error ("Result mismatch for the overriding procedure "
4857627f7eb2Smrg 		     "%qs at %L: %s", proc->name, &where, err);
4858627f7eb2Smrg 	  return false;
4859627f7eb2Smrg 	}
4860627f7eb2Smrg     }
4861627f7eb2Smrg 
4862627f7eb2Smrg   /* If the overridden binding is PUBLIC, the overriding one must not be
4863627f7eb2Smrg      PRIVATE.  */
4864627f7eb2Smrg   if (old->n.tb->access == ACCESS_PUBLIC
4865627f7eb2Smrg       && proc->n.tb->access == ACCESS_PRIVATE)
4866627f7eb2Smrg     {
4867627f7eb2Smrg       gfc_error ("%qs at %L overrides a PUBLIC procedure and must not be"
4868627f7eb2Smrg 		 " PRIVATE", proc->name, &where);
4869627f7eb2Smrg       return false;
4870627f7eb2Smrg     }
4871627f7eb2Smrg 
4872627f7eb2Smrg   /* Compare the formal argument lists of both procedures.  This is also abused
4873627f7eb2Smrg      to find the position of the passed-object dummy arguments of both
4874627f7eb2Smrg      bindings as at least the overridden one might not yet be resolved and we
4875627f7eb2Smrg      need those positions in the check below.  */
4876627f7eb2Smrg   proc_pass_arg = old_pass_arg = 0;
4877627f7eb2Smrg   if (!proc->n.tb->nopass && !proc->n.tb->pass_arg)
4878627f7eb2Smrg     proc_pass_arg = 1;
4879627f7eb2Smrg   if (!old->n.tb->nopass && !old->n.tb->pass_arg)
4880627f7eb2Smrg     old_pass_arg = 1;
4881627f7eb2Smrg   argpos = 1;
4882627f7eb2Smrg   proc_formal = gfc_sym_get_dummy_args (proc_target);
4883627f7eb2Smrg   old_formal = gfc_sym_get_dummy_args (old_target);
4884627f7eb2Smrg   for ( ; proc_formal && old_formal;
4885627f7eb2Smrg        proc_formal = proc_formal->next, old_formal = old_formal->next)
4886627f7eb2Smrg     {
4887627f7eb2Smrg       if (proc->n.tb->pass_arg
4888627f7eb2Smrg 	  && !strcmp (proc->n.tb->pass_arg, proc_formal->sym->name))
4889627f7eb2Smrg 	proc_pass_arg = argpos;
4890627f7eb2Smrg       if (old->n.tb->pass_arg
4891627f7eb2Smrg 	  && !strcmp (old->n.tb->pass_arg, old_formal->sym->name))
4892627f7eb2Smrg 	old_pass_arg = argpos;
4893627f7eb2Smrg 
4894627f7eb2Smrg       /* Check that the names correspond.  */
4895627f7eb2Smrg       if (strcmp (proc_formal->sym->name, old_formal->sym->name))
4896627f7eb2Smrg 	{
4897627f7eb2Smrg 	  gfc_error ("Dummy argument %qs of %qs at %L should be named %qs as"
4898627f7eb2Smrg 		     " to match the corresponding argument of the overridden"
4899627f7eb2Smrg 		     " procedure", proc_formal->sym->name, proc->name, &where,
4900627f7eb2Smrg 		     old_formal->sym->name);
4901627f7eb2Smrg 	  return false;
4902627f7eb2Smrg 	}
4903627f7eb2Smrg 
4904627f7eb2Smrg       check_type = proc_pass_arg != argpos && old_pass_arg != argpos;
4905627f7eb2Smrg       if (!gfc_check_dummy_characteristics (proc_formal->sym, old_formal->sym,
4906627f7eb2Smrg 					check_type, err, sizeof(err)))
4907627f7eb2Smrg 	{
49084c3eb207Smrg 	  gfc_error_opt (0, "Argument mismatch for the overriding procedure "
4909627f7eb2Smrg 			 "%qs at %L: %s", proc->name, &where, err);
4910627f7eb2Smrg 	  return false;
4911627f7eb2Smrg 	}
4912627f7eb2Smrg 
4913627f7eb2Smrg       ++argpos;
4914627f7eb2Smrg     }
4915627f7eb2Smrg   if (proc_formal || old_formal)
4916627f7eb2Smrg     {
4917627f7eb2Smrg       gfc_error ("%qs at %L must have the same number of formal arguments as"
4918627f7eb2Smrg 		 " the overridden procedure", proc->name, &where);
4919627f7eb2Smrg       return false;
4920627f7eb2Smrg     }
4921627f7eb2Smrg 
4922627f7eb2Smrg   /* If the overridden binding is NOPASS, the overriding one must also be
4923627f7eb2Smrg      NOPASS.  */
4924627f7eb2Smrg   if (old->n.tb->nopass && !proc->n.tb->nopass)
4925627f7eb2Smrg     {
4926627f7eb2Smrg       gfc_error ("%qs at %L overrides a NOPASS binding and must also be"
4927627f7eb2Smrg 		 " NOPASS", proc->name, &where);
4928627f7eb2Smrg       return false;
4929627f7eb2Smrg     }
4930627f7eb2Smrg 
4931627f7eb2Smrg   /* If the overridden binding is PASS(x), the overriding one must also be
4932627f7eb2Smrg      PASS and the passed-object dummy arguments must correspond.  */
4933627f7eb2Smrg   if (!old->n.tb->nopass)
4934627f7eb2Smrg     {
4935627f7eb2Smrg       if (proc->n.tb->nopass)
4936627f7eb2Smrg 	{
4937627f7eb2Smrg 	  gfc_error ("%qs at %L overrides a binding with PASS and must also be"
4938627f7eb2Smrg 		     " PASS", proc->name, &where);
4939627f7eb2Smrg 	  return false;
4940627f7eb2Smrg 	}
4941627f7eb2Smrg 
4942627f7eb2Smrg       if (proc_pass_arg != old_pass_arg)
4943627f7eb2Smrg 	{
4944627f7eb2Smrg 	  gfc_error ("Passed-object dummy argument of %qs at %L must be at"
4945627f7eb2Smrg 		     " the same position as the passed-object dummy argument of"
4946627f7eb2Smrg 		     " the overridden procedure", proc->name, &where);
4947627f7eb2Smrg 	  return false;
4948627f7eb2Smrg 	}
4949627f7eb2Smrg     }
4950627f7eb2Smrg 
4951627f7eb2Smrg   return true;
4952627f7eb2Smrg }
4953627f7eb2Smrg 
4954627f7eb2Smrg 
4955627f7eb2Smrg /* The following three functions check that the formal arguments
4956627f7eb2Smrg    of user defined derived type IO procedures are compliant with
4957627f7eb2Smrg    the requirements of the standard, see F03:9.5.3.7.2 (F08:9.6.4.8.3).  */
4958627f7eb2Smrg 
4959627f7eb2Smrg static void
check_dtio_arg_TKR_intent(gfc_symbol * fsym,bool typebound,bt type,int kind,int rank,sym_intent intent)4960627f7eb2Smrg check_dtio_arg_TKR_intent (gfc_symbol *fsym, bool typebound, bt type,
4961627f7eb2Smrg 			   int kind, int rank, sym_intent intent)
4962627f7eb2Smrg {
4963627f7eb2Smrg   if (fsym->ts.type != type)
4964627f7eb2Smrg     {
4965627f7eb2Smrg       gfc_error ("DTIO dummy argument at %L must be of type %s",
4966627f7eb2Smrg 		 &fsym->declared_at, gfc_basic_typename (type));
4967627f7eb2Smrg       return;
4968627f7eb2Smrg     }
4969627f7eb2Smrg 
4970627f7eb2Smrg   if (fsym->ts.type != BT_CLASS && fsym->ts.type != BT_DERIVED
4971627f7eb2Smrg       && fsym->ts.kind != kind)
4972627f7eb2Smrg     gfc_error ("DTIO dummy argument at %L must be of KIND = %d",
4973627f7eb2Smrg 	       &fsym->declared_at, kind);
4974627f7eb2Smrg 
4975627f7eb2Smrg   if (!typebound
4976627f7eb2Smrg       && rank == 0
4977627f7eb2Smrg       && (((type == BT_CLASS) && CLASS_DATA (fsym)->attr.dimension)
4978627f7eb2Smrg 	  || ((type != BT_CLASS) && fsym->attr.dimension)))
4979627f7eb2Smrg     gfc_error ("DTIO dummy argument at %L must be a scalar",
4980627f7eb2Smrg 	       &fsym->declared_at);
4981627f7eb2Smrg   else if (rank == 1
4982627f7eb2Smrg 	   && (fsym->as == NULL || fsym->as->type != AS_ASSUMED_SHAPE))
4983627f7eb2Smrg     gfc_error ("DTIO dummy argument at %L must be an "
4984627f7eb2Smrg 	       "ASSUMED SHAPE ARRAY", &fsym->declared_at);
4985627f7eb2Smrg 
4986627f7eb2Smrg   if (type == BT_CHARACTER && fsym->ts.u.cl->length != NULL)
4987627f7eb2Smrg     gfc_error ("DTIO character argument at %L must have assumed length",
4988627f7eb2Smrg                &fsym->declared_at);
4989627f7eb2Smrg 
4990627f7eb2Smrg   if (fsym->attr.intent != intent)
4991627f7eb2Smrg     gfc_error ("DTIO dummy argument at %L must have INTENT %s",
4992627f7eb2Smrg 	       &fsym->declared_at, gfc_code2string (intents, (int)intent));
4993627f7eb2Smrg   return;
4994627f7eb2Smrg }
4995627f7eb2Smrg 
4996627f7eb2Smrg 
4997627f7eb2Smrg static void
check_dtio_interface1(gfc_symbol * derived,gfc_symtree * tb_io_st,bool typebound,bool formatted,int code)4998627f7eb2Smrg check_dtio_interface1 (gfc_symbol *derived, gfc_symtree *tb_io_st,
4999627f7eb2Smrg 		       bool typebound, bool formatted, int code)
5000627f7eb2Smrg {
5001627f7eb2Smrg   gfc_symbol *dtio_sub, *generic_proc, *fsym;
5002627f7eb2Smrg   gfc_typebound_proc *tb_io_proc, *specific_proc;
5003627f7eb2Smrg   gfc_interface *intr;
5004627f7eb2Smrg   gfc_formal_arglist *formal;
5005627f7eb2Smrg   int arg_num;
5006627f7eb2Smrg 
5007627f7eb2Smrg   bool read = ((dtio_codes)code == DTIO_RF)
5008627f7eb2Smrg 	       || ((dtio_codes)code == DTIO_RUF);
5009627f7eb2Smrg   bt type;
5010627f7eb2Smrg   sym_intent intent;
5011627f7eb2Smrg   int kind;
5012627f7eb2Smrg 
5013627f7eb2Smrg   dtio_sub = NULL;
5014627f7eb2Smrg   if (typebound)
5015627f7eb2Smrg     {
5016627f7eb2Smrg       /* Typebound DTIO binding.  */
5017627f7eb2Smrg       tb_io_proc = tb_io_st->n.tb;
5018627f7eb2Smrg       if (tb_io_proc == NULL)
5019627f7eb2Smrg 	return;
5020627f7eb2Smrg 
5021627f7eb2Smrg       gcc_assert (tb_io_proc->is_generic);
5022627f7eb2Smrg 
5023627f7eb2Smrg       specific_proc = tb_io_proc->u.generic->specific;
5024627f7eb2Smrg       if (specific_proc == NULL || specific_proc->is_generic)
5025627f7eb2Smrg 	return;
5026627f7eb2Smrg 
5027627f7eb2Smrg       dtio_sub = specific_proc->u.specific->n.sym;
5028627f7eb2Smrg     }
5029627f7eb2Smrg   else
5030627f7eb2Smrg     {
5031627f7eb2Smrg       generic_proc = tb_io_st->n.sym;
5032627f7eb2Smrg       if (generic_proc == NULL || generic_proc->generic == NULL)
5033627f7eb2Smrg 	return;
5034627f7eb2Smrg 
5035627f7eb2Smrg       for (intr = tb_io_st->n.sym->generic; intr; intr = intr->next)
5036627f7eb2Smrg 	{
5037627f7eb2Smrg 	  if (intr->sym && intr->sym->formal && intr->sym->formal->sym
5038627f7eb2Smrg 	      && ((intr->sym->formal->sym->ts.type == BT_CLASS
5039627f7eb2Smrg 	           && CLASS_DATA (intr->sym->formal->sym)->ts.u.derived
5040627f7eb2Smrg 							     == derived)
5041627f7eb2Smrg 		  || (intr->sym->formal->sym->ts.type == BT_DERIVED
5042627f7eb2Smrg 		      && intr->sym->formal->sym->ts.u.derived == derived)))
5043627f7eb2Smrg 	    {
5044627f7eb2Smrg 	      dtio_sub = intr->sym;
5045627f7eb2Smrg 	      break;
5046627f7eb2Smrg 	    }
5047627f7eb2Smrg 	  else if (intr->sym && intr->sym->formal && !intr->sym->formal->sym)
5048627f7eb2Smrg 	    {
5049627f7eb2Smrg 	      gfc_error ("Alternate return at %L is not permitted in a DTIO "
5050627f7eb2Smrg 			 "procedure", &intr->sym->declared_at);
5051627f7eb2Smrg 	      return;
5052627f7eb2Smrg 	    }
5053627f7eb2Smrg 	}
5054627f7eb2Smrg 
5055627f7eb2Smrg       if (dtio_sub == NULL)
5056627f7eb2Smrg 	return;
5057627f7eb2Smrg     }
5058627f7eb2Smrg 
5059627f7eb2Smrg   gcc_assert (dtio_sub);
5060627f7eb2Smrg   if (!dtio_sub->attr.subroutine)
5061627f7eb2Smrg     gfc_error ("DTIO procedure %qs at %L must be a subroutine",
5062627f7eb2Smrg 	       dtio_sub->name, &dtio_sub->declared_at);
5063627f7eb2Smrg 
50644c3eb207Smrg   if (!dtio_sub->resolve_symbol_called)
50654c3eb207Smrg     gfc_resolve_formal_arglist (dtio_sub);
50664c3eb207Smrg 
5067627f7eb2Smrg   arg_num = 0;
5068627f7eb2Smrg   for (formal = dtio_sub->formal; formal; formal = formal->next)
5069627f7eb2Smrg     arg_num++;
5070627f7eb2Smrg 
5071627f7eb2Smrg   if (arg_num < (formatted ? 6 : 4))
5072627f7eb2Smrg     {
5073627f7eb2Smrg       gfc_error ("Too few dummy arguments in DTIO procedure %qs at %L",
5074627f7eb2Smrg 		 dtio_sub->name, &dtio_sub->declared_at);
5075627f7eb2Smrg       return;
5076627f7eb2Smrg     }
5077627f7eb2Smrg 
5078627f7eb2Smrg   if (arg_num > (formatted ? 6 : 4))
5079627f7eb2Smrg     {
5080627f7eb2Smrg       gfc_error ("Too many dummy arguments in DTIO procedure %qs at %L",
5081627f7eb2Smrg 		 dtio_sub->name, &dtio_sub->declared_at);
5082627f7eb2Smrg       return;
5083627f7eb2Smrg     }
5084627f7eb2Smrg 
5085627f7eb2Smrg   /* Now go through the formal arglist.  */
5086627f7eb2Smrg   arg_num = 1;
5087627f7eb2Smrg   for (formal = dtio_sub->formal; formal; formal = formal->next, arg_num++)
5088627f7eb2Smrg     {
5089627f7eb2Smrg       if (!formatted && arg_num == 3)
5090627f7eb2Smrg 	arg_num = 5;
5091627f7eb2Smrg       fsym = formal->sym;
5092627f7eb2Smrg 
5093627f7eb2Smrg       if (fsym == NULL)
5094627f7eb2Smrg 	{
5095627f7eb2Smrg 	  gfc_error ("Alternate return at %L is not permitted in a DTIO "
5096627f7eb2Smrg 		     "procedure", &dtio_sub->declared_at);
5097627f7eb2Smrg 	  return;
5098627f7eb2Smrg 	}
5099627f7eb2Smrg 
5100627f7eb2Smrg       switch (arg_num)
5101627f7eb2Smrg 	{
5102627f7eb2Smrg 	case(1):			/* DTV  */
5103627f7eb2Smrg 	  type = derived->attr.sequence || derived->attr.is_bind_c ?
5104627f7eb2Smrg 		 BT_DERIVED : BT_CLASS;
5105627f7eb2Smrg 	  kind = 0;
5106627f7eb2Smrg 	  intent = read ? INTENT_INOUT : INTENT_IN;
5107627f7eb2Smrg 	  check_dtio_arg_TKR_intent (fsym, typebound, type, kind,
5108627f7eb2Smrg 				     0, intent);
5109627f7eb2Smrg 	  break;
5110627f7eb2Smrg 
5111627f7eb2Smrg 	case(2):			/* UNIT  */
5112627f7eb2Smrg 	  type = BT_INTEGER;
5113627f7eb2Smrg 	  kind = gfc_default_integer_kind;
5114627f7eb2Smrg 	  intent = INTENT_IN;
5115627f7eb2Smrg 	  check_dtio_arg_TKR_intent (fsym, typebound, type, kind,
5116627f7eb2Smrg 				     0, intent);
5117627f7eb2Smrg 	  break;
5118627f7eb2Smrg 	case(3):			/* IOTYPE  */
5119627f7eb2Smrg 	  type = BT_CHARACTER;
5120627f7eb2Smrg 	  kind = gfc_default_character_kind;
5121627f7eb2Smrg 	  intent = INTENT_IN;
5122627f7eb2Smrg 	  check_dtio_arg_TKR_intent (fsym, typebound, type, kind,
5123627f7eb2Smrg 				     0, intent);
5124627f7eb2Smrg 	  break;
5125627f7eb2Smrg 	case(4):			/* VLIST  */
5126627f7eb2Smrg 	  type = BT_INTEGER;
5127627f7eb2Smrg 	  kind = gfc_default_integer_kind;
5128627f7eb2Smrg 	  intent = INTENT_IN;
5129627f7eb2Smrg 	  check_dtio_arg_TKR_intent (fsym, typebound, type, kind,
5130627f7eb2Smrg 				     1, intent);
5131627f7eb2Smrg 	  break;
5132627f7eb2Smrg 	case(5):			/* IOSTAT  */
5133627f7eb2Smrg 	  type = BT_INTEGER;
5134627f7eb2Smrg 	  kind = gfc_default_integer_kind;
5135627f7eb2Smrg 	  intent = INTENT_OUT;
5136627f7eb2Smrg 	  check_dtio_arg_TKR_intent (fsym, typebound, type, kind,
5137627f7eb2Smrg 				     0, intent);
5138627f7eb2Smrg 	  break;
5139627f7eb2Smrg 	case(6):			/* IOMSG  */
5140627f7eb2Smrg 	  type = BT_CHARACTER;
5141627f7eb2Smrg 	  kind = gfc_default_character_kind;
5142627f7eb2Smrg 	  intent = INTENT_INOUT;
5143627f7eb2Smrg 	  check_dtio_arg_TKR_intent (fsym, typebound, type, kind,
5144627f7eb2Smrg 				     0, intent);
5145627f7eb2Smrg 	  break;
5146627f7eb2Smrg 	default:
5147627f7eb2Smrg 	  gcc_unreachable ();
5148627f7eb2Smrg 	}
5149627f7eb2Smrg     }
5150627f7eb2Smrg   derived->attr.has_dtio_procs = 1;
5151627f7eb2Smrg   return;
5152627f7eb2Smrg }
5153627f7eb2Smrg 
5154627f7eb2Smrg void
gfc_check_dtio_interfaces(gfc_symbol * derived)5155627f7eb2Smrg gfc_check_dtio_interfaces (gfc_symbol *derived)
5156627f7eb2Smrg {
5157627f7eb2Smrg   gfc_symtree *tb_io_st;
5158627f7eb2Smrg   bool t = false;
5159627f7eb2Smrg   int code;
5160627f7eb2Smrg   bool formatted;
5161627f7eb2Smrg 
5162627f7eb2Smrg   if (derived->attr.is_class == 1 || derived->attr.vtype == 1)
5163627f7eb2Smrg     return;
5164627f7eb2Smrg 
5165627f7eb2Smrg   /* Check typebound DTIO bindings.  */
5166627f7eb2Smrg   for (code = 0; code < 4; code++)
5167627f7eb2Smrg     {
5168627f7eb2Smrg       formatted = ((dtio_codes)code == DTIO_RF)
5169627f7eb2Smrg 		   || ((dtio_codes)code == DTIO_WF);
5170627f7eb2Smrg 
5171627f7eb2Smrg       tb_io_st = gfc_find_typebound_proc (derived, &t,
5172627f7eb2Smrg 					  gfc_code2string (dtio_procs, code),
5173627f7eb2Smrg 					  true, &derived->declared_at);
5174627f7eb2Smrg       if (tb_io_st != NULL)
5175627f7eb2Smrg 	check_dtio_interface1 (derived, tb_io_st, true, formatted, code);
5176627f7eb2Smrg     }
5177627f7eb2Smrg 
5178627f7eb2Smrg   /* Check generic DTIO interfaces.  */
5179627f7eb2Smrg   for (code = 0; code < 4; code++)
5180627f7eb2Smrg     {
5181627f7eb2Smrg       formatted = ((dtio_codes)code == DTIO_RF)
5182627f7eb2Smrg 		   || ((dtio_codes)code == DTIO_WF);
5183627f7eb2Smrg 
5184627f7eb2Smrg       tb_io_st = gfc_find_symtree (derived->ns->sym_root,
5185627f7eb2Smrg 				   gfc_code2string (dtio_procs, code));
5186627f7eb2Smrg       if (tb_io_st != NULL)
5187627f7eb2Smrg 	check_dtio_interface1 (derived, tb_io_st, false, formatted, code);
5188627f7eb2Smrg     }
5189627f7eb2Smrg }
5190627f7eb2Smrg 
5191627f7eb2Smrg 
5192627f7eb2Smrg gfc_symtree*
gfc_find_typebound_dtio_proc(gfc_symbol * derived,bool write,bool formatted)5193627f7eb2Smrg gfc_find_typebound_dtio_proc (gfc_symbol *derived, bool write, bool formatted)
5194627f7eb2Smrg {
5195627f7eb2Smrg   gfc_symtree *tb_io_st = NULL;
5196627f7eb2Smrg   bool t = false;
5197627f7eb2Smrg 
51984c3eb207Smrg   if (!derived || !derived->resolve_symbol_called
51994c3eb207Smrg       || derived->attr.flavor != FL_DERIVED)
5200627f7eb2Smrg     return NULL;
5201627f7eb2Smrg 
5202627f7eb2Smrg   /* Try to find a typebound DTIO binding.  */
5203627f7eb2Smrg   if (formatted == true)
5204627f7eb2Smrg     {
5205627f7eb2Smrg       if (write == true)
5206627f7eb2Smrg         tb_io_st = gfc_find_typebound_proc (derived, &t,
5207627f7eb2Smrg 					    gfc_code2string (dtio_procs,
5208627f7eb2Smrg 							     DTIO_WF),
5209627f7eb2Smrg 					    true,
5210627f7eb2Smrg 					    &derived->declared_at);
5211627f7eb2Smrg       else
5212627f7eb2Smrg         tb_io_st = gfc_find_typebound_proc (derived, &t,
5213627f7eb2Smrg 					    gfc_code2string (dtio_procs,
5214627f7eb2Smrg 							     DTIO_RF),
5215627f7eb2Smrg 					    true,
5216627f7eb2Smrg 					    &derived->declared_at);
5217627f7eb2Smrg     }
5218627f7eb2Smrg   else
5219627f7eb2Smrg     {
5220627f7eb2Smrg       if (write == true)
5221627f7eb2Smrg         tb_io_st = gfc_find_typebound_proc (derived, &t,
5222627f7eb2Smrg 					    gfc_code2string (dtio_procs,
5223627f7eb2Smrg 							     DTIO_WUF),
5224627f7eb2Smrg 					    true,
5225627f7eb2Smrg 					    &derived->declared_at);
5226627f7eb2Smrg       else
5227627f7eb2Smrg         tb_io_st = gfc_find_typebound_proc (derived, &t,
5228627f7eb2Smrg 					    gfc_code2string (dtio_procs,
5229627f7eb2Smrg 							     DTIO_RUF),
5230627f7eb2Smrg 					    true,
5231627f7eb2Smrg 					    &derived->declared_at);
5232627f7eb2Smrg     }
5233627f7eb2Smrg   return tb_io_st;
5234627f7eb2Smrg }
5235627f7eb2Smrg 
5236627f7eb2Smrg 
5237627f7eb2Smrg gfc_symbol *
gfc_find_specific_dtio_proc(gfc_symbol * derived,bool write,bool formatted)5238627f7eb2Smrg gfc_find_specific_dtio_proc (gfc_symbol *derived, bool write, bool formatted)
5239627f7eb2Smrg {
5240627f7eb2Smrg   gfc_symtree *tb_io_st = NULL;
5241627f7eb2Smrg   gfc_symbol *dtio_sub = NULL;
5242627f7eb2Smrg   gfc_symbol *extended;
5243627f7eb2Smrg   gfc_typebound_proc *tb_io_proc, *specific_proc;
5244627f7eb2Smrg 
5245627f7eb2Smrg   tb_io_st = gfc_find_typebound_dtio_proc (derived, write, formatted);
5246627f7eb2Smrg 
5247627f7eb2Smrg   if (tb_io_st != NULL)
5248627f7eb2Smrg     {
5249627f7eb2Smrg       const char *genname;
5250627f7eb2Smrg       gfc_symtree *st;
5251627f7eb2Smrg 
5252627f7eb2Smrg       tb_io_proc = tb_io_st->n.tb;
5253627f7eb2Smrg       gcc_assert (tb_io_proc != NULL);
5254627f7eb2Smrg       gcc_assert (tb_io_proc->is_generic);
5255627f7eb2Smrg       gcc_assert (tb_io_proc->u.generic->next == NULL);
5256627f7eb2Smrg 
5257627f7eb2Smrg       specific_proc = tb_io_proc->u.generic->specific;
5258627f7eb2Smrg       gcc_assert (!specific_proc->is_generic);
5259627f7eb2Smrg 
5260627f7eb2Smrg       /* Go back and make sure that we have the right specific procedure.
5261627f7eb2Smrg 	 Here we most likely have a procedure from the parent type, which
5262627f7eb2Smrg 	 can be overridden in extensions.  */
5263627f7eb2Smrg       genname = tb_io_proc->u.generic->specific_st->name;
5264627f7eb2Smrg       st = gfc_find_typebound_proc (derived, NULL, genname,
5265627f7eb2Smrg 				    true, &tb_io_proc->where);
5266627f7eb2Smrg       if (st)
5267627f7eb2Smrg 	dtio_sub = st->n.tb->u.specific->n.sym;
5268627f7eb2Smrg       else
5269627f7eb2Smrg 	dtio_sub = specific_proc->u.specific->n.sym;
5270627f7eb2Smrg 
5271627f7eb2Smrg       goto finish;
5272627f7eb2Smrg     }
5273627f7eb2Smrg 
5274627f7eb2Smrg   /* If there is not a typebound binding, look for a generic
5275627f7eb2Smrg      DTIO interface.  */
5276627f7eb2Smrg   for (extended = derived; extended;
5277627f7eb2Smrg        extended = gfc_get_derived_super_type (extended))
5278627f7eb2Smrg     {
5279627f7eb2Smrg       if (extended == NULL || extended->ns == NULL
5280627f7eb2Smrg 	  || extended->attr.flavor == FL_UNKNOWN)
5281627f7eb2Smrg 	return NULL;
5282627f7eb2Smrg 
5283627f7eb2Smrg       if (formatted == true)
5284627f7eb2Smrg 	{
5285627f7eb2Smrg 	  if (write == true)
5286627f7eb2Smrg 	    tb_io_st = gfc_find_symtree (extended->ns->sym_root,
5287627f7eb2Smrg 					 gfc_code2string (dtio_procs,
5288627f7eb2Smrg 							  DTIO_WF));
5289627f7eb2Smrg 	  else
5290627f7eb2Smrg 	    tb_io_st = gfc_find_symtree (extended->ns->sym_root,
5291627f7eb2Smrg 					 gfc_code2string (dtio_procs,
5292627f7eb2Smrg 							  DTIO_RF));
5293627f7eb2Smrg 	}
5294627f7eb2Smrg       else
5295627f7eb2Smrg 	{
5296627f7eb2Smrg 	  if (write == true)
5297627f7eb2Smrg 	    tb_io_st = gfc_find_symtree (extended->ns->sym_root,
5298627f7eb2Smrg 					 gfc_code2string (dtio_procs,
5299627f7eb2Smrg 							  DTIO_WUF));
5300627f7eb2Smrg 	  else
5301627f7eb2Smrg 	    tb_io_st = gfc_find_symtree (extended->ns->sym_root,
5302627f7eb2Smrg 					 gfc_code2string (dtio_procs,
5303627f7eb2Smrg 							  DTIO_RUF));
5304627f7eb2Smrg 	}
5305627f7eb2Smrg 
5306627f7eb2Smrg       if (tb_io_st != NULL
5307627f7eb2Smrg 	  && tb_io_st->n.sym
5308627f7eb2Smrg 	  && tb_io_st->n.sym->generic)
5309627f7eb2Smrg 	{
5310627f7eb2Smrg 	  for (gfc_interface *intr = tb_io_st->n.sym->generic;
5311627f7eb2Smrg 	       intr && intr->sym; intr = intr->next)
5312627f7eb2Smrg 	    {
5313627f7eb2Smrg 	      if (intr->sym->formal)
5314627f7eb2Smrg 		{
5315627f7eb2Smrg 		  gfc_symbol *fsym = intr->sym->formal->sym;
5316627f7eb2Smrg 		  if ((fsym->ts.type == BT_CLASS
5317627f7eb2Smrg 		      && CLASS_DATA (fsym)->ts.u.derived == extended)
5318627f7eb2Smrg 		      || (fsym->ts.type == BT_DERIVED
5319627f7eb2Smrg 			  && fsym->ts.u.derived == extended))
5320627f7eb2Smrg 		    {
5321627f7eb2Smrg 		      dtio_sub = intr->sym;
5322627f7eb2Smrg 		      break;
5323627f7eb2Smrg 		    }
5324627f7eb2Smrg 		}
5325627f7eb2Smrg 	    }
5326627f7eb2Smrg 	}
5327627f7eb2Smrg     }
5328627f7eb2Smrg 
5329627f7eb2Smrg finish:
5330627f7eb2Smrg   if (dtio_sub && derived != CLASS_DATA (dtio_sub->formal->sym)->ts.u.derived)
5331627f7eb2Smrg     gfc_find_derived_vtab (derived);
5332627f7eb2Smrg 
5333627f7eb2Smrg   return dtio_sub;
5334627f7eb2Smrg }
53354c3eb207Smrg 
53364c3eb207Smrg /* Helper function - if we do not find an interface for a procedure,
53374c3eb207Smrg    construct it from the actual arglist.  Luckily, this can only
53384c3eb207Smrg    happen for call by reference, so the information we actually need
53394c3eb207Smrg    to provide (and which would be impossible to guess from the call
53404c3eb207Smrg    itself) is not actually needed.  */
53414c3eb207Smrg 
53424c3eb207Smrg void
gfc_get_formal_from_actual_arglist(gfc_symbol * sym,gfc_actual_arglist * actual_args)53434c3eb207Smrg gfc_get_formal_from_actual_arglist (gfc_symbol *sym,
53444c3eb207Smrg 				    gfc_actual_arglist *actual_args)
53454c3eb207Smrg {
53464c3eb207Smrg   gfc_actual_arglist *a;
53474c3eb207Smrg   gfc_formal_arglist **f;
53484c3eb207Smrg   gfc_symbol *s;
53494c3eb207Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
53504c3eb207Smrg   static int var_num;
53514c3eb207Smrg 
53524c3eb207Smrg   f = &sym->formal;
53534c3eb207Smrg   for (a = actual_args; a != NULL; a = a->next)
53544c3eb207Smrg     {
53554c3eb207Smrg       (*f) = gfc_get_formal_arglist ();
53564c3eb207Smrg       if (a->expr)
53574c3eb207Smrg 	{
53584c3eb207Smrg 	  snprintf (name, GFC_MAX_SYMBOL_LEN, "_formal_%d", var_num ++);
53594c3eb207Smrg 	  gfc_get_symbol (name, gfc_current_ns, &s);
53604c3eb207Smrg 	  if (a->expr->ts.type == BT_PROCEDURE)
53614c3eb207Smrg 	    {
53624c3eb207Smrg 	      s->attr.flavor = FL_PROCEDURE;
53634c3eb207Smrg 	    }
53644c3eb207Smrg 	  else
53654c3eb207Smrg 	    {
53664c3eb207Smrg 	      s->ts = a->expr->ts;
53674c3eb207Smrg 
53684c3eb207Smrg 	      if (s->ts.type == BT_CHARACTER)
53694c3eb207Smrg 		s->ts.u.cl = gfc_get_charlen ();
53704c3eb207Smrg 
53714c3eb207Smrg 	      s->ts.deferred = 0;
53724c3eb207Smrg 	      s->ts.is_iso_c = 0;
53734c3eb207Smrg 	      s->ts.is_c_interop = 0;
53744c3eb207Smrg 	      s->attr.flavor = FL_VARIABLE;
53754c3eb207Smrg 	      if (a->expr->rank > 0)
53764c3eb207Smrg 		{
53774c3eb207Smrg 		  s->attr.dimension = 1;
53784c3eb207Smrg 		  s->as = gfc_get_array_spec ();
53794c3eb207Smrg 		  s->as->rank = 1;
53804c3eb207Smrg 		  s->as->lower[0] = gfc_get_int_expr (gfc_index_integer_kind,
53814c3eb207Smrg 						      &a->expr->where, 1);
53824c3eb207Smrg 		  s->as->upper[0] = NULL;
53834c3eb207Smrg 		  s->as->type = AS_ASSUMED_SIZE;
53844c3eb207Smrg 		}
53854c3eb207Smrg 	      else
53864c3eb207Smrg 		s->maybe_array = maybe_dummy_array_arg (a->expr);
53874c3eb207Smrg 	    }
53884c3eb207Smrg 	  s->attr.dummy = 1;
53894c3eb207Smrg 	  s->attr.artificial = 1;
53904c3eb207Smrg 	  s->declared_at = a->expr->where;
53914c3eb207Smrg 	  s->attr.intent = INTENT_UNKNOWN;
53924c3eb207Smrg 	  (*f)->sym = s;
53934c3eb207Smrg 	}
53944c3eb207Smrg       else  /* If a->expr is NULL, this is an alternate rerturn.  */
53954c3eb207Smrg 	(*f)->sym = NULL;
53964c3eb207Smrg 
53974c3eb207Smrg       f = &((*f)->next);
53984c3eb207Smrg     }
53994c3eb207Smrg }
5400