Cleaner handling of cases where action produces no output or where there are no inputs.

This commit is contained in:
David Ungar
2018-02-07 13:50:29 -08:00
parent ba4f2a84b4
commit ef02d0bfc0
5 changed files with 62 additions and 24 deletions

View File

@@ -124,10 +124,24 @@ public:
const llvm::opt::ArgList &args, DiagnosticEngine &diags,
const FrontendInputsAndOutputs &inputsAndOutputs,
ArrayRef<std::string> outputFiles, StringRef moduleName);
Optional<SupplementaryOutputPaths> computeOutputPaths() const;
Optional<std::vector<SupplementaryOutputPaths>> computeOutputPaths() const;
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>>
getSupplementaryOutputPathsFromArguments() const;

View File

@@ -441,9 +441,6 @@ bool ArgsToFrontendOptionsConverter::
.convert(mainOutputs, supplementaryOutputs);
if (hadError)
return true;
assert(FrontendOptions::doesActionProduceOutput(Opts.RequestedAction) ||
mainOutputs.empty() &&
"Should be no main outputs if action does not produce them");
Opts.InputsAndOutputs.setMainAndSupplementaryOutputs(mainOutputs,
supplementaryOutputs);
return false;

View File

@@ -34,10 +34,6 @@ using namespace llvm::opt;
bool ArgsToFrontendOutputsConverter::convert(
std::vector<std::string> &mainOutputs,
SupplementaryOutputPaths &supplementaryOutputs) {
const auto requestedAction =
ArgsToFrontendOptionsConverter::determineRequestedAction(Args);
if (!FrontendOptions::doesActionProduceOutput(requestedAction))
return false;
Optional<OutputFilesComputer> ofc =
OutputFilesComputer::create(Args, Diags, InputsAndOutputs);
@@ -47,7 +43,7 @@ bool ArgsToFrontendOutputsConverter::convert(
if (!mains)
return true;
Optional<SupplementaryOutputPaths> supplementaries =
Optional<std::vector<SupplementaryOutputPaths>> supplementaries =
SupplementaryOutputPathsComputer(Args, Diags, InputsAndOutputs, *mains,
ModuleName)
.computeOutputPaths();
@@ -55,7 +51,10 @@ bool ArgsToFrontendOutputsConverter::convert(
return true;
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;
}
@@ -166,6 +165,13 @@ OutputFilesComputer::computeOutputFiles() const {
Optional<std::string>
OutputFilesComputer::computeOutputFile(StringRef outputArg,
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())
return deriveOutputFileForDirectory(input);
@@ -228,16 +234,41 @@ SupplementaryOutputPathsComputer::SupplementaryOutputPathsComputer(
RequestedAction(
ArgsToFrontendOptionsConverter::determineRequestedAction(Args)) {}
Optional<SupplementaryOutputPaths>
Optional<std::vector<SupplementaryOutputPaths>>
SupplementaryOutputPathsComputer::computeOutputPaths() const {
Optional<std::vector<SupplementaryOutputPaths>> pathsFromUser =
getSupplementaryOutputPathsFromArguments();
if (!pathsFromUser)
return None;
return computeOutputPathsForOneInput(
OutputFiles[0], (*pathsFromUser)[0],
InputsAndOutputs.firstInputProducingOutput());
if (InputsAndOutputs.hasPrimaryInputs())
assert(OutputFiles.size() == pathsFromUser->size());
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>>
@@ -302,7 +333,7 @@ SupplementaryOutputPathsComputer::getSupplementaryFilenamesFromArguments(
return std::vector<std::string>(N, std::string());
Diags.diagnose(SourceLoc(), diag::error_wrong_number_of_arguments,
Args.getLastArg(pathID)->getOption().getName(), N,
Args.getLastArg(pathID)->getOption().getPrefixedName(), N,
paths.size());
return None;
}
@@ -387,7 +418,6 @@ SupplementaryOutputPathsComputer::determineSupplementaryOutputFilename(
options::ID emitOpt, std::string pathFromArguments, StringRef extension,
StringRef mainOutputIfUsable,
StringRef defaultSupplementaryOutputPathExcludingExtension) const {
using namespace options;
if (!pathFromArguments.empty())
return pathFromArguments;

View File

@@ -289,9 +289,7 @@ void FrontendInputsAndOutputs::forEachInputProducingAMainOutputFile(
void FrontendInputsAndOutputs::setMainAndSupplementaryOutputs(
ArrayRef<std::string> outputFiles,
SupplementaryOutputPaths supplementaryOutputs) {
if (outputFiles.empty())
;
else if (hasPrimaryInputs()) {
if (hasPrimaryInputs()) {
unsigned i = 0;
for (auto index : indices(AllInputs)) {
InputFile &f = AllInputs[index];
@@ -344,15 +342,14 @@ bool FrontendInputsAndOutputs::hasNamedOutputFile() const {
unsigned
FrontendInputsAndOutputs::countOfFilesProducingSupplementaryOutput() const {
assertMustNotBeMoreThanOnePrimaryInput();
return 1; // will be extended when batch mode is implemented
return hasPrimaryInputs() ? primaryInputCount() : hasInputs() ? 1 : 0;
}
void FrontendInputsAndOutputs::forEachInputProducingSupplementaryOutput(
llvm::function_ref<void(const InputFile &)> fn) const {
if (hasPrimaryInputs())
forEachPrimaryInput(fn);
else
else if (hasInputs())
fn(firstInput());
}

View File

@@ -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
// 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)