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 4439218 : strings_same (const char *s1, const char *s2)
91 : {
92 4439218 : 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 760955 : options_same (const struct cl_decoded_option *opt1,
100 : const struct cl_decoded_option *opt2)
101 : {
102 760955 : return (opt1->opt_index == opt2->opt_index
103 760953 : && strings_same (opt1->arg, opt2->arg)
104 735653 : && strings_same (opt1->orig_option_with_args_text,
105 735653 : opt2->orig_option_with_args_text)
106 735653 : && strings_same (opt1->canonical_option[0],
107 735653 : opt2->canonical_option[0])
108 735653 : && strings_same (opt1->canonical_option[1],
109 735653 : opt2->canonical_option[1])
110 735653 : && strings_same (opt1->canonical_option[2],
111 735653 : opt2->canonical_option[2])
112 735653 : && strings_same (opt1->canonical_option[3],
113 735653 : opt2->canonical_option[3])
114 735653 : && (opt1->canonical_option_num_elements
115 735653 : == opt2->canonical_option_num_elements)
116 735653 : && opt1->value == opt2->value
117 1496608 : && 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 887748 : append_arg (const struct cl_decoded_option *arg)
126 : {
127 887748 : static unsigned int newargsize;
128 :
129 887748 : if (g77_new_decoded_options == g77_x_decoded_options
130 761048 : && g77_newargc < g77_xargc
131 1648703 : && options_same (arg, &g77_x_decoded_options[g77_newargc]))
132 : {
133 735653 : ++g77_newargc;
134 735653 : return; /* Nothing new here. */
135 : }
136 :
137 152095 : if (g77_new_decoded_options == g77_x_decoded_options)
138 : { /* Make new arglist. */
139 25395 : unsigned int i;
140 :
141 25395 : newargsize = (g77_xargc << 2) + 20; /* This should handle all. */
142 25395 : g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
143 :
144 : /* Copy what has been done so far. */
145 567900 : for (i = 0; i < g77_newargc; ++i)
146 542505 : g77_new_decoded_options[i] = g77_x_decoded_options[i];
147 : }
148 :
149 152095 : 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 152095 : 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 101489 : append_option (size_t opt_index, const char *arg, int value)
160 : {
161 101489 : struct cl_decoded_option decoded;
162 :
163 101489 : generate_option (opt_index, arg, value, CL_DRIVER, &decoded);
164 101489 : append_arg (&decoded);
165 101489 : }
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 50697 : add_arg_libgfortran (bool force_static ATTRIBUTE_UNUSED)
172 : {
173 : #ifdef HAVE_LD_STATIC_DYNAMIC
174 50697 : if (force_static)
175 4 : append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
176 : #endif
177 50697 : append_option (OPT_l, FORTRAN_LIBRARY, 1);
178 : #ifdef HAVE_LD_STATIC_DYNAMIC
179 50697 : if (force_static)
180 4 : append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
181 : #endif
182 50697 : }
183 :
184 : void
185 35172 : 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 35172 : unsigned int argc = *in_decoded_options_count;
190 35172 : struct cl_decoded_option *decoded_options = *in_decoded_options;
191 35172 : unsigned int i;
192 35172 : int verbose = 0;
193 :
194 : /* 0 => -xnone in effect.
195 : 1 => -xfoo in effect. */
196 35172 : 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 35172 : int saw_library = 0;
202 :
203 : /* By default, we throw on the math library if we have one. */
204 35172 : int need_math = (MATH_LIBRARY[0] != '\0');
205 :
206 : /* Whether we should link a static libgfortran. */
207 35172 : int static_lib = 0;
208 :
209 : /* Whether we need to link statically. */
210 35172 : int static_linking = 0;
211 :
212 : /* Whether -fcoarray=shared was given; triggers auto-link of -lcaf_shmem. */
213 35172 : int need_caf_shmem = 0;
214 :
215 : /* The number of input and output files in the incoming arg list. */
216 35172 : int n_infiles = 0;
217 35172 : int n_outfiles = 0;
218 :
219 35172 : 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 35172 : g77_xargc = argc;
229 35172 : g77_x_decoded_options = decoded_options;
230 35172 : g77_newargc = 0;
231 35172 : 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 786290 : for (i = 1; i < argc; ++i)
240 : {
241 751122 : if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
242 0 : continue;
243 :
244 751122 : switch (decoded_options[i].opt_index)
245 : {
246 35381 : case OPT_SPECIAL_input_file:
247 35381 : ++n_infiles;
248 35381 : continue;
249 :
250 8576 : case OPT_nostdlib:
251 8576 : case OPT_nodefaultlibs:
252 8576 : case OPT_c:
253 8576 : case OPT_r:
254 8576 : case OPT_S:
255 8576 : case OPT_fsyntax_only:
256 8576 : case OPT_E:
257 : /* These options disable linking entirely or linking of the
258 : standard libraries. */
259 8576 : library = 0;
260 8576 : break;
261 :
262 : case OPT_static_libgfortran:
263 : #ifdef HAVE_LD_STATIC_DYNAMIC
264 751118 : 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 25974 : case OPT_l:
275 25974 : ++n_infiles;
276 25974 : break;
277 :
278 33322 : case OPT_o:
279 33322 : ++n_outfiles;
280 33322 : break;
281 :
282 825 : case OPT_fcoarray_:
283 825 : if (decoded_options[i].value == GFC_FCOARRAY_SHARED)
284 751118 : need_caf_shmem = 1;
285 : break;
286 :
287 191 : case OPT_v:
288 191 : verbose = 1;
289 191 : 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 35168 : 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 35168 : if (n_infiles == 0)
317 1285 : library = 0;
318 :
319 : /* Second pass through arglist, transforming arguments as appropriate. */
320 :
321 35168 : append_arg (&decoded_options[0]); /* Start with command name, of course. */
322 :
323 786262 : for (i = 1; i < argc; ++i)
324 : {
325 751094 : if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
326 : {
327 0 : append_arg (&decoded_options[i]);
328 0 : continue;
329 : }
330 :
331 751094 : if (decoded_options[i].opt_index == OPT_SPECIAL_input_file
332 35381 : && 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 751094 : if (decoded_options[i].opt_index != OPT_l
340 725120 : && (decoded_options[i].opt_index != OPT_SPECIAL_input_file
341 35381 : || strcmp (decoded_options[i].arg, "-") == 0))
342 : {
343 : /* Not a filename or library. */
344 :
345 689739 : if (saw_library == 1 && need_math) /* -l<library>. */
346 0 : append_option (OPT_l, MATH_LIBRARY, 1);
347 :
348 689739 : saw_library = 0;
349 :
350 689739 : 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 689739 : if (decoded_options[i].opt_index == OPT_x)
357 : {
358 : /* Track input language. */
359 978 : const char *lang = decoded_options[i].arg;
360 :
361 978 : 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 689739 : 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 689738 : append_arg (&decoded_options[i]);
375 :
376 689738 : continue;
377 689738 : }
378 :
379 : /* A filename/library, not an option. */
380 :
381 61355 : if (saw_speclang)
382 : saw_library = 0; /* -xfoo currently active. */
383 : else
384 : { /* -lfoo or filename. */
385 60300 : if (decoded_options[i].opt_index == OPT_l
386 25974 : && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0)
387 : {
388 25300 : if (saw_library == 1)
389 : saw_library = 2; /* -l<library> -lm. */
390 : else
391 25300 : add_arg_libgfortran (static_lib && !static_linking);
392 : }
393 35000 : else if (decoded_options[i].opt_index == OPT_l
394 674 : && 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 34998 : if (saw_library == 1 && need_math)
403 2 : append_option (OPT_l, MATH_LIBRARY, 1);
404 : saw_library = 0;
405 : }
406 : }
407 61353 : append_arg (&decoded_options[i]);
408 : }
409 :
410 : /* Append `-lgfortran -lm' as necessary. */
411 :
412 35168 : if (library)
413 : { /* Doing a link and no -nostdlib. */
414 25395 : if (saw_speclang)
415 0 : append_option (OPT_x, "none", 1);
416 :
417 25395 : switch (saw_library)
418 : {
419 25395 : case 0:
420 25395 : add_arg_libgfortran (static_lib && !static_linking);
421 : /* Fall through. */
422 :
423 25395 : case 1:
424 25395 : if (need_math)
425 25395 : append_option (OPT_l, MATH_LIBRARY, 1);
426 25395 : default:
427 25395 : break;
428 : }
429 :
430 25395 : if (need_caf_shmem)
431 : {
432 1 : append_option (OPT_l, CAF_SHMEM_LIBRARY, 1);
433 1 : append_option (OPT_l, "pthread", 1);
434 : }
435 : }
436 :
437 : #ifdef ENABLE_SHARED_LIBGCC
438 35168 : if (library)
439 : {
440 : unsigned int i;
441 :
442 669125 : for (i = 1; i < g77_newargc; i++)
443 643741 : if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc
444 643741 : || g77_new_decoded_options[i].opt_index == OPT_static)
445 : break;
446 :
447 25395 : if (i == g77_newargc)
448 25384 : append_option (OPT_shared_libgcc, NULL, 1);
449 : }
450 :
451 : #endif
452 :
453 35168 : if (verbose && g77_new_decoded_options != g77_x_decoded_options)
454 : {
455 0 : fprintf (stderr, _("Driving:"));
456 0 : for (i = 0; i < g77_newargc; i++)
457 0 : fprintf (stderr, " %s",
458 0 : g77_new_decoded_options[i].orig_option_with_args_text);
459 0 : fprintf (stderr, "\n");
460 : }
461 :
462 35168 : *in_decoded_options_count = g77_newargc;
463 35168 : *in_decoded_options = g77_new_decoded_options;
464 : }
465 :
466 :
467 : /* Called before linking. Returns 0 on success and -1 on failure. */
468 : int
469 31448 : lang_specific_pre_link (void)
470 : {
471 31448 : if (library)
472 25392 : do_spec ("%:include(libgfortran.spec)");
473 :
474 31448 : return 0;
475 : }
476 :
477 : /* Number of extra output files that lang_specific_pre_link may generate. */
478 : int lang_specific_extra_outfiles = 0; /* Not used for F77. */
|