@@ -749,7 +749,8 @@ static bool ParseEnabledFeatureArgs(LangOptions &Opts, ArgList &Args,
749
749
OPT_enable_experimental_feature, OPT_disable_experimental_feature,
750
750
OPT_enable_upcoming_feature, OPT_disable_upcoming_feature)) {
751
751
auto &option = A->getOption ();
752
- StringRef value = A->getValue ();
752
+ const StringRef argValue = A->getValue ();
753
+
753
754
bool isEnableUpcomingFeatureFlag =
754
755
option.matches (OPT_enable_upcoming_feature);
755
756
bool isUpcomingFeatureFlag = isEnableUpcomingFeatureFlag ||
@@ -759,41 +760,45 @@ static bool ParseEnabledFeatureArgs(LangOptions &Opts, ArgList &Args,
759
760
760
761
// Collect some special case pseudo-features which should be processed
761
762
// separately.
762
- if (value .starts_with (" StrictConcurrency" ) ||
763
- value .starts_with (" AvailabilityMacro=" )) {
763
+ if (argValue .starts_with (" StrictConcurrency" ) ||
764
+ argValue .starts_with (" AvailabilityMacro=" )) {
764
765
if (isEnableFeatureFlag)
765
- psuedoFeatures.push_back (value );
766
+ psuedoFeatures.push_back (argValue );
766
767
continue ;
767
768
}
768
769
769
- auto feature = getUpcomingFeature (value);
770
+ // For all other features, the argument format is `<name>[:adoption]`.
771
+ StringRef featureName;
772
+ std::optional<StringRef> featureMode;
773
+ std::tie (featureName, featureMode) = argValue.rsplit (' :' );
774
+ if (featureMode.value ().empty ()) {
775
+ featureMode = std::nullopt;
776
+ }
777
+
778
+ auto feature = getUpcomingFeature (featureName);
770
779
if (feature) {
771
780
// Diagnose upcoming features enabled with -enable-experimental-feature.
772
781
if (!isUpcomingFeatureFlag)
773
- Diags.diagnose (SourceLoc (), diag::feature_not_experimental, value ,
782
+ Diags.diagnose (SourceLoc (), diag::feature_not_experimental, featureName ,
774
783
isEnableFeatureFlag);
775
784
} else {
776
785
// If -enable-upcoming-feature was used and an upcoming feature was not
777
786
// found, diagnose and continue.
778
787
if (isUpcomingFeatureFlag) {
779
- Diags.diagnose (SourceLoc (), diag::unrecognized_feature, value ,
788
+ Diags.diagnose (SourceLoc (), diag::unrecognized_feature, featureName ,
780
789
/* upcoming=*/ true );
781
790
continue ;
782
791
}
783
792
784
793
// If the feature is also not a recognized experimental feature, skip it.
785
- feature = getExperimentalFeature (value );
794
+ feature = getExperimentalFeature (featureName );
786
795
if (!feature) {
787
- Diags.diagnose (SourceLoc (), diag::unrecognized_feature, value ,
796
+ Diags.diagnose (SourceLoc (), diag::unrecognized_feature, featureName ,
788
797
/* upcoming=*/ false );
789
798
continue ;
790
799
}
791
800
}
792
801
793
- // Skip features that are already enabled or disabled.
794
- if (!seenFeatures.insert (*feature).second )
795
- continue ;
796
-
797
802
// If the current language mode enables the feature by default then
798
803
// diagnose and skip it.
799
804
if (auto firstVersion = getFeatureLanguageVersion (*feature)) {
@@ -810,11 +815,37 @@ static bool ParseEnabledFeatureArgs(LangOptions &Opts, ArgList &Args,
810
815
if (Opts.RestrictNonProductionExperimentalFeatures &&
811
816
!isFeatureAvailableInProduction (*feature)) {
812
817
Diags.diagnose (SourceLoc (),
813
- diag::experimental_not_supported_in_production, value);
818
+ diag::experimental_not_supported_in_production,
819
+ featureName);
814
820
HadError = true ;
815
821
continue ;
816
822
}
817
823
824
+ if (featureMode) {
825
+ if (isEnableFeatureFlag) {
826
+ // Diagnose an invalid mode.
827
+ StringRef validModeName = " adoption" ;
828
+ if (*featureMode != validModeName) {
829
+ Diags.diagnose (SourceLoc (), diag::invalid_feature_mode, *featureMode,
830
+ featureName,
831
+ /* didYouMean=*/ validModeName);
832
+ continue ;
833
+ }
834
+ } else {
835
+ // `-disable-*-feature` flags do not support a mode specifier.
836
+ Diags.diagnose (SourceLoc (), diag::cannot_disable_feature_with_mode,
837
+ option.getPrefixedName (), argValue);
838
+ continue ;
839
+ }
840
+
841
+ // Adoption mode is not plumbed through; ignore it.
842
+ continue ;
843
+ }
844
+
845
+ // Skip features that are already enabled or disabled.
846
+ if (!seenFeatures.insert (*feature).second )
847
+ continue ;
848
+
818
849
// Enable the feature if requested.
819
850
if (isEnableFeatureFlag)
820
851
Opts.enableFeature (*feature);
0 commit comments