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 = ¤t_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 = ¤t_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 = ¤t_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