mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Cleaner handling of cases where action produces no output or where there are no inputs.
This commit is contained in:
@@ -124,10 +124,24 @@ public:
|
|||||||
const llvm::opt::ArgList &args, DiagnosticEngine &diags,
|
const llvm::opt::ArgList &args, DiagnosticEngine &diags,
|
||||||
const FrontendInputsAndOutputs &inputsAndOutputs,
|
const FrontendInputsAndOutputs &inputsAndOutputs,
|
||||||
ArrayRef<std::string> outputFiles, StringRef moduleName);
|
ArrayRef<std::string> outputFiles, StringRef moduleName);
|
||||||
Optional<SupplementaryOutputPaths> computeOutputPaths() const;
|
Optional<std::vector<SupplementaryOutputPaths>> computeOutputPaths() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// \return None if error.
|
/// \Return a set of supplementary output paths for each input that might
|
||||||
|
/// produce supplementary outputs, or None to signal an error.
|
||||||
|
/// \note
|
||||||
|
/// At present, only one input can produce supplementary outputs, but
|
||||||
|
/// in the future, batch-mode will support multiple primary inputs and thus,
|
||||||
|
/// multiple sets of supplementary outputs. This function is written with that
|
||||||
|
/// future in mind.
|
||||||
|
/// \par
|
||||||
|
/// The paths are derived from arguments
|
||||||
|
/// such as -emit-module-path. These are not the final computed paths,
|
||||||
|
/// merely the ones passed in via the command line.
|
||||||
|
/// \note
|
||||||
|
/// In the future, these will also include those passed in via whatever
|
||||||
|
/// filelist scheme gets implemented to handle cases where the command line
|
||||||
|
/// arguments become burdensome.
|
||||||
Optional<std::vector<SupplementaryOutputPaths>>
|
Optional<std::vector<SupplementaryOutputPaths>>
|
||||||
getSupplementaryOutputPathsFromArguments() const;
|
getSupplementaryOutputPathsFromArguments() const;
|
||||||
|
|
||||||
|
|||||||
@@ -441,9 +441,6 @@ bool ArgsToFrontendOptionsConverter::
|
|||||||
.convert(mainOutputs, supplementaryOutputs);
|
.convert(mainOutputs, supplementaryOutputs);
|
||||||
if (hadError)
|
if (hadError)
|
||||||
return true;
|
return true;
|
||||||
assert(FrontendOptions::doesActionProduceOutput(Opts.RequestedAction) ||
|
|
||||||
mainOutputs.empty() &&
|
|
||||||
"Should be no main outputs if action does not produce them");
|
|
||||||
Opts.InputsAndOutputs.setMainAndSupplementaryOutputs(mainOutputs,
|
Opts.InputsAndOutputs.setMainAndSupplementaryOutputs(mainOutputs,
|
||||||
supplementaryOutputs);
|
supplementaryOutputs);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -34,10 +34,6 @@ using namespace llvm::opt;
|
|||||||
bool ArgsToFrontendOutputsConverter::convert(
|
bool ArgsToFrontendOutputsConverter::convert(
|
||||||
std::vector<std::string> &mainOutputs,
|
std::vector<std::string> &mainOutputs,
|
||||||
SupplementaryOutputPaths &supplementaryOutputs) {
|
SupplementaryOutputPaths &supplementaryOutputs) {
|
||||||
const auto requestedAction =
|
|
||||||
ArgsToFrontendOptionsConverter::determineRequestedAction(Args);
|
|
||||||
if (!FrontendOptions::doesActionProduceOutput(requestedAction))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Optional<OutputFilesComputer> ofc =
|
Optional<OutputFilesComputer> ofc =
|
||||||
OutputFilesComputer::create(Args, Diags, InputsAndOutputs);
|
OutputFilesComputer::create(Args, Diags, InputsAndOutputs);
|
||||||
@@ -47,7 +43,7 @@ bool ArgsToFrontendOutputsConverter::convert(
|
|||||||
if (!mains)
|
if (!mains)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Optional<SupplementaryOutputPaths> supplementaries =
|
Optional<std::vector<SupplementaryOutputPaths>> supplementaries =
|
||||||
SupplementaryOutputPathsComputer(Args, Diags, InputsAndOutputs, *mains,
|
SupplementaryOutputPathsComputer(Args, Diags, InputsAndOutputs, *mains,
|
||||||
ModuleName)
|
ModuleName)
|
||||||
.computeOutputPaths();
|
.computeOutputPaths();
|
||||||
@@ -55,7 +51,10 @@ bool ArgsToFrontendOutputsConverter::convert(
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
mainOutputs = std::move(*mains);
|
mainOutputs = std::move(*mains);
|
||||||
supplementaryOutputs = std::move(*supplementaries);
|
assert(supplementaries->size() <= 1 &&
|
||||||
|
"Have not implemented multiple primaries yet");
|
||||||
|
if (!supplementaries->empty())
|
||||||
|
supplementaryOutputs = std::move(supplementaries->front());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,6 +165,13 @@ OutputFilesComputer::computeOutputFiles() const {
|
|||||||
Optional<std::string>
|
Optional<std::string>
|
||||||
OutputFilesComputer::computeOutputFile(StringRef outputArg,
|
OutputFilesComputer::computeOutputFile(StringRef outputArg,
|
||||||
const InputFile &input) const {
|
const InputFile &input) const {
|
||||||
|
// Return an empty string to signify no output.
|
||||||
|
// The frontend does not currently produce a diagnostic
|
||||||
|
// if a -o argument is present for such an action
|
||||||
|
// for instance swiftc -frontend -o foo -interpret foo.swift
|
||||||
|
if (!FrontendOptions::doesActionProduceOutput(RequestedAction))
|
||||||
|
return std::string();
|
||||||
|
|
||||||
if (!OutputDirectoryArgument.empty())
|
if (!OutputDirectoryArgument.empty())
|
||||||
return deriveOutputFileForDirectory(input);
|
return deriveOutputFileForDirectory(input);
|
||||||
|
|
||||||
@@ -228,16 +234,41 @@ SupplementaryOutputPathsComputer::SupplementaryOutputPathsComputer(
|
|||||||
RequestedAction(
|
RequestedAction(
|
||||||
ArgsToFrontendOptionsConverter::determineRequestedAction(Args)) {}
|
ArgsToFrontendOptionsConverter::determineRequestedAction(Args)) {}
|
||||||
|
|
||||||
Optional<SupplementaryOutputPaths>
|
Optional<std::vector<SupplementaryOutputPaths>>
|
||||||
SupplementaryOutputPathsComputer::computeOutputPaths() const {
|
SupplementaryOutputPathsComputer::computeOutputPaths() const {
|
||||||
Optional<std::vector<SupplementaryOutputPaths>> pathsFromUser =
|
Optional<std::vector<SupplementaryOutputPaths>> pathsFromUser =
|
||||||
getSupplementaryOutputPathsFromArguments();
|
getSupplementaryOutputPathsFromArguments();
|
||||||
if (!pathsFromUser)
|
if (!pathsFromUser)
|
||||||
return None;
|
return None;
|
||||||
|
|
||||||
return computeOutputPathsForOneInput(
|
if (InputsAndOutputs.hasPrimaryInputs())
|
||||||
OutputFiles[0], (*pathsFromUser)[0],
|
assert(OutputFiles.size() == pathsFromUser->size());
|
||||||
InputsAndOutputs.firstInputProducingOutput());
|
else if (InputsAndOutputs.isSingleThreadedWMO())
|
||||||
|
assert(OutputFiles.size() == pathsFromUser->size() &&
|
||||||
|
pathsFromUser->size() == 1);
|
||||||
|
else {
|
||||||
|
// Multi-threaded WMO is the exception
|
||||||
|
assert(OutputFiles.size() == InputsAndOutputs.inputCount() &&
|
||||||
|
pathsFromUser->size() == InputsAndOutputs.hasInputs()
|
||||||
|
? 1
|
||||||
|
: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SupplementaryOutputPaths> outputPaths;
|
||||||
|
unsigned i = 0;
|
||||||
|
bool hadError = false;
|
||||||
|
InputsAndOutputs.forEachInputProducingSupplementaryOutput(
|
||||||
|
[&](const InputFile &input) -> void {
|
||||||
|
if (auto suppPaths = computeOutputPathsForOneInput(
|
||||||
|
OutputFiles[i], (*pathsFromUser)[i], input))
|
||||||
|
outputPaths.push_back(*suppPaths);
|
||||||
|
else
|
||||||
|
hadError = true;
|
||||||
|
++i;
|
||||||
|
});
|
||||||
|
if (hadError)
|
||||||
|
return None;
|
||||||
|
return outputPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<std::vector<SupplementaryOutputPaths>>
|
Optional<std::vector<SupplementaryOutputPaths>>
|
||||||
@@ -302,7 +333,7 @@ SupplementaryOutputPathsComputer::getSupplementaryFilenamesFromArguments(
|
|||||||
return std::vector<std::string>(N, std::string());
|
return std::vector<std::string>(N, std::string());
|
||||||
|
|
||||||
Diags.diagnose(SourceLoc(), diag::error_wrong_number_of_arguments,
|
Diags.diagnose(SourceLoc(), diag::error_wrong_number_of_arguments,
|
||||||
Args.getLastArg(pathID)->getOption().getName(), N,
|
Args.getLastArg(pathID)->getOption().getPrefixedName(), N,
|
||||||
paths.size());
|
paths.size());
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -387,7 +418,6 @@ SupplementaryOutputPathsComputer::determineSupplementaryOutputFilename(
|
|||||||
options::ID emitOpt, std::string pathFromArguments, StringRef extension,
|
options::ID emitOpt, std::string pathFromArguments, StringRef extension,
|
||||||
StringRef mainOutputIfUsable,
|
StringRef mainOutputIfUsable,
|
||||||
StringRef defaultSupplementaryOutputPathExcludingExtension) const {
|
StringRef defaultSupplementaryOutputPathExcludingExtension) const {
|
||||||
using namespace options;
|
|
||||||
|
|
||||||
if (!pathFromArguments.empty())
|
if (!pathFromArguments.empty())
|
||||||
return pathFromArguments;
|
return pathFromArguments;
|
||||||
|
|||||||
@@ -289,9 +289,7 @@ void FrontendInputsAndOutputs::forEachInputProducingAMainOutputFile(
|
|||||||
void FrontendInputsAndOutputs::setMainAndSupplementaryOutputs(
|
void FrontendInputsAndOutputs::setMainAndSupplementaryOutputs(
|
||||||
ArrayRef<std::string> outputFiles,
|
ArrayRef<std::string> outputFiles,
|
||||||
SupplementaryOutputPaths supplementaryOutputs) {
|
SupplementaryOutputPaths supplementaryOutputs) {
|
||||||
if (outputFiles.empty())
|
if (hasPrimaryInputs()) {
|
||||||
;
|
|
||||||
else if (hasPrimaryInputs()) {
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (auto index : indices(AllInputs)) {
|
for (auto index : indices(AllInputs)) {
|
||||||
InputFile &f = AllInputs[index];
|
InputFile &f = AllInputs[index];
|
||||||
@@ -344,15 +342,14 @@ bool FrontendInputsAndOutputs::hasNamedOutputFile() const {
|
|||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
FrontendInputsAndOutputs::countOfFilesProducingSupplementaryOutput() const {
|
FrontendInputsAndOutputs::countOfFilesProducingSupplementaryOutput() const {
|
||||||
assertMustNotBeMoreThanOnePrimaryInput();
|
return hasPrimaryInputs() ? primaryInputCount() : hasInputs() ? 1 : 0;
|
||||||
return 1; // will be extended when batch mode is implemented
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrontendInputsAndOutputs::forEachInputProducingSupplementaryOutput(
|
void FrontendInputsAndOutputs::forEachInputProducingSupplementaryOutput(
|
||||||
llvm::function_ref<void(const InputFile &)> fn) const {
|
llvm::function_ref<void(const InputFile &)> fn) const {
|
||||||
if (hasPrimaryInputs())
|
if (hasPrimaryInputs())
|
||||||
forEachPrimaryInput(fn);
|
forEachPrimaryInput(fn);
|
||||||
else
|
else if (hasInputs())
|
||||||
fn(firstInput());
|
fn(firstInput());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
// RUN: not %swift -c -primary-file a.swift b.swift -emit-module-path one -emit-module-path two 2>&1 | %FileCheck %s -check-prefix=CHECK1
|
// RUN: not %swift -c -primary-file a.swift b.swift -emit-module-path one -emit-module-path two 2>&1 | %FileCheck %s -check-prefix=CHECK1
|
||||||
// CHECK1: <unknown>:0: error: wrong number of 'emit-module-path' arguments (expected 1, got 2)
|
// CHECK1: <unknown>:0: error: wrong number of '-emit-module-path' arguments (expected 1, got 2)
|
||||||
|
|||||||
Reference in New Issue
Block a user