@@ -740,6 +740,151 @@ static bool ParseCASArgs(CASOptions &Opts, ArgList &Args,
740
740
return false ;
741
741
}
742
742
743
+ static bool ParseEnabledFeatureArgs (LangOptions &Opts, ArgList &Args,
744
+ DiagnosticEngine &Diags,
745
+ const FrontendOptions &FrontendOpts) {
746
+ using namespace options ;
747
+
748
+ bool HadError = false ;
749
+
750
+ // Enable feature upcoming/experimental features if requested. However, leave
751
+ // a feature disabled if an -enable-upcoming-feature flag is superseded by a
752
+ // -disable-upcoming-feature flag. Since only the last flag specified is
753
+ // honored, we iterate over them in reverse order.
754
+ std::vector<StringRef> psuedoFeatures;
755
+ llvm::SmallSet<Feature, 8 > seenFeatures;
756
+ for (const Arg *A : Args.filtered_reverse (
757
+ OPT_enable_experimental_feature, OPT_disable_experimental_feature,
758
+ OPT_enable_upcoming_feature, OPT_disable_upcoming_feature)) {
759
+ auto &option = A->getOption ();
760
+ StringRef value = A->getValue ();
761
+ bool enableUpcoming = option.matches (OPT_enable_upcoming_feature);
762
+ bool enableFeature =
763
+ enableUpcoming || option.matches (OPT_enable_experimental_feature);
764
+
765
+ // Collect some special case pseudo-features which should be processed
766
+ // separately.
767
+ if (value.starts_with (" StrictConcurrency" ) ||
768
+ value.starts_with (" AvailabilityMacro=" )) {
769
+ if (enableFeature)
770
+ psuedoFeatures.push_back (value);
771
+ continue ;
772
+ }
773
+
774
+ // If this was specified as an "upcoming feature", it must be recognized
775
+ // as one.
776
+ auto feature = getUpcomingFeature (value);
777
+ if (enableUpcoming || option.matches (OPT_disable_upcoming_feature)) {
778
+ if (!feature)
779
+ continue ;
780
+ }
781
+
782
+ // If it's not recognized as either an upcoming feature or an experimental
783
+ // feature, skip it.
784
+ if (!feature) {
785
+ feature = getExperimentalFeature (value);
786
+ if (!feature)
787
+ continue ;
788
+ }
789
+
790
+ // Skip features that are already enabled or disabled.
791
+ if (!seenFeatures.insert (*feature).second )
792
+ continue ;
793
+
794
+ // If the the current language mode enables the feature by default then
795
+ // diagnose and skip it.
796
+ if (auto firstVersion = getFeatureLanguageVersion (*feature)) {
797
+ if (Opts.isSwiftVersionAtLeast (*firstVersion)) {
798
+ Diags
799
+ .diagnose (SourceLoc (), diag::error_upcoming_feature_on_by_default,
800
+ getFeatureName (*feature), *firstVersion)
801
+ .limitBehaviorIf (!enableUpcoming, DiagnosticBehavior::Warning);
802
+ if (enableUpcoming)
803
+ HadError = true ;
804
+
805
+ continue ;
806
+ }
807
+ }
808
+
809
+ // If this is a known experimental feature, allow it in +Asserts
810
+ // (non-release) builds for testing purposes.
811
+ if (Opts.RestrictNonProductionExperimentalFeatures &&
812
+ !isFeatureAvailableInProduction (*feature)) {
813
+ Diags.diagnose (SourceLoc (),
814
+ diag::experimental_not_supported_in_production, value);
815
+ HadError = true ;
816
+ continue ;
817
+ }
818
+
819
+ // Enable the feature if requested.
820
+ if (enableFeature)
821
+ Opts.enableFeature (*feature);
822
+ }
823
+
824
+ // Since pseudo-features don't have a boolean on/off state, process them in
825
+ // the order they were specified on the command line.
826
+ for (auto featureName = psuedoFeatures.rbegin (), end = psuedoFeatures.rend ();
827
+ featureName != end; ++featureName) {
828
+
829
+ // Allow StrictConcurrency to have a value that corresponds to the
830
+ // -strict-concurrency=<blah> settings.
831
+ if (featureName->starts_with (" StrictConcurrency" )) {
832
+ auto decomposed = featureName->split (" =" );
833
+ if (decomposed.first == " StrictConcurrency" ) {
834
+ if (decomposed.second == " " ) {
835
+ Opts.StrictConcurrencyLevel = StrictConcurrency::Complete;
836
+ } else if (auto level = parseStrictConcurrency (decomposed.second )) {
837
+ Opts.StrictConcurrencyLevel = *level;
838
+ }
839
+ }
840
+ continue ;
841
+ }
842
+
843
+ // Hack: In order to support using availability macros in SPM packages, we
844
+ // need to be able to use:
845
+ // .enableExperimentalFeature("AvailabilityMacro='...'")
846
+ // within the package manifest and the feature recognizer can't recognize
847
+ // this form of feature, so specially handle it here until features can
848
+ // maybe have extra arguments in the future.
849
+ if (featureName->starts_with (" AvailabilityMacro=" )) {
850
+ auto availability = featureName->split (" =" ).second ;
851
+ Opts.AvailabilityMacros .push_back (availability.str ());
852
+ continue ;
853
+ }
854
+ }
855
+
856
+ // Map historical flags over to experimental features. We do this for all
857
+ // compilers because that's how existing experimental feature flags work.
858
+ if (Args.hasArg (OPT_enable_experimental_static_assert))
859
+ Opts.enableFeature (Feature::StaticAssert);
860
+ if (Args.hasArg (OPT_enable_experimental_named_opaque_types))
861
+ Opts.enableFeature (Feature::NamedOpaqueTypes);
862
+ if (Args.hasArg (OPT_enable_experimental_flow_sensitive_concurrent_captures))
863
+ Opts.enableFeature (Feature::FlowSensitiveConcurrencyCaptures);
864
+ if (Args.hasArg (OPT_enable_experimental_move_only)) {
865
+ // FIXME: drop addition of Feature::MoveOnly once its queries are gone.
866
+ Opts.enableFeature (Feature::MoveOnly);
867
+ Opts.enableFeature (Feature::NoImplicitCopy);
868
+ Opts.enableFeature (Feature::OldOwnershipOperatorSpellings);
869
+ }
870
+ if (Args.hasArg (OPT_experimental_one_way_closure_params))
871
+ Opts.enableFeature (Feature::OneWayClosureParameters);
872
+ if (Args.hasArg (OPT_enable_experimental_forward_mode_differentiation))
873
+ Opts.enableFeature (Feature::ForwardModeDifferentiation);
874
+ if (Args.hasArg (OPT_enable_experimental_additive_arithmetic_derivation))
875
+ Opts.enableFeature (Feature::AdditiveArithmeticDerivedConformances);
876
+
877
+ if (Args.hasArg (OPT_enable_experimental_opaque_type_erasure))
878
+ Opts.enableFeature (Feature::OpaqueTypeErasure);
879
+
880
+ if (Args.hasArg (OPT_enable_builtin_module))
881
+ Opts.enableFeature (Feature::BuiltinModule);
882
+
883
+ Opts.enableFeature (Feature::LayoutPrespecialization);
884
+
885
+ return HadError;
886
+ }
887
+
743
888
static bool ParseLangArgs (LangOptions &Opts, ArgList &Args,
744
889
DiagnosticEngine &Diags,
745
890
const FrontendOptions &FrontendOpts) {
@@ -1012,113 +1157,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
1012
1157
Opts.EnableExperimentalStringProcessing = true ;
1013
1158
}
1014
1159
1015
- auto enableUpcomingFeature = [&Opts, &Diags](Feature feature,
1016
- bool downgradeDiag) -> bool {
1017
- // Check if this feature was introduced already in this language version.
1018
- if (auto firstVersion = getFeatureLanguageVersion (feature)) {
1019
- if (Opts.isSwiftVersionAtLeast (*firstVersion)) {
1020
- Diags
1021
- .diagnose (SourceLoc (), diag::error_upcoming_feature_on_by_default,
1022
- getFeatureName (feature), *firstVersion)
1023
- .limitBehaviorIf (downgradeDiag, DiagnosticBehavior::Warning);
1024
- return !downgradeDiag;
1025
- }
1026
- }
1027
-
1028
- Opts.enableFeature (feature);
1029
- return false ;
1030
- };
1031
-
1032
- // Enable experimental features.
1033
- for (const Arg *A : Args.filtered (OPT_enable_experimental_feature)) {
1034
- // Allow StrictConcurrency to have a value that corresponds to the
1035
- // -strict-concurrency=<blah> settings.
1036
- StringRef value = A->getValue ();
1037
- if (value.starts_with (" StrictConcurrency" )) {
1038
- auto decomposed = value.split (" =" );
1039
- if (decomposed.first == " StrictConcurrency" ) {
1040
- if (decomposed.second == " " ) {
1041
- Opts.StrictConcurrencyLevel = StrictConcurrency::Complete;
1042
- } else if (auto level = parseStrictConcurrency (decomposed.second )) {
1043
- Opts.StrictConcurrencyLevel = *level;
1044
- }
1045
- }
1046
- }
1047
-
1048
- // If this is a known experimental feature, allow it in +Asserts
1049
- // (non-release) builds for testing purposes.
1050
- if (auto feature = getExperimentalFeature (value)) {
1051
- if (Opts.RestrictNonProductionExperimentalFeatures &&
1052
- !isFeatureAvailableInProduction (*feature)) {
1053
- Diags.diagnose (SourceLoc (), diag::experimental_not_supported_in_production,
1054
- A->getValue ());
1055
- HadError = true ;
1056
- } else {
1057
- Opts.enableFeature (*feature);
1058
- }
1059
- }
1060
-
1061
- // For compatibility, upcoming features can be enabled with the
1062
- // -enable-experimental-feature flag too since the feature may have
1063
- // graduated from being experimental.
1064
- if (auto feature = getUpcomingFeature (value)) {
1065
- if (enableUpcomingFeature (*feature, /* downgradeDiag=*/ true ))
1066
- HadError = true ;
1067
- }
1068
-
1069
- // Hack: In order to support using availability macros in SPM packages, we
1070
- // need to be able to use:
1071
- // .enableExperimentalFeature("AvailabilityMacro='...'")
1072
- // within the package manifest and the feature recognizer can't recognize
1073
- // this form of feature, so specially handle it here until features can
1074
- // maybe have extra arguments in the future.
1075
- auto strRef = StringRef (A->getValue ());
1076
- if (strRef.starts_with (" AvailabilityMacro=" )) {
1077
- auto availability = strRef.split (" =" ).second ;
1078
-
1079
- Opts.AvailabilityMacros .push_back (availability.str ());
1080
- }
1081
- }
1082
-
1083
- // Enable upcoming features.
1084
- for (const Arg *A : Args.filtered (OPT_enable_upcoming_feature)) {
1085
- // Ignore unknown features.
1086
- auto feature = getUpcomingFeature (A->getValue ());
1087
- if (!feature)
1088
- continue ;
1089
-
1090
- if (enableUpcomingFeature (*feature, /* downgradeDiag=*/ false ))
1091
- HadError = true ;
1092
- }
1093
-
1094
- // Map historical flags over to experimental features. We do this for all
1095
- // compilers because that's how existing experimental feature flags work.
1096
- if (Args.hasArg (OPT_enable_experimental_static_assert))
1097
- Opts.enableFeature (Feature::StaticAssert);
1098
- if (Args.hasArg (OPT_enable_experimental_named_opaque_types))
1099
- Opts.enableFeature (Feature::NamedOpaqueTypes);
1100
- if (Args.hasArg (OPT_enable_experimental_flow_sensitive_concurrent_captures))
1101
- Opts.enableFeature (Feature::FlowSensitiveConcurrencyCaptures);
1102
- if (Args.hasArg (OPT_enable_experimental_move_only)) {
1103
- // FIXME: drop addition of Feature::MoveOnly once its queries are gone.
1104
- Opts.enableFeature (Feature::MoveOnly);
1105
- Opts.enableFeature (Feature::NoImplicitCopy);
1106
- Opts.enableFeature (Feature::OldOwnershipOperatorSpellings);
1107
- }
1108
- if (Args.hasArg (OPT_experimental_one_way_closure_params))
1109
- Opts.enableFeature (Feature::OneWayClosureParameters);
1110
- if (Args.hasArg (OPT_enable_experimental_forward_mode_differentiation))
1111
- Opts.enableFeature (Feature::ForwardModeDifferentiation);
1112
- if (Args.hasArg (OPT_enable_experimental_additive_arithmetic_derivation))
1113
- Opts.enableFeature (Feature::AdditiveArithmeticDerivedConformances);
1114
-
1115
- if (Args.hasArg (OPT_enable_experimental_opaque_type_erasure))
1116
- Opts.enableFeature (Feature::OpaqueTypeErasure);
1117
-
1118
- if (Args.hasArg (OPT_enable_builtin_module))
1119
- Opts.enableFeature (Feature::BuiltinModule);
1120
-
1121
- Opts.enableFeature (Feature::LayoutPrespecialization);
1160
+ if (ParseEnabledFeatureArgs (Opts, Args, Diags, FrontendOpts))
1161
+ HadError = true ;
1122
1162
1123
1163
Opts.EnableAppExtensionLibraryRestrictions |= Args.hasArg (OPT_enable_app_extension_library);
1124
1164
Opts.EnableAppExtensionRestrictions |= Args.hasArg (OPT_enable_app_extension);
0 commit comments