Line data Source code
1 : /* Specific flags and argument handling of the Fortran front-end.
2 : Copyright (C) 1997-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GNU CC is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3, or (at your option)
9 : any later version.
10 :
11 : GNU CC is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : /* This file is copied more or less verbatim from g77. */
21 : /* This file contains a filter for the main `gcc' driver, which is
22 : replicated for the `gfortran' driver by adding this filter. The purpose
23 : of this filter is to be basically identical to gcc (in that
24 : it faithfully passes all of the original arguments to gcc) but,
25 : unless explicitly overridden by the user in certain ways, ensure
26 : that the needs of the language supported by this wrapper are met.
27 :
28 : For GNU Fortran 95(gfortran), we do the following to the argument list
29 : before passing it to `gcc':
30 :
31 : 1. Make sure `-lgfortran -lm' is at the end of the list.
32 :
33 : 2. Make sure each time `-lgfortran' or `-lm' is seen, it forms
34 : part of the series `-lgfortran -lm'.
35 :
36 : #1 and #2 are not done if `-nostdlib' or any option that disables
37 : the linking phase is present, or if `-xfoo' is in effect. Note that
38 : a lack of source files or -l options disables linking.
39 :
40 : This program was originally made out of gcc/cp/g++spec.cc, but the
41 : way it builds the new argument list was rewritten so it is much
42 : easier to maintain, improve the way it decides to add or not add
43 : extra arguments, etc. And several improvements were made in the
44 : handling of arguments, primarily to make it more consistent with
45 : `gcc' itself. */
46 :
47 : #include "config.h"
48 : #include "system.h"
49 : #include "coretypes.h"
50 : #include "opt-suggestions.h"
51 : #include "gcc.h"
52 : #include "opts.h"
53 :
54 : #include "tm.h"
55 : #include "intl.h"
56 :
57 : #ifndef MATH_LIBRARY
58 : #define MATH_LIBRARY "m"
59 : #endif
60 :
61 : #ifndef FORTRAN_LIBRARY
62 : #define FORTRAN_LIBRARY "gfortran"
63 : #endif
64 :
65 : #ifndef CAF_SHMEM_LIBRARY
66 : #define CAF_SHMEM_LIBRARY "caf_shmem"
67 : #endif
68 :
69 : /* Name of the spec file. */
70 : #define SPEC_FILE "libgfortran.spec"
71 :
72 : /* The original argument list and related info is copied here. */
73 : static unsigned int g77_xargc;
74 : static const struct cl_decoded_option *g77_x_decoded_options;
75 : static void append_arg (const struct cl_decoded_option *);
76 :
77 : /* The new argument list will be built here. */
78 : static unsigned int g77_newargc;
79 : static struct cl_decoded_option *g77_new_decoded_options;
80 :
81 : /* This will be NULL if we encounter a situation where we should not
82 : link in the fortran libraries. */
83 : static const char *library = NULL;
84 :
85 :
86 : /* Return whether strings S1 and S2 are both NULL or both the same
87 : string. */
88 :
89 : static bool
90 4314153 : strings_same (const char *s1, const char *s2)
91 : {
92 4314153 : return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0);
93 : }
94 :
95 : /* Return whether decoded option structures OPT1 and OPT2 are the
96 : same. */
97 :
98 : static bool
99 739840 : options_same (const struct cl_decoded_option *opt1,
100 : const struct cl_decoded_option *opt2)
101 : {
102 739840 : return (opt1->opt_index == opt2->opt_index
103 739838 : && strings_same (opt1->arg, opt2->arg)
104 714863 : && strings_same (opt1->orig_option_with_args_text,
105 714863 : opt2->orig_option_with_args_text)
106 714863 : && strings_same (opt1->canonical_option[0],
107 714863 : opt2->canonical_option[0])
108 714863 : && strings_same (opt1->canonical_option[1],
109 714863 : opt2->canonical_option[1])
110 714863 : && strings_same (opt1->canonical_option[2],
111 714863 : opt2->canonical_option[2])
112 714863 : && strings_same (opt1->canonical_option[3],
113 714863 : opt2->canonical_option[3])
114 714863 : && (opt1->canonical_option_num_elements
115 714863 : == opt2->canonical_option_num_elements)
116 714863 : && opt1->value == opt2->value
117 1454703 : && opt1->errors == opt2->errors);
118 : }
119 :
120 : /* Append another argument to the list being built. As long as it is
121 : identical to the corresponding arg in the original list, just increment
122 : the new arg count. Otherwise allocate a new list, etc. */
123 :
124 : static void
125 864989 : append_arg (const struct cl_decoded_option *arg)
126 : {
127 864989 : static unsigned int newargsize;
128 :
129 864989 : if (g77_new_decoded_options == g77_x_decoded_options
130 739927 : && g77_newargc < g77_xargc
131 1604829 : && options_same (arg, &g77_x_decoded_options[g77_newargc]))
132 : {
133 714863 : ++g77_newargc;
134 714863 : return; /* Nothing new here. */
135 : }
136 :
137 150126 : if (g77_new_decoded_options == g77_x_decoded_options)
138 : { /* Make new arglist. */
139 25064 : unsigned int i;
140 :
141 25064 : newargsize = (g77_xargc << 2) + 20; /* This should handle all. */
142 25064 : g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
143 :
144 : /* Copy what has been done so far. */
145 560535 : for (i = 0; i < g77_newargc; ++i)
146 535471 : g77_new_decoded_options[i] = g77_x_decoded_options[i];
147 : }
148 :
149 150126 : if (g77_newargc == newargsize)
150 0 : fatal_error (input_location, "overflowed output argument list for %qs",
151 0 : arg->orig_option_with_args_text);
152 :
153 150126 : g77_new_decoded_options[g77_newargc++] = *arg;
154 : }
155 :
156 : /* Append an option described by OPT_INDEX, ARG and VALUE to the list
157 : being built. */
158 : static void
159 100170 : append_option (size_t opt_index, const char *arg, int value)
160 : {
161 100170 : struct cl_decoded_option decoded;
162 :
163 100170 : generate_option (opt_index, arg, value, CL_DRIVER, &decoded);
164 100170 : append_arg (&decoded);
165 100170 : }
166 :
167 : /* Append a libgfortran argument to the list being built. If
168 : FORCE_STATIC, ensure the library is linked statically. */
169 :
170 : static void
171 50041 : add_arg_libgfortran (bool force_static ATTRIBUTE_UNUSED)
172 : {
173 : #ifdef HAVE_LD_STATIC_DYNAMIC
174 50041 : if (force_static)
175 4 : append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
176 : #endif
177 50041 : append_option (OPT_l, FORTRAN_LIBRARY, 1);
178 : #ifdef HAVE_LD_STATIC_DYNAMIC
179 50041 : if (force_static)
180 4 : append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
181 : #endif
182 50041 : }
183 :
184 : void
185 33984 : lang_specific_driver (struct cl_decoded_option **in_decoded_options,
186 : unsigned int *in_decoded_options_count,
187 : int *in_added_libraries ATTRIBUTE_UNUSED)
188 : {
189 33984 : unsigned int argc = *in_decoded_options_count;
190 33984 : struct cl_decoded_option *decoded_options = *in_decoded_options;
191 33984 : unsigned int i;
192 33984 : int verbose = 0;
193 :
194 : /* 0 => -xnone in effect.
195 : 1 => -xfoo in effect. */
196 33984 : int saw_speclang = 0;
197 :
198 : /* 0 => initial/reset state
199 : 1 => last arg was -l<library>
200 : 2 => last two args were -l<library> -lm. */
201 33984 : int saw_library = 0;
202 :
203 : /* By default, we throw on the math library if we have one. */
204 33984 : int need_math = (MATH_LIBRARY[0] != '\0');
205 :
206 : /* Whether we should link a static libgfortran. */
207 33984 : int static_lib = 0;
208 :
209 : /* Whether we need to link statically. */
210 33984 : int static_linking = 0;
211 :
212 : /* Whether -fcoarray=shared was given; triggers auto-link of -lcaf_shmem. */
213 33984 : int need_caf_shmem = 0;
214 :
215 : /* The number of input and output files in the incoming arg list. */
216 33984 : int n_infiles = 0;
217 33984 : int n_outfiles = 0;
218 :
219 33984 : library = FORTRAN_LIBRARY;
220 :
221 : #if 0
222 : fprintf (stderr, "Incoming:");
223 : for (i = 0; i < argc; i++)
224 : fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text);
225 : fprintf (stderr, "\n");
226 : #endif
227 :
228 33984 : g77_xargc = argc;
229 33984 : g77_x_decoded_options = decoded_options;
230 33984 : g77_newargc = 0;
231 33984 : g77_new_decoded_options = decoded_options;
232 :
233 : /* First pass through arglist.
234 :
235 : If -nostdlib or a "turn-off-linking" option is anywhere in the
236 : command line, don't do any library-option processing (except
237 : relating to -x). */
238 :
239 764850 : for (i = 1; i < argc; ++i)
240 : {
241 730870 : if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
242 0 : continue;
243 :
244 730870 : switch (decoded_options[i].opt_index)
245 : {
246 34619 : case OPT_SPECIAL_input_file:
247 34619 : ++n_infiles;
248 34619 : continue;
249 :
250 8157 : case OPT_nostdlib:
251 8157 : case OPT_nodefaultlibs:
252 8157 : case OPT_c:
253 8157 : case OPT_r:
254 8157 : case OPT_S:
255 8157 : case OPT_fsyntax_only:
256 8157 : case OPT_E:
257 : /* These options disable linking entirely or linking of the
258 : standard libraries. */
259 8157 : library = 0;
260 8157 : break;
261 :
262 : case OPT_static_libgfortran:
263 : #ifdef HAVE_LD_STATIC_DYNAMIC
264 730866 : static_lib = 1;
265 : #endif
266 : break;
267 :
268 11 : case OPT_static:
269 : #ifdef HAVE_LD_STATIC_DYNAMIC
270 11 : static_linking = 1;
271 : #endif
272 11 : break;
273 :
274 25648 : case OPT_l:
275 25648 : ++n_infiles;
276 25648 : break;
277 :
278 32710 : case OPT_o:
279 32710 : ++n_outfiles;
280 32710 : break;
281 :
282 825 : case OPT_fcoarray_:
283 825 : if (decoded_options[i].value == GFC_FCOARRAY_SHARED)
284 730866 : need_caf_shmem = 1;
285 : break;
286 :
287 185 : case OPT_v:
288 185 : verbose = 1;
289 185 : break;
290 :
291 4 : case OPT__version:
292 4 : printf ("GNU Fortran %s%s\n", pkgversion_string, version_string);
293 4 : printf ("Copyright %s 2026 Free Software Foundation, Inc.\n",
294 : _("(C)"));
295 4 : fputs (_("This is free software; see the source for copying conditions. There is NO\n\
296 : warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
297 : stdout);
298 4 : exit (0);
299 : break;
300 :
301 : case OPT__help:
302 : /* Let gcc.cc handle this, as it has a really
303 : cool facility for handling --help and --verbose --help. */
304 : return;
305 :
306 : default:
307 : break;
308 : }
309 : }
310 :
311 33980 : if ((n_outfiles != 0) && (n_infiles == 0))
312 0 : fatal_error (input_location,
313 : "no input files; unwilling to write output files");
314 :
315 : /* If there are no input files, no need for the library. */
316 33980 : if (n_infiles == 0)
317 847 : library = 0;
318 :
319 : /* Second pass through arglist, transforming arguments as appropriate. */
320 :
321 33980 : append_arg (&decoded_options[0]); /* Start with command name, of course. */
322 :
323 764822 : for (i = 1; i < argc; ++i)
324 : {
325 730842 : if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
326 : {
327 0 : append_arg (&decoded_options[i]);
328 0 : continue;
329 : }
330 :
331 730842 : if (decoded_options[i].opt_index == OPT_SPECIAL_input_file
332 34619 : && decoded_options[i].arg[0] == '\0')
333 : {
334 : /* Interesting. Just append as is. */
335 0 : append_arg (&decoded_options[i]);
336 0 : continue;
337 : }
338 :
339 730842 : if (decoded_options[i].opt_index != OPT_l
340 705194 : && (decoded_options[i].opt_index != OPT_SPECIAL_input_file
341 34619 : || strcmp (decoded_options[i].arg, "-") == 0))
342 : {
343 : /* Not a filename or library. */
344 :
345 670575 : if (saw_library == 1 && need_math) /* -l<library>. */
346 0 : append_option (OPT_l, MATH_LIBRARY, 1);
347 :
348 670575 : saw_library = 0;
349 :
350 670575 : if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
351 : {
352 0 : append_arg (&decoded_options[i]); /* "-" == Standard input. */
353 0 : continue;
354 : }
355 :
356 670575 : if (decoded_options[i].opt_index == OPT_x)
357 : {
358 : /* Track input language. */
359 702 : const char *lang = decoded_options[i].arg;
360 :
361 702 : saw_speclang = (strcmp (lang, "none") != 0);
362 : }
363 :
364 : /* -fcoarray=shared is a driver-level alias for -fcoarray=lib that
365 : also arranges for -lcaf_shmem to be linked automatically. Pass
366 : -fcoarray=lib to cc1 so the frontend uses the library code path. */
367 670575 : if (decoded_options[i].opt_index == OPT_fcoarray_
368 825 : && decoded_options[i].value == GFC_FCOARRAY_SHARED)
369 : {
370 1 : append_option (OPT_fcoarray_, "lib", GFC_FCOARRAY_LIB);
371 1 : continue;
372 : }
373 :
374 670574 : append_arg (&decoded_options[i]);
375 :
376 670574 : continue;
377 670574 : }
378 :
379 : /* A filename/library, not an option. */
380 :
381 60267 : if (saw_speclang)
382 : saw_library = 0; /* -xfoo currently active. */
383 : else
384 : { /* -lfoo or filename. */
385 59488 : if (decoded_options[i].opt_index == OPT_l
386 25648 : && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0)
387 : {
388 24975 : if (saw_library == 1)
389 : saw_library = 2; /* -l<library> -lm. */
390 : else
391 24975 : add_arg_libgfortran (static_lib && !static_linking);
392 : }
393 34513 : else if (decoded_options[i].opt_index == OPT_l
394 673 : && strcmp (decoded_options[i].arg, FORTRAN_LIBRARY) == 0)
395 : {
396 2 : saw_library = 1; /* -l<library>. */
397 2 : add_arg_libgfortran (static_lib && !static_linking);
398 2 : continue;
399 : }
400 : else
401 : { /* Other library, or filename. */
402 34511 : if (saw_library == 1 && need_math)
403 2 : append_option (OPT_l, MATH_LIBRARY, 1);
404 : saw_library = 0;
405 : }
406 : }
407 60265 : append_arg (&decoded_options[i]);
408 : }
409 :
410 : /* Append `-lgfortran -lm' as necessary. */
411 :
412 33980 : if (library)
413 : { /* Doing a link and no -nostdlib. */
414 25064 : if (saw_speclang)
415 0 : append_option (OPT_x, "none", 1);
416 :
417 25064 : switch (saw_library)
418 : {
419 25064 : case 0:
420 25064 : add_arg_libgfortran (static_lib && !static_linking);
421 : /* Fall through. */
422 :
423 25064 : case 1:
424 25064 : if (need_math)
425 25064 : append_option (OPT_l, MATH_LIBRARY, 1);
426 25064 : default:
427 25064 : break;
428 : }
429 :
430 25064 : if (need_caf_shmem)
431 1 : append_option (OPT_l, CAF_SHMEM_LIBRARY, 1);
432 : }
433 :
434 : #ifdef ENABLE_SHARED_LIBGCC
435 33980 : if (library)
436 : {
437 : unsigned int i;
438 :
439 660453 : for (i = 1; i < g77_newargc; i++)
440 635400 : if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc
441 635400 : || g77_new_decoded_options[i].opt_index == OPT_static)
442 : break;
443 :
444 25064 : if (i == g77_newargc)
445 25053 : append_option (OPT_shared_libgcc, NULL, 1);
446 : }
447 :
448 : #endif
449 :
450 33980 : if (verbose && g77_new_decoded_options != g77_x_decoded_options)
451 : {
452 0 : fprintf (stderr, _("Driving:"));
453 0 : for (i = 0; i < g77_newargc; i++)
454 0 : fprintf (stderr, " %s",
455 0 : g77_new_decoded_options[i].orig_option_with_args_text);
456 0 : fprintf (stderr, "\n");
457 : }
458 :
459 33980 : *in_decoded_options_count = g77_newargc;
460 33980 : *in_decoded_options = g77_new_decoded_options;
461 : }
462 :
463 :
464 : /* Called before linking. Returns 0 on success and -1 on failure. */
465 : int
466 30725 : lang_specific_pre_link (void)
467 : {
468 30725 : if (library)
469 25061 : do_spec ("%:include(libgfortran.spec)");
470 :
471 30725 : return 0;
472 : }
473 :
474 : /* Number of extra output files that lang_specific_pre_link may generate. */
475 : int lang_specific_extra_outfiles = 0; /* Not used for F77. */
|