3.3.3.1.1. Options for C++
For C/C++ or obj-C, handle_options of lang_hooks is the same as c_common_handle_option. In below, OPT_* is used as index into cl_options.
251 int
252 c_common_handle_option (size_t scode, const char *arg, int value) in c-opts.c
253 {
254 const struct cl_option *option = &cl_options[scode];
255 enum opt_code code = (enum opt_code) scode;
256 int result = 1;
257
258 switch (code)
259 {
260 default:
261 result = permit_fortran_options;
262 break;
263
264 case OPT__output_pch_:
265 pch_file = arg;
266 break;
267
268 case OPT_A:
269 defer_opt (code, arg);
270 break;
271
272 case OPT_C:
273 cpp_opts->discard_comments = 0;
274 break;
275
276 case OPT_CC:
277 cpp_opts->discard_comments = 0;
278 cpp_opts->discard_comments_in_macro_exp = 0;
279 break;
280
281 case OPT_D:
282 defer_opt (code, arg);
283 break;
284
285 case OPT_E:
286 flag_preprocess_only = 1;
287 break;
288
289 case OPT_H:
290 cpp_opts->print_include_names = 1;
291 break;
292
293 case OPT_I:
294 if (strcmp (arg, "-"))
295 add_path (xstrdup (arg), BRACKET, 0);
296 else
297 {
298 if (quote_chain_split)
299 error ("-I- specified twice");
300 quote_chain_split = true;
301 split_quote_chain ();
302 }
303 break;
304
305 case OPT_M:
306 case OPT_MM:
307 /* When doing dependencies with -M or -MM, suppress normal
308 preprocessed output, but still do -dM etc. as software
309 depends on this. Preprocessed output does occur if -MD, -MMD
310 or environment var dependency generation is used. */
311 cpp_opts->deps.style = (code == OPT_M ? DEPS_SYSTEM: DEPS_USER);
312 flag_no_output = 1;
313 cpp_opts->inhibit_warnings = 1;
314 break;
315
316 case OPT_MD:
317 case OPT_MMD:
318 cpp_opts->deps.style = (code == OPT_MD ? DEPS_SYSTEM: DEPS_USER);
319 deps_file = arg;
320 break;
321
322 case OPT_MF:
323 deps_seen = true;
324 deps_file = arg;
325 break;
At line 265, pch_file indicates the file name to which we should write a precompiled header, or NULL if no header will be written in this compile.
At line 268, -Aquestion[=answer] specifies a question and answer for an assertion in the following form:
#if #question(answer)
This option can be written as –assert for –A too.
Also at line 281, -Dmacro[=string], if the string is specified, a macro by that name is defined just as if it had been included as part of the code. For example, -Dbrunt=logger generates the following definition:
#define brunt=logger
If the string is not specified, the macro is defined as the string “1”. For example, -Dminke generates the following definition:
#define minke 1
All -D options are processed before any -U options, and all -U options are processed before any -include or -imacros options.
Both –A and –D switches are handled by defer_opt, notice that arg points to the string after -A or -D.
179 static void
180 defer_opt (enum opt_code code, const char *arg) in c-opts.c
181 {
182 deferred_opts[deferred_count].code = code;
183 deferred_opts[deferred_count].arg = arg;
184 deferred_count++;
185 }
deferred_opts holds switches parsed by c_common_handle_option, but whose handling is deferred to c_common_post_options.
If flag_preprocess_only (–E) holds, stops after preprocessing the source code and output the result. The output is written to standard out unless the -o option is used to send it to a file. Input files that do not require preprocessing are ignored, which is determined either by the file name suffixes or by not having their types indicated by the -x option. This option defines the environment variables __GNUC__, __GNUC_MINOR__, and __GNUC_PATCHLEVEL__.
Option –H prints a nested listing of all the header files used, along with a list of the ones that are missing a multiple include guard. This option can be written as --trace-includes too.
For –I path switch, add_path is invoked to include the parameter. The “include” path information is saved into cpp_dir which has definition as following.
402 struct cpp_dir in cpplib.h
403 {
404 /* NULL-terminated singly-linked list. */
405 struct cpp_dir *next;
406
407 /* NAME of the directory, NUL-terminated. */
408 char *name;
409 unsigned int len;
410
411 /* One if a system header, two if a system header that has extern
412 "C" guards for C++. */
413 unsigned char sysp;
414
415 /* Mapping of file names for this directory for MS-DOS and related
416 platforms. A NULL-terminated array of (from, to) pairs. */
417 const char **name_map;
418
419 /* The C front end uses these to recognize duplicated
420 directories in the search path. */
421 ino_t ino;
422 dev_t dev;
423 };
In the system, header files included are grouped into 4 classes. One is included by “”, one is included by <>, one indicates the header file is system ones, the last indicates the header file included by switch -idirafter. So in below, heads and tails are arrays of size 4. Each pair maintains a list of header files’ path of specified class by pointing to the head and tail respectively.
303 void
304 add_path (char *path, int chain, int cxx_aware) in c-inpath.c
305 {
306 struct cpp_dir *p;
307
308 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
309 /* Convert all backslashes to slashes. The native CRT stat()
310 function does not recognise a directory that ends in a backslash
311 (unless it is a drive root dir, such "c:/"). Forward slashes,
312 trailing or otherwise, cause no problems for stat(). */
313 char* c;
314 for (c = path; *c; c++)
315 if (*c == '//') *c = '/';
316 #endif
317
318 p = xmalloc (sizeof (struct cpp_dir));
319 p->next = NULL;
320 p->name = path;
321 if (chain == SYSTEM || chain == AFTER)
322 p->sysp = 1 + !cxx_aware;
323 else
324 p->sysp = 0;
325
326 if (tails[chain])
327 tails[chain]->next = p;
328 else
329 heads[chain] = p;
330 tails[chain] = p;
331 }
Above, at line 322 and 324, for the meaning of sysp, refers to line 411 in definition of cpp_dir. Then for switch -I-, which specifies to not look for other source files in the same directory as the source file named on the command line to be compiled. So split_quote_chain is invoked to remove paths included by “”. Notice that it contains memory leak problem.
290 void
291 split_quote_chain (void) in c-inpath.c
292 {
293 heads[QUOTE] = heads[BRACKET];
294 tails[QUOTE] = tails[BRACKET];
295 heads[BRACKET] = NULL;
296 tails[BRACKET] = NULL;
297 /* This is NOT redundant. */
298 quote_ignores_source_dir = true;
299 }
Above at line 305 in c_common_handle_option, with -M switch the preprocessor outputs a rule suitable for inclusion in a makefile. The rule is composed of the object file name, a colon, the name of the source file and the name of the included files. The include files are listed on separate lines by their full path names. If the –include or -imacros options are on the command line, those files are also in the list. The -M option implies -E.
The resulting rule contains the name of the object file and the list of dependencies; it does not include a rule to compile the source. Unless either the -MT or -MQ option is used to specify the name, the object file name in the produced rule is the same as the input source with the suffix replaced.
The other preprocessor options involved with producing makefile rules are -MD, -MMD, -MF, -MG, -MM, -MP, -MQ, and -MT.
At line 311, -MM is similar with –M, except no system header files are listed.
For –MG, this option can be used in conjunction with -M or -MM to specify that missing header files are assumed to be generated files that reside in the same directory as the source file. The dependency list is generated just as if the header file existed and included no other headers.
For –MP, used in conjunction with -M or -MM to produce a dummy target for each include file. The only purpose of this is to prevent make from generating error messages when you remove a header file without updating the makefile.
Then at line 323, deps_seen indicates if dependency switches (-MF etc.) have been given. –MF filename, when used with -M, -MM, -MD, or -MMD, this option specifies the name of the output file to write the dependencies to. An alternative way of specifying the name of the output file is to set the environment variable DEPENDENCIES_OUTPUT.
At line 337, -MQ target, this option is the same as -MT except the target name is quoted appropriately for the makefile. For example, the command gcc -M –MQ '$(OBJMRK)mrk.o' brink.c will produce the following:
$$(OBJMRK)mrk.o: brink.c
Then –MT target, used in conjunction with -M or -MM to specify the name of the target file of the produced makefile rule. By default, the target file is the same name as the input source file with a .o suffix appended to it. The -MT option can be used to specify a different name, a complete path name, or a name based on an environment variable. For example, the command gcc -M -MT '$(OBJMRK)mrk.o' brink.c will produce the following:
$(OBJMRK)mrk.o: brink.c
flag_no_line_commands (-P) if nonzero, the preprocessor is not to generate #line directives when used with the -E option.
At line 348, flag_working_directory (-fworking-directory) if 0, means we want the preprocessor to not emit line directives for the current working directory, if 1 means we want it to do it, and -1 means we should decide depending on whether debugging information is being emitted or not (the default value is -1).
For –Umacro, if macro has been previously defined, the macro definition is removed. All -D options are processed before any -U options, and all -U options are processed before any -include or -imacros options. The handling is deferred to c_common_post_options.
At line 356, warn_abi (-Wabi) if nonzero, means warn about things that will change when compiling with an ABI-compliant compiler (the default value is 0). [6] gives out the examples of the imcompliant of ABI of G++, however by my testing, these imcompliances have been fixed in current version.
c_common_handle_option (continue)
327 case OPT_MG:
328 deps_seen = true;
329 cpp_opts->deps.missing_files = true;
330 break;
331
332 case OPT_MP:
333 deps_seen = true;
334 cpp_opts->deps.phony_targets = true;
335 break;
336
337 case OPT_MQ:
338 case OPT_MT:
339 deps_seen = true;
340 defer_opt (code, arg);
341 break;
342
343 case OPT_P:
344 flag_no_line_commands = 1;
345 break;
346
347 case OPT_fworking_directory:
348 flag_working_directory = value;
349 break;
350
351 case OPT_U:
352 defer_opt (code, arg);
353 break;
354
355 case OPT_Wabi:
356 warn_abi = value;
357 break;
358
359 case OPT_Wall:
360 set_Wunused (value);
361 set_Wformat (value);
362 set_Wimplicit (value);
363 warn_char_subscripts = value;
364 warn_missing_braces = value;
365 warn_parentheses = value;
366 warn_return_type = value;
367 warn_sequence_point = value; /* Was C only. */
368 if (c_dialect_cxx ())
369 warn_sign_compare = value;
370 warn_switch = value;
371 warn_strict_aliasing = value;
372
373 /* Only warn about unknown pragmas that are not in system
374 headers. */
375 warn_unknown_pragmas = value;
376
377 /* We save the value of warn_uninitialized, since if they put
378 -Wuninitialized on the command line, we need to generate a
379 warning about not using it without also specifying -O. */
380 if (warn_uninitialized != 1)
381 warn_uninitialized = (value ? 2 : 0);
382
383 if (!c_dialect_cxx ())
384 /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding
385 can turn it off only if it's not explicit. */
386 warn_main = value * 2;
387 else
388 {
389 /* C++-specific warnings. */
390 warn_nonvdtor = value;
391 warn_reorder = value;
392 warn_nontemplate_friend = value;
393 }
394
395 cpp_opts->warn_trigraphs = value;
396 cpp_opts->warn_comments = value;
397 cpp_opts->warn_num_sign_change = value;
398 cpp_opts->warn_multichar = value; /* Was C++ only. */
399 break;
For –Wall switch, remember that the value at line 360 indicates if the switch is negative or not (0 for negative, 1 for otherwise, see handle_option). Here, value is 1.
1572 void
1573 set_Wunused (int setting) in opts.c
1574 {
1575 warn_unused_function = setting;
1576 warn_unused_label = setting;
1577 /* Unused function parameter warnings are reported when either
1578 ``-Wextra -Wunused'' or ``-Wunused-parameter'' is specified.
1579 Thus, if -Wextra has already been seen, set warn_unused_parameter;
1580 otherwise set maybe_warn_extra_parameter, which will be picked up
1581 by set_Wextra. */
1582 maybe_warn_unused_parameter = setting;
1583 warn_unused_parameter = (setting && extra_warnings);
1584 warn_unused_variable = setting;
1585 warn_unused_value = setting;
1586 }
So in above, all flags for warning unused items are set to true. At line 1583, extra_warnings is set with switch –W/-Wextra.
36 void
37 set_Wformat (int setting) in c-format.c
38 {
39 warn_format = setting;
40 warn_format_extra_args = setting;
41 warn_format_zero_length = setting;
42 if (setting != 1)
43 {
44 warn_format_nonliteral = setting;
45 warn_format_security = setting;
46 warn_format_y2k = setting;
47 }
48 /* Make sure not to disable -Wnonnull if -Wformat=0 is specified. */
49 if (setting)
50 warn_nonnull = setting;
51 }
Above, warn_format (-Wformat) if nonzero, warns about format/argument anomalies in calls to formatted I/O functions (printf, scanf, strftime, strfmon, etc.).
warn_format_extra_args (C, C++, ObjC, -Wformat-extra-args) if nonzero, warns about excess arguments to formats.
warn_format_zero_length (-Wformat-zero-length) if nonzero and -Wformat is also specified, warns about zero length formats.
warn_format_nonliteral (C, C++, ObjC, -Wformat-nonliteral) if nonzero, warns about non-literal format arguments.
warn_format_security (C, C++, ObjC, -Wformat-security) if nonzero, issues a warning if -Wformat is specified and a call to a function such as printf() and scanf() presents a possible security problem. Function calls using a variable instead of a literal constant string for the formatting is not trusted because it could contain a %n.
warn_format_y2k (C, C++, ObjC, -Wformat-y2k) if nonzero, warns about Y2K problems with strftime formats.
warn_nonnull if nonzero, warns about NULL being passed to argument slots marked as requiring non-NULL.
1559 static void
1560 set_Wimplicit (int on) in c-opts.c
1561 {
1562 warn_implicit = on;
1563 warn_implicit_int = on;
1564 if (on)
1565 {
1566 if (mesg_implicit_function_declaration != 2)
1567 mesg_implicit_function_declaration = 1;
1568 }
1569 else
1570 mesg_implicit_function_declaration = 0;
1571 }
Above, warn_implicit if nonzero, warns about implicit declarations.
warn_implicit_int (C, -Wimplicit-int) if nonzero, warns about use of implicit int. This option is also set by -Wimplicit and -Wall.
mesg_implicit_function_declaration (C, -Wimplicit-function-declaration) if nonzero, means message about use of implicit function declarations; 1 means warning; 2 means error. This option is also set by -Wimplicit and -Wall.
Then in c_common_handle_option above, at line 363, warn_char_subscripts (C, C++, ObjC, -Wchar-subscripts) if nonzero, warns about a subscript that has type char. Because char often defaults to being signed, this can be the cause of an error.
warn_missing_braces (C, C++, ObjC, -Wmissing-braces, also set by -Wall) if nonzero, issues a warning if the initial values of an array are not completely bracketed. In the following example, both arrays a and b are initialized correctly, but braces are used for array b to be more specific about the placement of the values :
int a[2][2] = { 0, 1, 2, 3 };
int b[2][2] = { { 1, 2 }, { 3, 4} };
warn_parentheses (C, C++, ObjC, -Wparentheses, also set by -Wall) if nonzero, issues warnings for constructions that, while syntactically correct, could possibly be confusing to the programmer because of operator precedence or the structure of the code.
The following expression will cause a warning to be issued because it is difficult to remember whether logical operators associate left to right or right to left:
if(a && b || c) . . .
The following will issue a warning because, in the absence of braces, the relationships among the if and else statements could be misleading:
if(a)
if(b)
m = p;
else
a = 0;
It is apparent from the indention that the programmer intended for the else statement is to be associated with the first if statement, but it is not.
warn_return_type (C, C++, -Wreturn-type, also set by -Wall) if nonzero, warns about function definitions that default the return type or that use a null return and have a return-type other than void.
warn_sequence_point (C, -Wsequence-point, also set by -Wall) if nonzero, issues a warning if a variable is referenced more than once in an expression, and one of the references modifies its value. The definition of the C language allows expressions between sequence points to be evaluated in any order (as long as operator precedences are maintained), so modification of a variable in one location makes its value undetermined if it is used in another. A sequence point is specified in the code by the presence of one of the following operators:
; , && || ? :
The following are some examples of expressions that have ambiguous results because of a sequence point violation:
s = a[s++];
s = s--;
a[s++] = b[s];
a[s] = b[s += c];
warn_sign_compare (C, C++, ObjC, -Wsign-compare, also set by –Wall) if nonzero, warns about comparison of signed and unsigned values. If -1, neither -Wsign-compare nor -Wno-sign-compare has been specified (in which case -Wextra gets to decide).
warn_switch (C, C++, ObjC, -Wswitch, alse set by –Wall) if nonzero, warns if a switch on an enum, that does not have a default case, fails to have a case for every enum value.
warn_strict_aliasing (-Wstrict-aliasing), the strictest aliasing rules are applied depending on the language being compiled.With strict aliasing in C, for example, an int cannot be the alias of a double or a pointer, but it can be the alias of an unsigned int. Even with strict aliasing there is not a problem with union members as long as the references are through the union and not through a pointer to the address of a union member. The following code could cause a problem:
int *iptr;
union {
int ivalue;
double dvalue;
} migs;
. . .
migs.ivalue = 45;
iptr = &migs.ivalue;
frammis(*iptr);
migs.dvalue = 88.6;
frammis(*iptr);
In this example is possible that strict aliasing would not recognize that the value pointed to by iptr had changed between the two function calls. However, referring to the union members directly would not cause a problem.
warn_unknown_pragmas (-Wunknown-pragmas, also set by -Wall) if nonzero, warns about #pragma directives that are not recognized.
warn_uninitialized (-Winitialized) if nonzero, issues a warning if an automatic variable is used before it is initialized. Also issue a warning if a setjmp() call may destroy the value of an automatic variable. This option can only be used in conjunction with -O because it is the optimizing data flow information that is required for these situations to be detected.
Because this option requires data flow analysis, it is not possible for it to be completely accurate. For example, in the following code it is not possible to guarantee that value will or will not be initialized for the printf() statement:
int value;
if(a < b)
value = 5;
else if(a > c)
value = 10;
printf("%d/n",value);
Because of the nature of the data flow analysis, this option does not apply to structures, unions, arrays, any variable declared as volatile, any variable that has its address taken, or a variable used to compute a value that is never used. The data flow analysis is aware of the setjmp() statement, but it has no way of knowing from where longjmp() may be called, so a warning could be issued when there is no problem.
This option is set by -Wall if the -O option is also specified.
warn_main (C, C++, -Wmain) if nonzero, warns if main is suspicious.
warn_nonvdtor (C++, -Wnon-virtual-dtor, also set by -Wall) if nonzero, warns when declaring a class that has a non virtual destructor, when it really ought to have a virtual one.
warn_reorder (C++, -Wreorder, also set by –Wall) if nonzero, issues a warning if the compiler rearranges member initializers to match the order in which they are declared. For example, the following initializers must be rearranged:
class Reo {
int i;
int j;
Reo(): j(5), i(10) { }
};
warn_nontemplate_friend (C++, -Wnon-template-friend, also set by –Wall) if nonzero, warns when non-templatized friend functions are declared within a template.