mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Implement a new "fast" dependency scanning option, `-scan-dependencies`, in the Swift frontend that determines all of the source file and module dependencies for a given set of Swift sources. It covers four forms of modules: 1) Swift (serialized) module files, by reading the module header 2) Swift interface files, by parsing the source code to find imports 3) Swift source modules, by parsing the source code to find imports 4) Clang modules, using Clang's fast dependency scanning tool A single `-scan-dependencies` operation maps out the full dependency graph for the given Swift source files, including all of the Swift and Clang modules that may need to be built, such that all of the work can be scheduled up front by the Swift driver or any other build system that understands this option. The dependency graph is emitted as JSON, which can be consumed by these other tools.
584 lines
21 KiB
C++
584 lines
21 KiB
C++
//===--- ArgsToFrontendOptionsConverter -----------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ArgsToFrontendOptionsConverter.h"
|
|
|
|
#include "ArgsToFrontendInputsConverter.h"
|
|
#include "ArgsToFrontendOutputsConverter.h"
|
|
#include "swift/AST/DiagnosticsFrontend.h"
|
|
#include "swift/Basic/Platform.h"
|
|
#include "swift/Frontend/Frontend.h"
|
|
#include "swift/Option/Options.h"
|
|
#include "swift/Option/SanitizerOptions.h"
|
|
#include "swift/Parse/Lexer.h"
|
|
#include "swift/Strings.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/Triple.h"
|
|
#include "llvm/Option/Arg.h"
|
|
#include "llvm/Option/ArgList.h"
|
|
#include "llvm/Option/Option.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/LineIterator.h"
|
|
#include "llvm/Support/Path.h"
|
|
|
|
using namespace swift;
|
|
using namespace llvm::opt;
|
|
|
|
// This is a separate function so that it shows up in stack traces.
|
|
LLVM_ATTRIBUTE_NOINLINE
|
|
static void debugFailWithAssertion() {
|
|
// This assertion should always fail, per the user's request, and should
|
|
// not be converted to llvm_unreachable.
|
|
assert(0 && "This is an assertion!");
|
|
}
|
|
|
|
// This is a separate function so that it shows up in stack traces.
|
|
LLVM_ATTRIBUTE_NOINLINE
|
|
static void debugFailWithCrash() { LLVM_BUILTIN_TRAP; }
|
|
|
|
bool ArgsToFrontendOptionsConverter::convert(
|
|
SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> *buffers) {
|
|
using namespace options;
|
|
|
|
handleDebugCrashGroupArguments();
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_dump_api_path)) {
|
|
Opts.DumpAPIPath = A->getValue();
|
|
}
|
|
if (const Arg *A = Args.getLastArg(OPT_group_info_path)) {
|
|
Opts.GroupInfoPath = A->getValue();
|
|
}
|
|
if (const Arg *A = Args.getLastArg(OPT_index_store_path)) {
|
|
Opts.IndexStorePath = A->getValue();
|
|
}
|
|
if (const Arg *A = Args.getLastArg(OPT_prebuilt_module_cache_path)) {
|
|
Opts.PrebuiltModuleCachePath = A->getValue();
|
|
}
|
|
if (const Arg *A = Args.getLastArg(OPT_bridging_header_directory_for_print)) {
|
|
Opts.BridgingHeaderDirForPrint = A->getValue();
|
|
}
|
|
Opts.IndexSystemModules |= Args.hasArg(OPT_index_system_modules);
|
|
Opts.IndexIgnoreStdlib |= Args.hasArg(OPT_index_ignore_stdlib);
|
|
|
|
Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
|
|
Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil);
|
|
|
|
Opts.EnableTesting |= Args.hasArg(OPT_enable_testing);
|
|
Opts.EnablePrivateImports |= Args.hasArg(OPT_enable_private_imports);
|
|
Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_library_evolution);
|
|
|
|
// FIXME: Remove this flag
|
|
Opts.EnableLibraryEvolution |= Args.hasArg(OPT_enable_resilience);
|
|
|
|
Opts.EnableImplicitDynamic |= Args.hasArg(OPT_enable_implicit_dynamic);
|
|
|
|
Opts.TrackSystemDeps |= Args.hasArg(OPT_track_system_dependencies);
|
|
|
|
Opts.SerializeModuleInterfaceDependencyHashes |=
|
|
Args.hasArg(OPT_serialize_module_interface_dependency_hashes);
|
|
|
|
Opts.RemarkOnRebuildFromModuleInterface |=
|
|
Args.hasArg(OPT_Rmodule_interface_rebuild);
|
|
|
|
Opts.DisableInterfaceFileLock |= Args.hasArg(OPT_disable_interface_lockfile);
|
|
|
|
computePrintStatsOptions();
|
|
computeDebugTimeOptions();
|
|
computeTBDOptions();
|
|
|
|
Opts.CheckOnoneSupportCompleteness = Args.hasArg(OPT_check_onone_completeness);
|
|
|
|
Opts.DebuggerTestingTransform = Args.hasArg(OPT_debugger_testing_transform);
|
|
|
|
computePlaygroundOptions();
|
|
|
|
// This can be enabled independently of the playground transform.
|
|
Opts.PCMacro |= Args.hasArg(OPT_pc_macro);
|
|
|
|
Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
|
|
|
|
Opts.IgnoreSwiftSourceInfo |= Args.hasArg(OPT_ignore_module_source_info);
|
|
computeHelpOptions();
|
|
|
|
if (Args.hasArg(OPT_print_target_info)) {
|
|
Opts.PrintTargetInfo = true;
|
|
}
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
|
|
Opts.VerifyGenericSignaturesInModule = A->getValue();
|
|
}
|
|
|
|
computeDumpScopeMapLocations();
|
|
|
|
Optional<FrontendInputsAndOutputs> inputsAndOutputs =
|
|
ArgsToFrontendInputsConverter(Diags, Args).convert(buffers);
|
|
|
|
// None here means error, not just "no inputs". Propagage unconditionally.
|
|
if (!inputsAndOutputs)
|
|
return true;
|
|
|
|
// InputsAndOutputs can only get set up once; if it was set already when we
|
|
// entered this function, we should not set it again (and should assert this
|
|
// is not being done). Further, the computeMainAndSupplementaryOutputFilenames
|
|
// call below needs to only happen when there was a new InputsAndOutputs,
|
|
// since it clobbers the existing one rather than adding to it.
|
|
bool HaveNewInputsAndOutputs = false;
|
|
if (Opts.InputsAndOutputs.hasInputs()) {
|
|
assert(!inputsAndOutputs->hasInputs());
|
|
} else {
|
|
HaveNewInputsAndOutputs = true;
|
|
Opts.InputsAndOutputs = std::move(inputsAndOutputs).getValue();
|
|
}
|
|
|
|
if (Opts.RequestedAction == FrontendOptions::ActionType::NoneAction) {
|
|
Opts.RequestedAction = determineRequestedAction(Args);
|
|
}
|
|
|
|
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
|
|
Opts.InputsAndOutputs.hasPrimaryInputs()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
|
|
return true;
|
|
}
|
|
|
|
if (setUpInputKindAndImmediateArgs())
|
|
return true;
|
|
|
|
if (computeModuleName())
|
|
return true;
|
|
|
|
if (HaveNewInputsAndOutputs &&
|
|
computeMainAndSupplementaryOutputFilenames())
|
|
return true;
|
|
|
|
if (checkUnusedSupplementaryOutputPaths())
|
|
return true;
|
|
|
|
if (FrontendOptions::doesActionGenerateIR(Opts.RequestedAction)
|
|
&& Args.hasArg(OPT_experimental_skip_non_inlinable_function_bodies)) {
|
|
Diags.diagnose(SourceLoc(), diag::cannot_emit_ir_skipping_function_bodies);
|
|
return true;
|
|
}
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_module_link_name))
|
|
Opts.ModuleLinkName = A->getValue();
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_serialize_debugging_options,
|
|
OPT_no_serialize_debugging_options)) {
|
|
Opts.SerializeOptionsForDebugging =
|
|
A->getOption().matches(OPT_serialize_debugging_options);
|
|
}
|
|
|
|
Opts.EnableSourceImport |= Args.hasArg(OPT_enable_source_import);
|
|
Opts.ImportUnderlyingModule |= Args.hasArg(OPT_import_underlying_module);
|
|
Opts.EnableIncrementalDependencyVerifier |= Args.hasArg(OPT_verify_incremental_dependencies);
|
|
|
|
computeImportObjCHeaderOptions();
|
|
computeImplicitImportModuleNames();
|
|
computeLLVMArgs();
|
|
|
|
return false;
|
|
}
|
|
|
|
void ArgsToFrontendOptionsConverter::handleDebugCrashGroupArguments() {
|
|
using namespace options;
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_debug_crash_Group)) {
|
|
Option Opt = A->getOption();
|
|
if (Opt.matches(OPT_debug_assert_immediately)) {
|
|
debugFailWithAssertion();
|
|
} else if (Opt.matches(OPT_debug_crash_immediately)) {
|
|
debugFailWithCrash();
|
|
} else if (Opt.matches(OPT_debug_assert_after_parse)) {
|
|
// Set in FrontendOptions
|
|
Opts.CrashMode = FrontendOptions::DebugCrashMode::AssertAfterParse;
|
|
} else if (Opt.matches(OPT_debug_crash_after_parse)) {
|
|
// Set in FrontendOptions
|
|
Opts.CrashMode = FrontendOptions::DebugCrashMode::CrashAfterParse;
|
|
} else {
|
|
llvm_unreachable("Unknown debug_crash_Group option!");
|
|
}
|
|
}
|
|
}
|
|
|
|
void ArgsToFrontendOptionsConverter::computePrintStatsOptions() {
|
|
using namespace options;
|
|
Opts.PrintStats |= Args.hasArg(OPT_print_stats);
|
|
Opts.PrintClangStats |= Args.hasArg(OPT_print_clang_stats);
|
|
#if defined(NDEBUG) && !defined(LLVM_ENABLE_STATS)
|
|
if (Opts.PrintStats || Opts.PrintClangStats)
|
|
Diags.diagnose(SourceLoc(), diag::stats_disabled);
|
|
#endif
|
|
}
|
|
|
|
void ArgsToFrontendOptionsConverter::computeDebugTimeOptions() {
|
|
using namespace options;
|
|
Opts.DebugTimeCompilation |= Args.hasArg(OPT_debug_time_compilation);
|
|
|
|
if (const Arg *A = Args.getLastArg(OPT_stats_output_dir)) {
|
|
Opts.StatsOutputDir = A->getValue();
|
|
if (Args.getLastArg(OPT_trace_stats_events)) {
|
|
Opts.TraceStats = true;
|
|
}
|
|
if (Args.getLastArg(OPT_profile_stats_events)) {
|
|
Opts.ProfileEvents = true;
|
|
}
|
|
if (Args.getLastArg(OPT_profile_stats_entities)) {
|
|
Opts.ProfileEntities = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ArgsToFrontendOptionsConverter::computeTBDOptions() {
|
|
using namespace options;
|
|
if (const Arg *A = Args.getLastArg(OPT_validate_tbd_against_ir_EQ)) {
|
|
using Mode = FrontendOptions::TBDValidationMode;
|
|
StringRef value = A->getValue();
|
|
if (value == "none") {
|
|
Opts.ValidateTBDAgainstIR = Mode::None;
|
|
} else if (value == "missing") {
|
|
Opts.ValidateTBDAgainstIR = Mode::MissingFromTBD;
|
|
} else if (value == "all") {
|
|
Opts.ValidateTBDAgainstIR = Mode::All;
|
|
} else {
|
|
Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument,
|
|
A->getOption().getPrefixedName(), value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ArgsToFrontendOptionsConverter::computePlaygroundOptions() {
|
|
using namespace options;
|
|
Opts.PlaygroundTransform |= Args.hasArg(OPT_playground);
|
|
if (Args.hasArg(OPT_disable_playground_transform))
|
|
Opts.PlaygroundTransform = false;
|
|
Opts.PlaygroundHighPerformance |=
|
|
Args.hasArg(OPT_playground_high_performance);
|
|
}
|
|
|
|
void ArgsToFrontendOptionsConverter::computeHelpOptions() {
|
|
using namespace options;
|
|
if (const Arg *A = Args.getLastArg(OPT_help, OPT_help_hidden)) {
|
|
if (A->getOption().matches(OPT_help)) {
|
|
Opts.PrintHelp = true;
|
|
} else if (A->getOption().matches(OPT_help_hidden)) {
|
|
Opts.PrintHelpHidden = true;
|
|
} else {
|
|
llvm_unreachable("Unknown help option parsed");
|
|
}
|
|
}
|
|
}
|
|
|
|
void ArgsToFrontendOptionsConverter::computeDumpScopeMapLocations() {
|
|
using namespace options;
|
|
const Arg *A = Args.getLastArg(OPT_modes_Group);
|
|
if (!A || !A->getOption().matches(OPT_dump_scope_maps))
|
|
return;
|
|
StringRef value = A->getValue();
|
|
if (value == "expanded") {
|
|
// Note: fully expanded the scope map.
|
|
return;
|
|
}
|
|
// Parse a comma-separated list of line:column for lookups to
|
|
// perform (and dump the result of).
|
|
SmallVector<StringRef, 4> locations;
|
|
value.split(locations, ',');
|
|
|
|
bool invalid = false;
|
|
for (auto location : locations) {
|
|
auto lineColumnStr = location.split(':');
|
|
unsigned line, column;
|
|
if (lineColumnStr.first.getAsInteger(10, line) ||
|
|
lineColumnStr.second.getAsInteger(10, column)) {
|
|
Diags.diagnose(SourceLoc(), diag::error_invalid_source_location_str,
|
|
location);
|
|
invalid = true;
|
|
continue;
|
|
}
|
|
Opts.DumpScopeMapLocations.push_back({line, column});
|
|
}
|
|
|
|
if (!invalid && Opts.DumpScopeMapLocations.empty())
|
|
Diags.diagnose(SourceLoc(), diag::error_no_source_location_scope_map);
|
|
}
|
|
|
|
FrontendOptions::ActionType
|
|
ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) {
|
|
using namespace options;
|
|
const Arg *A = args.getLastArg(OPT_modes_Group);
|
|
if (!A) {
|
|
// We don't have a mode, so determine a default.
|
|
if (args.hasArg(OPT_emit_module, OPT_emit_module_path)) {
|
|
// We've been told to emit a module, but have no other mode indicators.
|
|
// As a result, put the frontend into EmitModuleOnly mode.
|
|
// (Setting up module output will be handled below.)
|
|
return FrontendOptions::ActionType::EmitModuleOnly;
|
|
}
|
|
return FrontendOptions::ActionType::NoneAction;
|
|
}
|
|
Option Opt = A->getOption();
|
|
if (Opt.matches(OPT_emit_object))
|
|
return FrontendOptions::ActionType::EmitObject;
|
|
if (Opt.matches(OPT_emit_assembly))
|
|
return FrontendOptions::ActionType::EmitAssembly;
|
|
if (Opt.matches(OPT_emit_ir))
|
|
return FrontendOptions::ActionType::EmitIR;
|
|
if (Opt.matches(OPT_emit_bc))
|
|
return FrontendOptions::ActionType::EmitBC;
|
|
if (Opt.matches(OPT_emit_sil))
|
|
return FrontendOptions::ActionType::EmitSIL;
|
|
if (Opt.matches(OPT_emit_silgen))
|
|
return FrontendOptions::ActionType::EmitSILGen;
|
|
if (Opt.matches(OPT_emit_sib))
|
|
return FrontendOptions::ActionType::EmitSIB;
|
|
if (Opt.matches(OPT_emit_sibgen))
|
|
return FrontendOptions::ActionType::EmitSIBGen;
|
|
if (Opt.matches(OPT_emit_pch))
|
|
return FrontendOptions::ActionType::EmitPCH;
|
|
if (Opt.matches(OPT_emit_imported_modules))
|
|
return FrontendOptions::ActionType::EmitImportedModules;
|
|
if (Opt.matches(OPT_scan_dependencies))
|
|
return FrontendOptions::ActionType::ScanDependencies;
|
|
if (Opt.matches(OPT_parse))
|
|
return FrontendOptions::ActionType::Parse;
|
|
if (Opt.matches(OPT_resolve_imports))
|
|
return FrontendOptions::ActionType::ResolveImports;
|
|
if (Opt.matches(OPT_typecheck))
|
|
return FrontendOptions::ActionType::Typecheck;
|
|
if (Opt.matches(OPT_dump_parse))
|
|
return FrontendOptions::ActionType::DumpParse;
|
|
if (Opt.matches(OPT_dump_ast))
|
|
return FrontendOptions::ActionType::DumpAST;
|
|
if (Opt.matches(OPT_emit_syntax))
|
|
return FrontendOptions::ActionType::EmitSyntax;
|
|
if (Opt.matches(OPT_merge_modules))
|
|
return FrontendOptions::ActionType::MergeModules;
|
|
if (Opt.matches(OPT_dump_scope_maps))
|
|
return FrontendOptions::ActionType::DumpScopeMaps;
|
|
if (Opt.matches(OPT_dump_type_refinement_contexts))
|
|
return FrontendOptions::ActionType::DumpTypeRefinementContexts;
|
|
if (Opt.matches(OPT_dump_interface_hash))
|
|
return FrontendOptions::ActionType::DumpInterfaceHash;
|
|
if (Opt.matches(OPT_dump_type_info))
|
|
return FrontendOptions::ActionType::DumpTypeInfo;
|
|
if (Opt.matches(OPT_print_ast))
|
|
return FrontendOptions::ActionType::PrintAST;
|
|
if (Opt.matches(OPT_emit_pcm))
|
|
return FrontendOptions::ActionType::EmitPCM;
|
|
if (Opt.matches(OPT_dump_pcm))
|
|
return FrontendOptions::ActionType::DumpPCM;
|
|
|
|
if (Opt.matches(OPT_repl) || Opt.matches(OPT_deprecated_integrated_repl))
|
|
return FrontendOptions::ActionType::REPL;
|
|
if (Opt.matches(OPT_interpret))
|
|
return FrontendOptions::ActionType::Immediate;
|
|
if (Opt.matches(OPT_compile_module_from_interface))
|
|
return FrontendOptions::ActionType::CompileModuleFromInterface;
|
|
|
|
llvm_unreachable("Unhandled mode option");
|
|
}
|
|
|
|
bool ArgsToFrontendOptionsConverter::setUpInputKindAndImmediateArgs() {
|
|
using namespace options;
|
|
bool treatAsSIL =
|
|
Args.hasArg(OPT_parse_sil) || Opts.InputsAndOutputs.shouldTreatAsSIL();
|
|
|
|
if (Opts.InputsAndOutputs.verifyInputs(
|
|
Diags, treatAsSIL,
|
|
Opts.RequestedAction == FrontendOptions::ActionType::REPL,
|
|
Opts.RequestedAction == FrontendOptions::ActionType::NoneAction)) {
|
|
return true;
|
|
}
|
|
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) {
|
|
Opts.ImmediateArgv.push_back(
|
|
Opts.InputsAndOutputs.getFilenameOfFirstInput()); // argv[0]
|
|
if (const Arg *A = Args.getLastArg(OPT__DASH_DASH)) {
|
|
for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) {
|
|
Opts.ImmediateArgv.push_back(A->getValue(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (treatAsSIL)
|
|
Opts.InputKind = InputFileKind::SIL;
|
|
else if (Opts.InputsAndOutputs.shouldTreatAsLLVM())
|
|
Opts.InputKind = InputFileKind::LLVM;
|
|
else if (Opts.InputsAndOutputs.shouldTreatAsModuleInterface())
|
|
Opts.InputKind = InputFileKind::SwiftModuleInterface;
|
|
else if (Args.hasArg(OPT_parse_as_library))
|
|
Opts.InputKind = InputFileKind::SwiftLibrary;
|
|
else if (Opts.RequestedAction == FrontendOptions::ActionType::REPL)
|
|
Opts.InputKind = InputFileKind::SwiftREPL;
|
|
else
|
|
Opts.InputKind = InputFileKind::Swift;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ArgsToFrontendOptionsConverter::computeModuleName() {
|
|
const Arg *A = Args.getLastArg(options::OPT_module_name);
|
|
if (A) {
|
|
Opts.ModuleName = A->getValue();
|
|
} else if (Opts.ModuleName.empty()) {
|
|
// The user did not specify a module name, so determine a default fallback
|
|
// based on other options.
|
|
|
|
// Note: this code path will only be taken when running the frontend
|
|
// directly; the driver should always pass -module-name when invoking the
|
|
// frontend.
|
|
if (computeFallbackModuleName())
|
|
return true;
|
|
}
|
|
|
|
if (Lexer::isIdentifier(Opts.ModuleName) &&
|
|
(Opts.ModuleName != STDLIB_NAME || Opts.ParseStdlib)) {
|
|
return false;
|
|
}
|
|
if (!FrontendOptions::needsProperModuleName(Opts.RequestedAction) ||
|
|
Opts.isCompilingExactlyOneSwiftFile()) {
|
|
Opts.ModuleName = "main";
|
|
return false;
|
|
}
|
|
auto DID = (Opts.ModuleName == STDLIB_NAME) ? diag::error_stdlib_module_name
|
|
: diag::error_bad_module_name;
|
|
Diags.diagnose(SourceLoc(), DID, Opts.ModuleName, A == nullptr);
|
|
Opts.ModuleName = "__bad__";
|
|
return false; // FIXME: Must continue to run to pass the tests, but should not
|
|
// have to.
|
|
}
|
|
|
|
bool ArgsToFrontendOptionsConverter::computeFallbackModuleName() {
|
|
if (Opts.RequestedAction == FrontendOptions::ActionType::REPL) {
|
|
// Default to a module named "REPL" if we're in REPL mode.
|
|
Opts.ModuleName = "REPL";
|
|
return false;
|
|
}
|
|
// In order to pass some tests, must leave ModuleName empty.
|
|
if (!Opts.InputsAndOutputs.hasInputs()) {
|
|
Opts.ModuleName = std::string();
|
|
// FIXME: This is a bug that should not happen, but does in tests.
|
|
// The compiler should bail out earlier, where "no frontend action was
|
|
// selected".
|
|
return false;
|
|
}
|
|
Optional<std::vector<std::string>> outputFilenames =
|
|
OutputFilesComputer::getOutputFilenamesFromCommandLineOrFilelist(Args,
|
|
Diags);
|
|
|
|
std::string nameToStem =
|
|
outputFilenames && outputFilenames->size() == 1 &&
|
|
outputFilenames->front() != "-" &&
|
|
!llvm::sys::fs::is_directory(outputFilenames->front())
|
|
? outputFilenames->front()
|
|
: Opts.InputsAndOutputs.getFilenameOfFirstInput();
|
|
|
|
Opts.ModuleName = llvm::sys::path::stem(nameToStem).str();
|
|
return false;
|
|
}
|
|
|
|
bool ArgsToFrontendOptionsConverter::
|
|
computeMainAndSupplementaryOutputFilenames() {
|
|
std::vector<std::string> mainOutputs;
|
|
std::vector<SupplementaryOutputPaths> supplementaryOutputs;
|
|
const bool hadError = ArgsToFrontendOutputsConverter(
|
|
Args, Opts.ModuleName, Opts.InputsAndOutputs, Diags)
|
|
.convert(mainOutputs, supplementaryOutputs);
|
|
if (hadError)
|
|
return true;
|
|
Opts.InputsAndOutputs.setMainAndSupplementaryOutputs(mainOutputs,
|
|
supplementaryOutputs);
|
|
return false;
|
|
}
|
|
|
|
bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths()
|
|
const {
|
|
if (!FrontendOptions::canActionEmitDependencies(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasDependenciesPath()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_dependencies);
|
|
return true;
|
|
}
|
|
if (!FrontendOptions::canActionEmitReferenceDependencies(Opts.RequestedAction)
|
|
&& Opts.InputsAndOutputs.hasReferenceDependenciesPath()) {
|
|
Diags.diagnose(SourceLoc(),
|
|
diag::error_mode_cannot_emit_reference_dependencies);
|
|
return true;
|
|
}
|
|
if (!FrontendOptions::canActionEmitSwiftRanges(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasSwiftRangesPath()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_swift_ranges);
|
|
return true;
|
|
}
|
|
if (!FrontendOptions::canActionEmitCompiledSource(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasCompiledSourcePath()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_compiled_source);
|
|
return true;
|
|
}
|
|
if (!FrontendOptions::canActionEmitObjCHeader(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasObjCHeaderOutputPath()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_header);
|
|
return true;
|
|
}
|
|
if (!FrontendOptions::canActionEmitLoadedModuleTrace(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasLoadedModuleTracePath()) {
|
|
Diags.diagnose(SourceLoc(),
|
|
diag::error_mode_cannot_emit_loaded_module_trace);
|
|
return true;
|
|
}
|
|
if (!FrontendOptions::canActionEmitModule(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasModuleOutputPath()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module);
|
|
return true;
|
|
}
|
|
if (!FrontendOptions::canActionEmitModuleDoc(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasModuleDocOutputPath()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_doc);
|
|
return true;
|
|
}
|
|
// If we cannot emit module doc, we cannot emit source information file either.
|
|
if (!FrontendOptions::canActionEmitModuleDoc(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasModuleSourceInfoOutputPath()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_source_info);
|
|
return true;
|
|
}
|
|
if (!FrontendOptions::canActionEmitInterface(Opts.RequestedAction) &&
|
|
Opts.InputsAndOutputs.hasModuleInterfaceOutputPath()) {
|
|
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_interface);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void ArgsToFrontendOptionsConverter::computeImportObjCHeaderOptions() {
|
|
using namespace options;
|
|
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) {
|
|
Opts.ImplicitObjCHeaderPath = A->getValue();
|
|
Opts.SerializeBridgingHeader |= !Opts.InputsAndOutputs.hasPrimaryInputs();
|
|
}
|
|
}
|
|
void ArgsToFrontendOptionsConverter::computeImplicitImportModuleNames() {
|
|
using namespace options;
|
|
for (const Arg *A : Args.filtered(OPT_import_module)) {
|
|
auto *moduleStr = A->getValue();
|
|
if (!Lexer::isIdentifier(moduleStr)) {
|
|
Diags.diagnose(SourceLoc(), diag::error_bad_module_name, moduleStr,
|
|
/*suggestModuleNameFlag*/ false);
|
|
continue;
|
|
}
|
|
Opts.ImplicitImportModuleNames.push_back(moduleStr);
|
|
}
|
|
}
|
|
void ArgsToFrontendOptionsConverter::computeLLVMArgs() {
|
|
using namespace options;
|
|
for (const Arg *A : Args.filtered(OPT_Xllvm)) {
|
|
Opts.LLVMArgs.push_back(A->getValue());
|
|
}
|
|
}
|