20
20
#include " swift/Basic/Assertions.h"
21
21
#include " swift/Basic/Feature.h"
22
22
#include " swift/Basic/Platform.h"
23
+ #include " swift/Basic/Version.h"
23
24
#include " swift/Option/Options.h"
24
25
#include " swift/Option/SanitizerOptions.h"
25
26
#include " swift/Parse/Lexer.h"
@@ -92,20 +93,6 @@ void CompilerInvocation::setMainExecutablePath(StringRef Path) {
92
93
llvm::sys::path::remove_filename (clangPath);
93
94
llvm::sys::path::append (clangPath, " clang" );
94
95
ClangImporterOpts.clangPath = std::string (clangPath);
95
-
96
- llvm::SmallString<128 > DiagnosticDocsPath (Path);
97
- llvm::sys::path::remove_filename (DiagnosticDocsPath); // Remove /swift
98
- llvm::sys::path::remove_filename (DiagnosticDocsPath); // Remove /bin
99
- llvm::sys::path::append (DiagnosticDocsPath, " share" , " doc" , " swift" ,
100
- " diagnostics" );
101
- DiagnosticOpts.DiagnosticDocumentationPath = std::string (DiagnosticDocsPath.str ());
102
-
103
- // Compute the path to the diagnostic translations in the toolchain/build.
104
- llvm::SmallString<128 > DiagnosticMessagesDir (Path);
105
- llvm::sys::path::remove_filename (DiagnosticMessagesDir); // Remove /swift
106
- llvm::sys::path::remove_filename (DiagnosticMessagesDir); // Remove /bin
107
- llvm::sys::path::append (DiagnosticMessagesDir, " share" , " swift" , " diagnostics" );
108
- DiagnosticOpts.LocalizationPath = std::string (DiagnosticMessagesDir.str ());
109
96
}
110
97
111
98
static std::string
@@ -758,6 +745,8 @@ static bool ParseEnabledFeatureArgs(LangOptions &Opts, ArgList &Args,
758
745
auto &option = A->getOption ();
759
746
StringRef value = A->getValue ();
760
747
bool enableUpcoming = option.matches (OPT_enable_upcoming_feature);
748
+ bool isUpcomingFlag =
749
+ enableUpcoming || option.matches (OPT_disable_upcoming_feature);
761
750
bool enableFeature =
762
751
enableUpcoming || option.matches (OPT_enable_experimental_feature);
763
752
@@ -770,20 +759,28 @@ static bool ParseEnabledFeatureArgs(LangOptions &Opts, ArgList &Args,
770
759
continue ;
771
760
}
772
761
773
- // If this was specified as an "upcoming feature", it must be recognized
774
- // as one.
775
762
auto feature = getUpcomingFeature (value);
776
- if (enableUpcoming || option.matches (OPT_disable_upcoming_feature)) {
777
- if (!feature)
763
+ if (feature) {
764
+ // Diagnose upcoming features enabled with -enable-experimental-feature.
765
+ if (!isUpcomingFlag)
766
+ Diags.diagnose (SourceLoc (), diag::feature_not_experimental, value,
767
+ enableFeature);
768
+ } else {
769
+ // If -enable-upcoming-feature was used and an upcoming feature was not
770
+ // found, diagnose and continue.
771
+ if (isUpcomingFlag) {
772
+ Diags.diagnose (SourceLoc (), diag::unrecognized_feature, value,
773
+ /* upcoming=*/ true );
778
774
continue ;
779
- }
775
+ }
780
776
781
- // If it's not recognized as either an upcoming feature or an experimental
782
- // feature, skip it.
783
- if (!feature) {
777
+ // If the feature is also not a recognized experimental feature, skip it.
784
778
feature = getExperimentalFeature (value);
785
- if (!feature)
779
+ if (!feature) {
780
+ Diags.diagnose (SourceLoc (), diag::unrecognized_feature, value,
781
+ /* upcoming=*/ false );
786
782
continue ;
783
+ }
787
784
}
788
785
789
786
// Skip features that are already enabled or disabled.
@@ -2369,6 +2366,9 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, ArgList &Args,
2369
2366
2370
2367
static bool ParseDiagnosticArgs (DiagnosticOptions &Opts, ArgList &Args,
2371
2368
DiagnosticEngine &Diags) {
2369
+ // NOTE: This executes at the beginning of parsing the command line and cannot
2370
+ // depend on the results of parsing other options.
2371
+
2372
2372
using namespace options ;
2373
2373
2374
2374
if (Args.hasArg (OPT_verify))
@@ -2492,6 +2492,56 @@ static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
2492
2492
return false ;
2493
2493
}
2494
2494
2495
+ static void configureDiagnosticEngine (
2496
+ const DiagnosticOptions &Options,
2497
+ std::optional<version::Version> effectiveLanguageVersion,
2498
+ StringRef mainExecutablePath, DiagnosticEngine &Diagnostics) {
2499
+ if (Options.ShowDiagnosticsAfterFatalError ) {
2500
+ Diagnostics.setShowDiagnosticsAfterFatalError ();
2501
+ }
2502
+ if (Options.SuppressWarnings ) {
2503
+ Diagnostics.setSuppressWarnings (true );
2504
+ }
2505
+ if (Options.SuppressRemarks ) {
2506
+ Diagnostics.setSuppressRemarks (true );
2507
+ }
2508
+ Diagnostics.setWarningsAsErrorsRules (Options.WarningsAsErrorsRules );
2509
+ Diagnostics.setPrintDiagnosticNamesMode (Options.PrintDiagnosticNames );
2510
+
2511
+ std::string docsPath = Options.DiagnosticDocumentationPath ;
2512
+ if (docsPath.empty ()) {
2513
+ // Default to a location relative to the compiler.
2514
+ llvm::SmallString<128 > docsPathBuffer (mainExecutablePath);
2515
+ llvm::sys::path::remove_filename (docsPathBuffer); // Remove /swift
2516
+ llvm::sys::path::remove_filename (docsPathBuffer); // Remove /bin
2517
+ llvm::sys::path::append (docsPathBuffer, " share" , " doc" , " swift" ,
2518
+ " diagnostics" );
2519
+ docsPath = docsPathBuffer.str ();
2520
+ }
2521
+ Diagnostics.setDiagnosticDocumentationPath (docsPath);
2522
+
2523
+ if (!Options.LocalizationCode .empty ()) {
2524
+ std::string locPath = Options.LocalizationPath ;
2525
+ if (locPath.empty ()) {
2526
+ llvm::SmallString<128 > locPathBuffer (mainExecutablePath);
2527
+ llvm::sys::path::remove_filename (locPathBuffer); // Remove /swift
2528
+ llvm::sys::path::remove_filename (locPathBuffer); // Remove /bin
2529
+ llvm::sys::path::append (locPathBuffer, " share" , " swift" , " diagnostics" );
2530
+ locPath = locPathBuffer.str ();
2531
+ }
2532
+ Diagnostics.setLocalization (Options.LocalizationCode , locPath);
2533
+ }
2534
+
2535
+ if (effectiveLanguageVersion)
2536
+ Diagnostics.setLanguageVersion (*effectiveLanguageVersion);
2537
+ }
2538
+
2539
+ // / Configures the diagnostic engine for the invocation's options.
2540
+ void CompilerInvocation::setUpDiagnosticEngine (DiagnosticEngine &diags) {
2541
+ configureDiagnosticEngine (DiagnosticOpts, LangOpts.EffectiveLanguageVersion ,
2542
+ FrontendOpts.MainExecutablePath , diags);
2543
+ }
2544
+
2495
2545
// / Parse -enforce-exclusivity=... options
2496
2546
void parseExclusivityEnforcementOptions (const llvm::opt::Arg *A,
2497
2547
SILOptions &Opts,
@@ -3742,6 +3792,16 @@ bool CompilerInvocation::parseArgs(
3742
3792
return true ;
3743
3793
}
3744
3794
3795
+ // Parse options that control diagnostic behavior as early as possible, so
3796
+ // that they can influence the behavior of diagnostics emitted during the
3797
+ // rest of parsing.
3798
+ if (ParseDiagnosticArgs (DiagnosticOpts, ParsedArgs, Diags)) {
3799
+ return true ;
3800
+ }
3801
+ configureDiagnosticEngine (DiagnosticOpts,
3802
+ /* effectiveLanguageVersion=*/ std::nullopt,
3803
+ mainExecutablePath, Diags);
3804
+
3745
3805
ParseAssertionArgs (ParsedArgs);
3746
3806
3747
3807
if (ParseFrontendArgs (FrontendOpts, ParsedArgs, Diags,
@@ -3796,10 +3856,6 @@ bool CompilerInvocation::parseArgs(
3796
3856
return true ;
3797
3857
}
3798
3858
3799
- if (ParseDiagnosticArgs (DiagnosticOpts, ParsedArgs, Diags)) {
3800
- return true ;
3801
- }
3802
-
3803
3859
if (ParseMigratorArgs (MigratorOpts, LangOpts, FrontendOpts,
3804
3860
SearchPathOpts.RuntimeResourcePath , ParsedArgs, Diags)) {
3805
3861
return true ;
0 commit comments