diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 22869254749..72f13c2bdc4 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -143,6 +143,8 @@ ERROR(error_mode_cannot_emit_symbol_graph,none, "this mode does not support emitting symbol graph files", ()) ERROR(error_mode_cannot_emit_abi_descriptor,none, "this mode does not support emitting ABI descriptor", ()) +ERROR(error_mode_cannot_emit_const_values,none, + "this mode does not support emitting extracted const values", ()) ERROR(error_mode_cannot_emit_module_semantic_info,none, "this mode does not support emitting module semantic info", ()) ERROR(cannot_emit_ir_skipping_function_bodies,none, diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index db214ddf4f8..ab9f6d0a2b9 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -339,6 +339,9 @@ public: /// A file containing modules we should perform batch scanning. std::string BatchScanInputFilePath; + /// A file containing a list of protocols whose conformances require const value extraction. + std::string ConstGatherProtocolListFilePath; + /// Debug path mappings to apply to serialized search paths. These are /// specified in LLDB from the target.source-map entries. PathRemapper SearchPathRemapper; diff --git a/include/swift/Basic/FileTypes.def b/include/swift/Basic/FileTypes.def index 2d3c7e37543..337c60e539a 100644 --- a/include/swift/Basic/FileTypes.def +++ b/include/swift/Basic/FileTypes.def @@ -77,6 +77,8 @@ TYPE("json-dependencies", JSONDependencies, "dependencies.json", // Complete feature information for the given Swift compiler. TYPE("json-features", JSONFeatures, "features.json", "") +// Gathered compile-time-known value information for the given Swift input file as JSON. +TYPE("const-values", ConstValues, "swiftconstvalues", "") TYPE("index-data", IndexData, "", "") TYPE("index-unit-output-path", IndexUnitOutputPath, "", "") diff --git a/include/swift/Basic/SupplementaryOutputPaths.h b/include/swift/Basic/SupplementaryOutputPaths.h index c8ba0b075ba..5dfdc82b3af 100644 --- a/include/swift/Basic/SupplementaryOutputPaths.h +++ b/include/swift/Basic/SupplementaryOutputPaths.h @@ -147,6 +147,9 @@ struct SupplementaryOutputPaths { /// The output path to generate ABI baseline. std::string ABIDescriptorOutputPath; + /// The output path for extracted compile-time-known value information + std::string ConstValuesOutputPath; + /// The output path of Swift semantic info for this module. std::string ModuleSemanticInfoOutputPath; @@ -188,6 +191,8 @@ struct SupplementaryOutputPaths { fn(ModuleSummaryOutputPath); if (!ABIDescriptorOutputPath.empty()) fn(ABIDescriptorOutputPath); + if (!ConstValuesOutputPath.empty()) + fn(ConstValuesOutputPath); if (!YAMLOptRecordPath.empty()) fn(YAMLOptRecordPath); if (!BitstreamOptRecordPath.empty()) @@ -204,6 +209,7 @@ struct SupplementaryOutputPaths { TBDPath.empty() && ModuleInterfaceOutputPath.empty() && ModuleSourceInfoOutputPath.empty() && ABIDescriptorOutputPath.empty() && + ConstValuesOutputPath.empty() && ModuleSemanticInfoOutputPath.empty() && YAMLOptRecordPath.empty() && BitstreamOptRecordPath.empty(); } diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index b0f6e4dcf4f..6db341f5325 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -396,6 +396,7 @@ public: std::string getModuleOutputPathForAtMostOnePrimary() const; std::string getReferenceDependenciesFilePathForPrimary(StringRef filename) const; + std::string getConstValuesFilePathForPrimary(StringRef filename) const; std::string getSerializedDiagnosticsPathForAtMostOnePrimary() const; /// TBDPath only makes sense in whole module compilation mode, diff --git a/include/swift/Frontend/FrontendInputsAndOutputs.h b/include/swift/Frontend/FrontendInputsAndOutputs.h index b21642cbd93..c2fa0e4672c 100644 --- a/include/swift/Frontend/FrontendInputsAndOutputs.h +++ b/include/swift/Frontend/FrontendInputsAndOutputs.h @@ -257,6 +257,7 @@ public: bool hasModuleInterfaceOutputPath() const; bool hasPrivateModuleInterfaceOutputPath() const; bool hasABIDescriptorOutputPath() const; + bool hasConstValuesOutputPath() const; bool hasModuleSemanticInfoOutputPath() const; bool hasModuleSummaryOutputPath() const; bool hasTBDPath() const; diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index cbffd4ca972..a6892681c2d 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -472,6 +472,7 @@ private: static bool canActionEmitModuleSummary(ActionType); static bool canActionEmitInterface(ActionType); static bool canActionEmitABIDescriptor(ActionType); + static bool canActionEmitConstValues(ActionType); static bool canActionEmitModuleSemanticInfo(ActionType); public: diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index c0641d98e9a..d4b633d056b 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -192,6 +192,10 @@ def explicit_swift_module_map : Separate<["-"], "explicit-swift-module-map-file">, MetaVarName<"">, HelpText<"Specify a JSON file containing information of explicit Swift modules">; +def const_gather_protocols_file + : Separate<["-"], "const-gather-protocols-file">, MetaVarName<"">, + HelpText<"Specify a list of protocols for extraction of conformances' const values'">; + def placeholder_dependency_module_map : Separate<["-"], "placeholder-dependency-module-map-file">, MetaVarName<"">, HelpText<"Specify a JSON file containing information of external Swift module dependencies">; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 0a5f5baa01d..e7043fee335 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -524,6 +524,14 @@ def emit_parseable_module_interface_path : Flags<[FrontendOption, NoInteractiveOption, HelpHidden, ArgumentIsPath, SupplementaryOutput]>; +def emit_const_values : + Flag<["-"], "emit-const-values">, + Flags<[NoInteractiveOption, SupplementaryOutput]>; +def emit_const_values_path : Separate<["-"], "emit-const-values-path">, + Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath, + SupplementaryOutput]>, + MetaVarName<"">, HelpText<"Emit the extracted compile-time known values to ">; + def emit_objc_header : Flag<["-"], "emit-objc-header">, Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>, HelpText<"Emit an Objective-C header file">; diff --git a/lib/Basic/FileTypes.cpp b/lib/Basic/FileTypes.cpp index 7c688c9cd0b..88e6aadf705 100644 --- a/lib/Basic/FileTypes.cpp +++ b/lib/Basic/FileTypes.cpp @@ -86,6 +86,7 @@ bool file_types::isTextual(ID Id) { case file_types::TY_JSONDependencies: case file_types::TY_JSONFeatures: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_ConstValues: return true; case file_types::TY_Image: case file_types::TY_Object: @@ -160,6 +161,7 @@ bool file_types::isAfterLLVM(ID Id) { case file_types::TY_JSONFeatures: case file_types::TY_IndexUnitOutputPath: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_ConstValues: return false; case file_types::TY_INVALID: llvm_unreachable("Invalid type ID."); @@ -212,6 +214,7 @@ bool file_types::isPartOfSwiftCompilation(ID Id) { case file_types::TY_JSONFeatures: case file_types::TY_IndexUnitOutputPath: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_ConstValues: return false; case file_types::TY_INVALID: llvm_unreachable("Invalid type ID."); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index b2fca7c9bd8..52513fca5b4 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2082,6 +2082,7 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, case file_types::TY_JSONDependencies: case file_types::TY_JSONFeatures: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_ConstValues: // We could in theory handle assembly or LLVM input, but let's not. // FIXME: What about LTO? Diags.diagnose(SourceLoc(), diag::error_unexpected_input_file, diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index ae2fb710d30..fd25d65b2f6 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -698,6 +698,7 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const { case file_types::TY_SwiftOverlayFile: case file_types::TY_IndexUnitOutputPath: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_ConstValues: llvm_unreachable("Output type can never be primary output."); case file_types::TY_INVALID: llvm_unreachable("Invalid type ID"); @@ -958,6 +959,7 @@ ToolChain::constructInvocation(const BackendJobAction &job, case file_types::TY_SwiftOverlayFile: case file_types::TY_IndexUnitOutputPath: case file_types::TY_SwiftABIDescriptor: + case file_types::TY_ConstValues: llvm_unreachable("Output type can never be primary output."); case file_types::TY_INVALID: llvm_unreachable("Invalid type ID"); diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index de530903d2f..a632692b600 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -654,6 +654,11 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths() Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_abi_descriptor); return true; } + if (!FrontendOptions::canActionEmitConstValues(Opts.RequestedAction) && + Opts.InputsAndOutputs.hasConstValuesOutputPath()) { + Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_const_values); + return true; + } if (!FrontendOptions::canActionEmitModuleSemanticInfo(Opts.RequestedAction) && Opts.InputsAndOutputs.hasModuleSemanticInfoOutputPath()) { Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_semantic_info); diff --git a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp index 1ebaa9837f3..1b982da725a 100644 --- a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp @@ -335,6 +335,8 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments() options::OPT_emit_module_summary_path); auto abiDescriptorOutput = getSupplementaryFilenamesFromArguments( options::OPT_emit_abi_descriptor_path); + auto constValuesOutput = getSupplementaryFilenamesFromArguments( + options::OPT_emit_const_values_path); auto moduleSemanticInfoOutput = getSupplementaryFilenamesFromArguments( options::OPT_emit_module_semantic_info_path); auto optRecordOutput = getSupplementaryFilenamesFromArguments( @@ -367,6 +369,7 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments() sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[i]; sop.ModuleSummaryOutputPath = (*moduleSummaryOutput)[i]; sop.ABIDescriptorOutputPath = (*abiDescriptorOutput)[i]; + sop.ConstValuesOutputPath = (*constValuesOutput)[i]; sop.ModuleSemanticInfoOutputPath = (*moduleSemanticInfoOutput)[i]; sop.YAMLOptRecordPath = (*optRecordOutput)[i]; sop.BitstreamOptRecordPath = (*optRecordOutput)[i]; @@ -426,6 +429,12 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput( file_types::TY_SwiftDeps, "", defaultSupplementaryOutputPathExcludingExtension); + auto constValuesOutputPath = determineSupplementaryOutputFilename( + OPT_emit_const_values, + pathsFromArguments.ConstValuesOutputPath, + file_types::TY_ConstValues, "", + defaultSupplementaryOutputPathExcludingExtension); + auto serializedDiagnosticsPath = determineSupplementaryOutputFilename( OPT_serialize_diagnostics, pathsFromArguments.SerializedDiagnosticsPath, file_types::TY_SerializedDiagnostics, "", @@ -470,7 +479,9 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput( // There is no non-path form of -emit-abi-descriptor-path auto ABIDescriptorOutputPath = pathsFromArguments.ABIDescriptorOutputPath; + // There is no non-path form of -emit-module-semantic-info-path auto ModuleSemanticInfoOutputPath = pathsFromArguments.ModuleSemanticInfoOutputPath; + ID emitModuleOption; std::string moduleExtension; std::string mainOutputIfUsableForModule; @@ -506,6 +517,7 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput( sop.ModuleSourceInfoOutputPath = moduleSourceInfoOutputPath; sop.ModuleSummaryOutputPath = moduleSummaryOutputPath; sop.ABIDescriptorOutputPath = ABIDescriptorOutputPath; + sop.ConstValuesOutputPath = constValuesOutputPath; sop.ModuleSemanticInfoOutputPath = ModuleSemanticInfoOutputPath; sop.YAMLOptRecordPath = YAMLOptRecordPath; sop.BitstreamOptRecordPath = bitstreamOptRecordPath; @@ -594,6 +606,7 @@ createFromTypeToPathMap(const TypeToPathMap *map) { {file_types::TY_YAMLOptRecord, paths.YAMLOptRecordPath}, {file_types::TY_BitstreamOptRecord, paths.BitstreamOptRecordPath}, {file_types::TY_SwiftABIDescriptor, paths.ABIDescriptorOutputPath}, + {file_types::TY_ConstValues, paths.ConstValuesOutputPath} }; for (const std::pair &typeAndString : typesAndStrings) { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 21017dea690..8758260c0ad 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1350,6 +1350,9 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, if (const Arg *A = Args.getLastArg(OPT_batch_scan_input_file)) Opts.BatchScanInputFilePath = A->getValue(); + if (const Arg *A = Args.getLastArg(OPT_const_gather_protocols_file)) + Opts.ConstGatherProtocolListFilePath = A->getValue(); + for (auto A : Args.getAllArgValues(options::OPT_serialized_path_obfuscate)) { auto SplitMap = StringRef(A).split('='); Opts.DeserializedPathRecoverer.addMapping(SplitMap.first, SplitMap.second); diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index f688a972f43..f9ca9061739 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -105,6 +105,11 @@ std::string CompilerInvocation::getReferenceDependenciesFilePathForPrimary( return getPrimarySpecificPathsForPrimary(filename) .SupplementaryOutputs.ReferenceDependenciesFilePath; } +std::string CompilerInvocation::getConstValuesFilePathForPrimary( + StringRef filename) const { + return getPrimarySpecificPathsForPrimary(filename) + .SupplementaryOutputs.ConstValuesOutputPath; +} std::string CompilerInvocation::getSerializedDiagnosticsPathForAtMostOnePrimary() const { return getPrimarySpecificPathsForAtMostOnePrimary() diff --git a/lib/Frontend/FrontendInputsAndOutputs.cpp b/lib/Frontend/FrontendInputsAndOutputs.cpp index ca2746ff6ec..5b7b78750c2 100644 --- a/lib/Frontend/FrontendInputsAndOutputs.cpp +++ b/lib/Frontend/FrontendInputsAndOutputs.cpp @@ -509,6 +509,12 @@ bool FrontendInputsAndOutputs::hasABIDescriptorOutputPath() const { return outs.ABIDescriptorOutputPath; }); } +bool FrontendInputsAndOutputs::hasConstValuesOutputPath() const { + return hasSupplementaryOutputPath( + [](const SupplementaryOutputPaths &outs) -> const std::string & { + return outs.ConstValuesOutputPath; + }); +} bool FrontendInputsAndOutputs::hasModuleSemanticInfoOutputPath() const { return hasSupplementaryOutputPath( [](const SupplementaryOutputPaths &outs) -> const std::string & { diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index 84ecf13f446..4bffba49f09 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -582,6 +582,48 @@ bool FrontendOptions::canActionEmitABIDescriptor(ActionType action) { return true; return false; } +bool FrontendOptions::canActionEmitConstValues(ActionType action) { + switch (action) { + case ActionType::NoneAction: + case ActionType::Parse: + case ActionType::ResolveImports: + case ActionType::DumpParse: + case ActionType::DumpInterfaceHash: + case ActionType::DumpAST: + case ActionType::EmitSyntax: + case ActionType::PrintAST: + case ActionType::PrintASTDecl: + case ActionType::DumpScopeMaps: + case ActionType::DumpTypeRefinementContexts: + case ActionType::DumpTypeInfo: + case ActionType::CompileModuleFromInterface: + case ActionType::TypecheckModuleFromInterface: + case ActionType::Immediate: + case ActionType::REPL: + case ActionType::EmitPCM: + case ActionType::DumpPCM: + case ActionType::ScanDependencies: + case ActionType::PrintVersion: + case ActionType::PrintFeature: + return false; + case ActionType::Typecheck: + case ActionType::MergeModules: + case ActionType::EmitModuleOnly: + case ActionType::EmitPCH: + case ActionType::EmitSILGen: + case ActionType::EmitSIL: + case ActionType::EmitSIBGen: + case ActionType::EmitSIB: + case ActionType::EmitIRGen: + case ActionType::EmitIR: + case ActionType::EmitBC: + case ActionType::EmitAssembly: + case ActionType::EmitObject: + case ActionType::EmitImportedModules: + return true; + } + llvm_unreachable("unhandled action"); +} bool FrontendOptions::canActionEmitModule(ActionType action) { switch (action) { case ActionType::NoneAction: diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 8de0d7d080c..07cb28fc6da 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -693,6 +693,42 @@ static void emitSwiftdepsForAllPrimaryInputsIfNeeded( } } +static bool emitConstValuesForWholeModuleIfNeeded( + CompilerInstance &Instance) { + const auto &Invocation = Instance.getInvocation(); + const auto &frontendOpts = Invocation.getFrontendOptions(); + if (!frontendOpts.InputsAndOutputs.hasConstValuesOutputPath()) + return false; + std::error_code EC; + assert(frontendOpts.InputsAndOutputs.isWholeModule() && + "'emitConstValuesForWholeModule' only makes sense when the whole module can be seen"); + auto ConstValuesFilePath = frontendOpts.InputsAndOutputs + .getPrimarySpecificPathsForAtMostOnePrimary().SupplementaryOutputs + .ConstValuesOutputPath; + llvm::raw_fd_ostream OS(ConstValuesFilePath, EC, llvm::sys::fs::OF_None); + OS << "{}\n"; + return false; +} + +static void emitConstValuesForAllPrimaryInputsIfNeeded( + CompilerInstance &Instance) { + const auto &Invocation = Instance.getInvocation(); + + for (auto *SF : Instance.getPrimarySourceFiles()) { + const std::string &ConstValuesFilePath = + Invocation.getConstValuesFilePathForPrimary( + SF->getFilename()); + if (ConstValuesFilePath.empty()) { + continue; + } + + // TODO: Emit extracted values + std::error_code EC; + llvm::raw_fd_ostream OS(ConstValuesFilePath, EC, llvm::sys::fs::OF_None); + OS << "{}\n"; + } +} + static bool writeModuleSemanticInfoIfNeeded(CompilerInstance &Instance) { const auto &Invocation = Instance.getInvocation(); const auto &frontendOpts = Invocation.getFrontendOptions(); @@ -900,6 +936,10 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs( { hadAnyError |= writeModuleSemanticInfoIfNeeded(Instance); } + + { + hadAnyError |= emitConstValuesForWholeModuleIfNeeded(Instance); + } return hadAnyError; } @@ -1072,6 +1112,9 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) { // Emit Make-style dependencies. emitMakeDependenciesIfNeeded(Instance.getDiags(), Instance.getDependencyTracker(), opts); + + // Emit extracted constant values for every file in the batch + emitConstValuesForAllPrimaryInputsIfNeeded(Instance); } static bool printSwiftVersion(const CompilerInvocation &Invocation) { diff --git a/test/Frontend/emit-const-values-file.swift b/test/Frontend/emit-const-values-file.swift new file mode 100644 index 00000000000..68ee21eff54 --- /dev/null +++ b/test/Frontend/emit-const-values-file.swift @@ -0,0 +1,17 @@ +// RUN: %empty-directory(%t) +// RUN: echo 'print("Hello, World!")' >%t/main.swift +// RUN: cd %t + +// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/main.swiftconstvalues -primary-file %t/main.swift +// RUN: test -f %t/main.swiftconstvalues + +// RUN: echo '"%/t/main.swift": { const-values: "%/t/foo.swiftconstvalues" }' > %/t/filemap.json +// RUN: %target-swift-frontend -typecheck -supplementary-output-file-map %/t/filemap.json -primary-file %/t/main.swift +// RUN: test -f %t/foo.swiftconstvalues + +// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/main.module.swiftconstvalues %t/main.swift +// RUN: test -f %t/main.module.swiftconstvalues + +// RUN: echo '{"%/t/main.swift": { const-values: "%/t/main.module.swiftconstvalues" }}' > %/t/filemap.json +// RUN: %target-swift-frontend -typecheck -supplementary-output-file-map %/t/filemap.json %/t/main.swift +// RUN: test -f %t/main.module.swiftconstvalues diff --git a/test/Frontend/supplementary-output-support.swift b/test/Frontend/supplementary-output-support.swift index 30fa6bf7406..5f9dc91e807 100644 --- a/test/Frontend/supplementary-output-support.swift +++ b/test/Frontend/supplementary-output-support.swift @@ -33,3 +33,6 @@ // PARSE_NO_PRIVATE_INTERFACE: error: this mode does not support emitting module interface files{{$}} // RUN: not %target-swift-frontend -emit-silgen -emit-private-module-interface-path %t %s 2>&1 | %FileCheck -check-prefix=SILGEN_NO_PRIVATE_INTERFACE %s // SILGEN_NO_PRIVATE_INTERFACE: error: this mode does not support emitting module interface files{{$}} + +// RUN: not %target-swift-frontend -parse -emit-const-values-path %t %s 2>&1 | %FileCheck -check-prefix=PARSE_NO_CONST_VALUES %s +// PARSE_NO_CONST_VALUES: error: this mode does not support emitting extracted const values{{$}}