对于公用选项及c_common_handle_option未能完成处理之选项,则需要继续调用 common_handle_option。
655 static int
656 common_handle_option (size_t scode, const char *arg, in opts.c
657 int value ATTRIBUTE_UNUSED)
658 {
659 enum opt_code code = (enum opt_code) scode;
660
661 switch (code)
662 {
663 default:
664 abort ();
665
666 case OPT__help:
667 print_help ();
668 exit_after_options = true;
669 break;
670
671 case OPT__param:
672 handle_param (arg);
673 break;
选项–param name=value设定某些GCC使用的内部限制,以确定优化的力度,因此调整这些变量就是调整优化。
参数调整通过handle_param来完成。
1529 static void
1530 handle_param (const char *carg) in opts.c
1531 {
1532 char *equal, *arg;
1533 int value;
1534
1535 arg = xstrdup (carg);
1536 equal = strchr (arg, '=');
1537 if (!equal)
1538 error ("%s: --param arguments should be of the form NAME=VALUE", arg);
1539 else
1540 {
1541 value = integral_argument (equal + 1);
1542 if (value == -1)
1543 error ("invalid --param value `%s'", equal + 1);
1544 else
1545 {
1546 *equal = '/0';
1547 set_param_value (arg, value);
1548 }
1549 }
1550
1551 free (arg);
1552 }
参数必须是正整数,为了设定值,调用set_param_value。
58 void
59 set_param_value (const char *name, int value) in params.c
60 {
61 size_t i;
62
63 /* Make sure nobody tries to set a parameter to an invalid value. */
64 if (value == INVALID_PARAM_VAL)
65 abort ();
66
67 /* Scan the parameter table to find a matching entry. */
68 for (i = 0; i < num_compiler_params; ++i)
69 if (strcmp (compiler_params[i].option, name) == 0)
70 {
71 compiler_params[i].value = value;
72 return;
73 }
74
75 /* If we didn't find this parameter, issue an error message. */
76 error ("invalid parameter `%s'", name);
77 }
--param所能使用的参数是已经确定的。在general_init的4264行,add_params确定了这些名字,并使用lang_independent_params初始化compiler_params。
common_handle_option (continue)
675 case OPT__target_help:
676 display_target_options ();
677 exit_after_options = true;
678 break;
679
680 case OPT__version:
681 print_version (stderr, "");
682 exit_after_options = true;
683 break;
684
685 case OPT_G:
686 g_switch_value = value;
687 g_switch_set = true;
688 break;
689
690 case OPT_O:
691 case OPT_Os:
692 /* Currently handled in a prescan. */
693 break;
694
695 case OPT_W:
696 /* For backward compatibility, -W is the same as -Wextra. */
697 set_Wextra (value);
698 break;
699
700 case OPT_Waggregate_return:
701 warn_aggregate_return = value;
702 break;
703
704 case OPT_Wcast_align:
705 warn_cast_align = value;
706 break;
707
708 case OPT_Wdeprecated_declarations:
709 warn_deprecated_decl = value;
710 break;
711
712 case OPT_Wdisabled_optimization:
713 warn_disabled_optimization = value;
714 break;
715
716 case OPT_Werror:
717 warnings_are_errors = value;
718 break;
719
720 case OPT_Wextra:
721 set_Wextra (value);
722 break;
723
724 case OPT_Winline:
725 warn_inline = value;
726 break;
727
728 case OPT_Wlarger_than_:
729 larger_than_size = value;
730 warn_larger_than = value != -1;
731 break;
732
733 case OPT_Wmissing_noreturn:
734 warn_missing_noreturn = value;
735 break;
736
737 case OPT_Wpacked:
738 warn_packed = value;
739 break;
740
741 case OPT_Wpadded:
742 warn_padded = value;
743 break;
744
745 case OPT_Wshadow:
746 warn_shadow = value;
747 break;
748
749 case OPT_Wstrict_aliasing:
750 warn_strict_aliasing = value;
751 break;
752
753 case OPT_Wswitch:
754 warn_switch = value;
755 break;
756
757 case OPT_Wswitch_default:
758 warn_switch_default = value;
759 break;
760
761 case OPT_Wswitch_enum:
762 warn_switch_enum = value;
763 break;
764
765 case OPT_Wsystem_headers:
766 warn_system_headers = value;
767 break;
768
769 case OPT_Wuninitialized:
770 warn_uninitialized = value;
771 break;
772
773 case OPT_Wunreachable_code:
774 warn_notreached = value;
775 break;
776
777 case OPT_Wunused:
778 set_Wunused (value);
779 break;
780
781 case OPT_Wunused_function:
782 warn_unused_function = value;
783 break;
784
785 case OPT_Wunused_label:
786 warn_unused_label = value;
787 break;
788
789 case OPT_Wunused_parameter:
790 warn_unused_parameter = value;
791 break;
792
793 case OPT_Wunused_value:
794 warn_unused_value = value;
795 break;
796
797 case OPT_Wunused_variable:
798 warn_unused_variable = value;
799 break;
上面,所遭遇的选项及相关的变量有:
g_switch_value(-G number),将小于number字节的全局及静态对象置于小的数据或bss段,而不是普通的数据段或bss段。默认的number值是8。选项-msdata必须被设为sdata或能使得该选项起作用。所有模块必须使用同一组-msdata及-G设置来编译。使用不同的number值,编译可能能正常工作,也可能不正常。如果不正常,链接器将检出错误,以避免产生错误的代码。
又在697行,选项–W由set_Wextra来处理。
1555 static void
1556 set_Wextra (int setting) in opts.c
1557 {
1558 extra_warnings = setting;
1559 warn_unused_value = setting;
1560 warn_unused_parameter = (setting && maybe_warn_unused_parameter);
1561
1562 /* We save the value of warn_uninitialized, since if they put
1563 -Wuninitialized on the command line, we need to generate a
1564 warning about not using it without also specifying -O. */
1565 if (setting == 0)
1566 warn_uninitialized = 0;
1567 else if (warn_uninitialized != 1)
1568 warn_uninitialized = 2;
1569 }
-W 这个选项启动了一族警告。这些警告主要涉及可能导致问题的代码,但这些代码可能是编程者故意为之。这个选项将启动如下所有:
Comparison 如果一个无符号值测试小于0,发出警告。例如,因为无符号值不会为负数,下列测试永远为false:
unsigned int x;
. . .
if(x < 0) . . .
Comparison 如果一个有符号值与无符号值比较,发出警告。当一个无符号值转换为有符号值用于比较时,可能会产生不正确的结果。这个警告可被-Wno-sign-compare压制。
Comparison 代数记符和C句法,在表示比较方面是不同的。下面的语句将触发警告:
if(a < b < c) . . .
在代数记符中,这个表达式是true仅当b在a和c的开区间内。在C里,这个表达式与下列表达式等效,含义大不相同:
int result;
result = a < b;
if(result < b) . . .
Const return 警告函数的返回值被声明为const。在这里的const声明没有任何意义,因为函数返回值是一个右值。
Aggregate initializers 警告一个聚集类的初始化值,这个值不能涵盖聚集类的所有成员。在下面的例子中,数组和结构体均被警告:
struct {
int a;
int b;
int c;
} trmp = { 1, 2 };
int arr[10] = { 1, 2, 3, 4, 5 };
No side effect 警告一条没有副作用的语句。例如,下面加法的结果就没有被使用:
int a = 1;
int b = 2;
a + b;
Overflow 在Fortran中,警告浮点常量声明的溢出。
Return value 警告函数被写成可能返回或不返回值,象下例中,如果x是负数,函数不返回值:
ambigret(int x) {
if(x >= 0)
return(x);
}
Static syntax 警告关键字static不是第一个出现在声明行上。这个次序已不再被标准C要求。
Unused arguments 如果-Wall或-Wunused,和-W一起使用,警告在函数体内未被使用的参数。
warn_inline(C,C++,ObjC,-Winline)如果非0,警告函数被声明为内联但不能展开为内联。
warn_larger_than(C,C++,ObjC,-Wlarger-than)如果非0,警告声明一个大于特定字节数的对象,及一个函数的返回值大于特定字节数。
warn_aggregate_return(C,C++,ObjC,-Waggregate-return)如果非0,警告函数返回一个结构体,union或者数组。
warn_cast_align(C,C++,ObjC,-Wcast-align)如果非0,警告将一指针转换为不同类型者,可能会因对齐而导致问题。例如,在一些机器上,可能只可以在2或4的边界上访问一个int,因此将一个char指针转换为一个int指针会导致无效的地址值。
warn_deprecated_decl(C,C++,ObjC,-Wdeprecated-declaration)如果非0,警告使用了过时的特性,除非指明-Wno-deprecated-declarations。
warn_disabled_optimization(-Wdisabled-optimization)如果非0,警告所要求的优化被失能。这个情况的发生不是由于代码的问题,而是因为编译器本身的限制。GCC将拒绝执行太复杂及需时太多的优化。
warn_missing_noreturn,如果非0,警告函数可能是noreturn属性的候选。
warn_packed,如果非0,警告结构体所应用的packed属性是不必要及低效的。
warn_padded,如果非0,警告gcc填充结构体至对齐边界。
warn_shadow,如果非0,警告声明将屏蔽其他声明。
warn_switch_defaul,如果非0,警告switch缺少default项。
warn_switch_enum,如果非0,警告应用enum的switch语句不能覆盖所有枚举值。
warn_system_headers(C, C++, ObjC, -Wsystem-headers)如果非0,对系统头文件亦发出警告信息。通常系统头文件导致的警告会被压制。要对系统头文件中的不能识别之pragmas产生警告,需指明-Wunknown-pragmas,因为使用-Wall仅检查程序中的pragmas,而忽略在系统头文件中的pragmas。
warn_notreached,如果非0,警告不能到达之代码。
common_handle_option (continue)
801 case OPT_aux_info:
802 case OPT_aux_info_:
803 aux_info_file_name = arg;
804 flag_gen_aux_info = 1;
805 break;
806
807 case OPT_auxbase:
808 aux_base_name = arg;
809 break;
810
811 case OPT_auxbase_strip:
812 {
813 char *tmp = xstrdup (arg);
814 strip_off_ending (tmp, strlen (tmp));
815 if (tmp[0])
816 aux_base_name = tmp;
817 }
818 break;
819
820 case OPT_d:
821 decode_d_option (arg);
822 break;
823
824 case OPT_dumpbase:
825 dump_base_name = arg;
826 break;
827
828 case OPT_fPIC:
829 flag_pic = value + value;
830 break;
831
832 case OPT_fPIE:
833 flag_pie = value + value;
834 break;
835
836 case OPT_fabi_version_:
837 flag_abi_version = value;
838 break;
839
840 case OPT_falign_functions:
841 align_functions = !value;
842 break;
843
844 case OPT_falign_functions_:
845 align_functions = value;
846 break;
847
848 case OPT_falign_jumps:
849 align_jumps = !value;
850 break;
851
852 case OPT_falign_jumps_:
853 align_jumps = value;
854 break;
855
856 case OPT_falign_labels:
857 align_labels = !value;
858 break;
859
860 case OPT_falign_labels_:
861 align_labels = value;
862 break;
863
864 case OPT_falign_loops:
865 align_loops = !value;
866 break;
867
868 case OPT_falign_loops_:
869 align_loops = value;
870 break;
871
872 case OPT_fargument_alias:
873 flag_argument_noalias = !value;
874 break;
875
876 case OPT_fargument_noalias:
877 flag_argument_noalias = value;
878 break;
879
880 case OPT_fargument_noalias_global:
881 flag_argument_noalias = value + value;
882 break;
883
884 case OPT_fasynchronous_unwind_tables:
885 flag_asynchronous_unwind_tables = value;
886 break;
887
888 case OPT_fbounds_check:
889 flag_bounds_check = value;
890 break;
891
892 case OPT_fbranch_count_reg:
893 flag_branch_on_count_reg = value;
894 break;
895
896 case OPT_fbranch_probabilities:
897 flag_branch_probabilities_set = true;
898 flag_branch_probabilities = value;
899 break;
900
901 case OPT_fbranch_target_load_optimize:
902 flag_branch_target_load_optimize = value;
903 break;
904
905 case OPT_fbranch_target_load_optimize2:
906 flag_branch_target_load_optimize2 = value;
907 break;
aux_info_file_name(C,-aux-info filename)输出在单一编译单元(一个C源文件及所有包含的头文件)中声明或定义的函数原型声明至命名文件。
flag_gen_aux_info,如果非0,表示将声明信息保存在一个.X后缀文件内。
aux_base_name(-auxbase,-auxbase-strip)指明用作辅助输出文件的不带后缀名。
flag_abi_version(-fabi-version=)表示所使用的C++ ABI的版本。以下值是所允许的:
0: ABI的版本确信符合C++ ABI的规范。这个ABI可能因为bug的发现及修正而修改。因此,在不同G++版本中,表示相同的ABI,0是不足够的。
1: 该版本的ABI首先用于G++ 3.2。
2: 该版本的ABI首先用于G++ 3.4。
额外的整数将被用于作为默认版本的新版本ABI。
flag_argument_noalias取以下值:
0 如果指针参数可互为别名。在C中为true。
1 如果指针参数不能互为别名,但可为全局变量的别名。
2 如果指针参数不能互为别名,亦不能为全局变量的别名。在fortran中为true。
对于C,默认值为0。并且其值可由下列选项设定。
-fargument-alias 表明传给函数的实参可能互为别名。亦即,2个或多个参数可能访问同一内存位置。亦可能一实参是一全局值的别名。对于C,C++及ObjC,这是默认选项。
-fargument-noalias 表明传给函数的实参不互为别名。亦即,2个或多个参数不会访问同一内存位置。然而,有可能一实参是一全局值的别名。
-fargument-noalias-global表明传给函数的实参不互为别名。亦即,2个或多个参数不会访问同一内存位置。同时该实参亦不会是全局值的别名。
flag_bounds_check(-fbounds-check)导致gcc进行数组边界检查。对于C,C++,ObjC,默认为关。对于Java,默认为开。对于Fortran,默认为关。
flag_branch_on_count_reg(-fbranch-count-reg)如果非0,表示试图替换加-1,比较,跳转元组(tupple)为基于计数寄存器(count register)的更低代价的跳转。
flag_branch_probabilities(-fbranch-probabilities)如果非0,在使用-fprofile-arcs进行编译,并运行编译所得程序,以得到包含代码每个块执行计数的文件后,使用这个选项重新编译程序,使用前生成文件中的信息,对最频繁的跳转进行优化。没有这些信息,GCC则只能猜测哪条路径最可能执取而进行优化。这些信息保存在与源文件同名具有.da后缀的文件中。
flag_branch_target_load_optimize(-fbranch-target-load-optimize)如果非0,在序言/结尾线程(prologue / epilogue threading)前执行跳转目的加载优化(branch target load optimization)
flag_branch_target_load_optimize2(-fbranch-target-load-optimize2)如果非0,在序言/结尾线程(prologue / epilogue threading)后执行跳转目的加载优化(branch target load optimization)。