mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #12920 from davidungar/Move-input-conversion
Move input conversion
This commit is contained in:
@@ -154,6 +154,9 @@ ERROR(error_primary_file_not_found,none,
|
||||
"primary file '%0' was not found in file list '%1'",
|
||||
(StringRef, StringRef))
|
||||
|
||||
ERROR(error_cannot_have_input_files_with_file_list,none,
|
||||
"cannot have input files with file list", ())
|
||||
|
||||
ERROR(repl_must_be_initialized,none,
|
||||
"variables currently must have an initial value when entered at the "
|
||||
"top level of the REPL", ())
|
||||
|
||||
@@ -359,7 +359,7 @@ class CompilerInstance {
|
||||
void createSILModule();
|
||||
void setPrimarySourceFile(SourceFile *SF);
|
||||
|
||||
bool setupForFileAt(unsigned i);
|
||||
bool setUpForFileAt(unsigned i);
|
||||
|
||||
public:
|
||||
SourceManager &getSourceMgr() { return SourceMgr; }
|
||||
|
||||
@@ -68,6 +68,8 @@ enum class InputFileKind {
|
||||
|
||||
/// Information about all the inputs to the frontend.
|
||||
class FrontendInputs {
|
||||
friend class ArgsToFrontendInputsConverter;
|
||||
|
||||
private:
|
||||
/// The names of input files to the frontend.
|
||||
std::vector<std::string> InputFilenames;
|
||||
@@ -75,26 +77,28 @@ private:
|
||||
/// Input buffers which may override the file contents of input files.
|
||||
std::vector<llvm::MemoryBuffer *> InputBuffers;
|
||||
|
||||
/// The input for which output should be generated. If not set, output will
|
||||
/// be generated for the whole module.
|
||||
Optional<SelectedInput> PrimaryInput;
|
||||
/// The inputs for which output should be generated. If empty, output will
|
||||
/// be generated for the whole module, in other words, whole-module mode.
|
||||
/// Even if every input file is mentioned here, it is not the same as
|
||||
/// whole-module mode.
|
||||
std::vector<SelectedInput> PrimaryInputs;
|
||||
|
||||
public:
|
||||
// Readers:
|
||||
|
||||
// Input filename readers
|
||||
ArrayRef<std::string> getInputFilenames() const { return InputFilenames; }
|
||||
bool hasInputFilenames() const { return !getInputFilenames().empty(); }
|
||||
bool haveInputFilenames() const { return !getInputFilenames().empty(); }
|
||||
unsigned inputFilenameCount() const { return getInputFilenames().size(); }
|
||||
|
||||
bool hasUniqueInputFilename() const { return inputFilenameCount() == 1; }
|
||||
bool haveUniqueInputFilename() const { return inputFilenameCount() == 1; }
|
||||
const std::string &getFilenameOfFirstInput() const {
|
||||
assert(hasInputFilenames());
|
||||
assert(haveInputFilenames());
|
||||
return getInputFilenames()[0];
|
||||
}
|
||||
|
||||
bool isReadingFromStdin() {
|
||||
return hasUniqueInputFilename() && getFilenameOfFirstInput() == "-";
|
||||
bool isReadingFromStdin() const {
|
||||
return haveUniqueInputFilename() && getFilenameOfFirstInput() == "-";
|
||||
}
|
||||
|
||||
// If we have exactly one input filename, and its extension is "bc" or "ll",
|
||||
@@ -110,21 +114,64 @@ public:
|
||||
|
||||
// Primary input readers
|
||||
|
||||
Optional<SelectedInput> getPrimaryInput() const { return PrimaryInput; }
|
||||
bool hasPrimaryInput() const { return getPrimaryInput().hasValue(); }
|
||||
|
||||
bool isWholeModule() { return !hasPrimaryInput(); }
|
||||
|
||||
bool isPrimaryInputAFileAt(unsigned i) {
|
||||
return hasPrimaryInput() && getPrimaryInput()->isFilename() &&
|
||||
getPrimaryInput()->Index == i;
|
||||
private:
|
||||
void assertMustNotBeMoreThanOnePrimaryInput() const {
|
||||
assert(PrimaryInputs.size() < 2 &&
|
||||
"have not implemented >1 primary input yet");
|
||||
}
|
||||
|
||||
public:
|
||||
ArrayRef<SelectedInput> getPrimaryInputs() const { return PrimaryInputs; }
|
||||
|
||||
unsigned primaryInputCount() const { return getPrimaryInputs().size(); }
|
||||
|
||||
// Primary count readers:
|
||||
|
||||
bool haveUniquePrimaryInput() const { return primaryInputCount() == 1; }
|
||||
|
||||
bool havePrimaryInputs() const { return primaryInputCount() > 0; }
|
||||
|
||||
bool isWholeModule() const { return !havePrimaryInputs(); }
|
||||
|
||||
// Count-dependend readers:
|
||||
|
||||
Optional<SelectedInput> getOptionalPrimaryInput() const {
|
||||
return havePrimaryInputs() ? Optional<SelectedInput>(getPrimaryInputs()[0])
|
||||
: Optional<SelectedInput>();
|
||||
}
|
||||
|
||||
SelectedInput getRequiredUniquePrimaryInput() const {
|
||||
assert(haveUniquePrimaryInput());
|
||||
return getPrimaryInputs()[0];
|
||||
}
|
||||
|
||||
Optional<SelectedInput> getOptionalUniquePrimaryInput() const {
|
||||
return haveUniquePrimaryInput()
|
||||
? Optional<SelectedInput>(getPrimaryInputs()[0])
|
||||
: Optional<SelectedInput>();
|
||||
}
|
||||
|
||||
bool haveAPrimaryInputFile() const {
|
||||
return hasPrimaryInput() && getPrimaryInput()->isFilename();
|
||||
return havePrimaryInputs() && getOptionalPrimaryInput()->isFilename();
|
||||
}
|
||||
|
||||
Optional<StringRef> getOptionalUniquePrimaryInputFilename() const {
|
||||
Optional<SelectedInput> primaryInput = getOptionalUniquePrimaryInput();
|
||||
return (primaryInput && primaryInput->isFilename())
|
||||
? Optional<StringRef>(getInputFilenames()[primaryInput->Index])
|
||||
: Optional<StringRef>();
|
||||
}
|
||||
|
||||
bool isPrimaryInputAFileAt(unsigned i) const {
|
||||
assertMustNotBeMoreThanOnePrimaryInput();
|
||||
if (Optional<SelectedInput> primaryInput = getOptionalPrimaryInput())
|
||||
return primaryInput->isFilename() && primaryInput->Index == i;
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<unsigned> primaryInputFileIndex() const {
|
||||
return haveAPrimaryInputFile()
|
||||
? Optional<unsigned>(getPrimaryInput()->Index)
|
||||
? Optional<unsigned>(getOptionalPrimaryInput()->Index)
|
||||
: None;
|
||||
}
|
||||
|
||||
@@ -135,9 +182,11 @@ public:
|
||||
return StringRef();
|
||||
}
|
||||
|
||||
public:
|
||||
// Multi-facet readers
|
||||
StringRef baseNameOfOutput(const llvm::opt::ArgList &Args,
|
||||
StringRef ModuleName) const;
|
||||
|
||||
bool shouldTreatAsSIL() const;
|
||||
|
||||
/// Return true for error
|
||||
@@ -158,8 +207,31 @@ public:
|
||||
|
||||
// Primary input writers
|
||||
|
||||
void setPrimaryInput(SelectedInput si) { PrimaryInput = si; }
|
||||
void clearPrimaryInput() { PrimaryInput = 0; }
|
||||
private:
|
||||
std::vector<SelectedInput> &getMutablePrimaryInputs() {
|
||||
assertMustNotBeMoreThanOnePrimaryInput();
|
||||
return PrimaryInputs;
|
||||
}
|
||||
|
||||
public:
|
||||
void clearPrimaryInputs() { getMutablePrimaryInputs().clear(); }
|
||||
|
||||
void setPrimaryInputToFirstFile() {
|
||||
clearPrimaryInputs();
|
||||
addPrimaryInput(SelectedInput(0, SelectedInput::InputKind::Filename));
|
||||
}
|
||||
|
||||
void addPrimaryInput(SelectedInput si) { PrimaryInputs.push_back(si); }
|
||||
|
||||
void setPrimaryInput(SelectedInput si) {
|
||||
clearPrimaryInputs();
|
||||
getMutablePrimaryInputs().push_back(si);
|
||||
}
|
||||
|
||||
void addPrimaryInputFilename(unsigned index) {
|
||||
addPrimaryInput(SelectedInput(index, SelectedInput::InputKind::Filename));
|
||||
}
|
||||
|
||||
void setPrimaryInputForInputFilename(const std::string &inputFilename) {
|
||||
setPrimaryInput(!inputFilename.empty() && inputFilename != "-"
|
||||
? SelectedInput(inputFilenameCount(),
|
||||
@@ -174,12 +246,6 @@ public:
|
||||
InputFilenames.clear();
|
||||
InputBuffers.clear();
|
||||
}
|
||||
|
||||
void setInputFilenamesAndPrimaryInput(DiagnosticEngine &Diags,
|
||||
llvm::opt::ArgList &Args);
|
||||
|
||||
void readInputFileList(DiagnosticEngine &diags, llvm::opt::ArgList &Args,
|
||||
const llvm::opt::Arg *filelistPath);
|
||||
};
|
||||
|
||||
/// Options for controlling the behavior of the frontend.
|
||||
@@ -214,7 +280,7 @@ public:
|
||||
}
|
||||
bool isOutputFileDirectory() const;
|
||||
bool isOutputFilePlainFile() const;
|
||||
bool hasNamedOutputFile() const {
|
||||
bool haveNamedOutputFile() const {
|
||||
return !OutputFilenames.empty() && !isOutputFilenameStdout();
|
||||
}
|
||||
void setOutputFileList(DiagnosticEngine &Diags,
|
||||
@@ -474,7 +540,7 @@ public:
|
||||
|
||||
bool isCompilingExactlyOneSwiftFile() const {
|
||||
return InputKind == InputFileKind::IFK_Swift &&
|
||||
Inputs.hasUniqueInputFilename();
|
||||
Inputs.haveUniqueInputFilename();
|
||||
}
|
||||
|
||||
void setModuleName(DiagnosticEngine &Diags, const llvm::opt::ArgList &Args);
|
||||
|
||||
@@ -16,17 +16,18 @@
|
||||
# include "AppleHostVersionDetection.h"
|
||||
#endif
|
||||
|
||||
#include "swift/Strings.h"
|
||||
#include "swift/AST/DiagnosticsFrontend.h"
|
||||
#include "swift/Basic/Platform.h"
|
||||
#include "swift/Option/Options.h"
|
||||
#include "swift/Option/SanitizerOptions.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;
|
||||
@@ -83,6 +84,147 @@ SourceFileKind CompilerInvocation::getSourceFileKind() const {
|
||||
llvm_unreachable("Unhandled InputFileKind in switch.");
|
||||
}
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// Implement argument semantics in a way that will make it easier to have
|
||||
/// >1 primary file (or even a primary file list) in the future without
|
||||
/// breaking anything today.
|
||||
///
|
||||
/// Semantics today:
|
||||
/// If input files are on command line, primary files on command line are also
|
||||
/// input files; they are not repeated without -primary-file. If input files are
|
||||
/// in a file list, the primary files on the command line are repeated in the
|
||||
/// file list. Thus, if there are any primary files, it is illegal to have both
|
||||
/// (non-primary) input files and a file list. Finally, the order of input files
|
||||
/// must match the order given on the command line or the file list.
|
||||
///
|
||||
/// Side note:
|
||||
/// since each input file will cause a lot of work for the compiler, this code
|
||||
/// is biased towards clarity and not optimized.
|
||||
/// In the near future, it will be possible to put primary files in the
|
||||
/// filelist, or to have a separate filelist for primaries. The organization
|
||||
/// here anticipates that evolution.
|
||||
|
||||
class ArgsToFrontendInputsConverter {
|
||||
DiagnosticEngine &Diags;
|
||||
const ArgList &Args;
|
||||
FrontendInputs &Inputs;
|
||||
|
||||
Arg const *const FilelistPathArg;
|
||||
|
||||
std::unique_ptr<llvm::MemoryBuffer> FilelistBuffer;
|
||||
|
||||
llvm::StringMap<unsigned> FileIndices;
|
||||
std::vector<StringRef> PrimaryFiles;
|
||||
|
||||
StringRef filelistPath() { return FilelistPathArg->getValue(); }
|
||||
|
||||
void addPrimary(StringRef file) { PrimaryFiles.push_back(file); }
|
||||
|
||||
void addInput(StringRef file) {
|
||||
FileIndices.insert({file, Inputs.inputFilenameCount()});
|
||||
Inputs.addInputFilename(file);
|
||||
}
|
||||
|
||||
bool arePrimariesOnCommandLineAlsoAppearingInFilelist() {
|
||||
return FilelistPathArg != nullptr;
|
||||
}
|
||||
|
||||
enum class Whence {
|
||||
PrimaryFromCommandLine,
|
||||
SecondaryFromCommandLine,
|
||||
SecondaryFromFileList
|
||||
};
|
||||
|
||||
void addFile(StringRef file, Whence whence) {
|
||||
switch (whence) {
|
||||
case Whence::PrimaryFromCommandLine:
|
||||
addPrimary(file);
|
||||
if (!arePrimariesOnCommandLineAlsoAppearingInFilelist())
|
||||
addInput(file);
|
||||
break;
|
||||
case Whence::SecondaryFromCommandLine:
|
||||
case Whence::SecondaryFromFileList:
|
||||
addInput(file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
ArgsToFrontendInputsConverter(DiagnosticEngine &Diags, const ArgList &Args,
|
||||
FrontendInputs &Inputs)
|
||||
: Diags(Diags), Args(Args), Inputs(Inputs),
|
||||
FilelistPathArg(Args.getLastArg(options::OPT_filelist)) {}
|
||||
|
||||
bool convert() {
|
||||
if (enforceFilelistExclusion())
|
||||
return true;
|
||||
getFilesFromCommandLine();
|
||||
if (getFilesFromFilelist())
|
||||
return true;
|
||||
return setPrimaryFiles();
|
||||
}
|
||||
|
||||
private:
|
||||
bool enforceFilelistExclusion() {
|
||||
if (Args.hasArg(options::OPT_INPUT) && FilelistPathArg != nullptr) {
|
||||
Diags.diagnose(SourceLoc(),
|
||||
diag::error_cannot_have_input_files_with_file_list);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void getFilesFromCommandLine() {
|
||||
for (const Arg *A :
|
||||
Args.filtered(options::OPT_INPUT, options::OPT_primary_file)) {
|
||||
StringRef file = A->getValue();
|
||||
if (A->getOption().matches(options::OPT_INPUT))
|
||||
addFile(file, Whence::SecondaryFromCommandLine);
|
||||
else if (A->getOption().matches(options::OPT_primary_file))
|
||||
addFile(file, Whence::PrimaryFromCommandLine);
|
||||
else
|
||||
llvm_unreachable("Unknown input-related argument!");
|
||||
}
|
||||
}
|
||||
|
||||
bool getFilesFromFilelist() {
|
||||
if (FilelistPathArg == nullptr)
|
||||
return false;
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> filelistBufferOrError =
|
||||
llvm::MemoryBuffer::getFile(filelistPath());
|
||||
if (!filelistBufferOrError) {
|
||||
Diags.diagnose(SourceLoc(), diag::cannot_open_file, filelistPath(),
|
||||
filelistBufferOrError.getError().message());
|
||||
return true;
|
||||
}
|
||||
// Keep buffer alive because code passes around StringRefs.
|
||||
FilelistBuffer = std::move(*filelistBufferOrError);
|
||||
for (auto file : llvm::make_range(llvm::line_iterator(*FilelistBuffer),
|
||||
llvm::line_iterator())) {
|
||||
addFile(file, Whence::SecondaryFromFileList);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool setPrimaryFiles() {
|
||||
for (StringRef primaryFile : PrimaryFiles) {
|
||||
const auto iterator = FileIndices.find(primaryFile);
|
||||
// Catch "swiftc -frontend -c -filelist foo -primary-file
|
||||
// some-file-not-in-foo".
|
||||
if (iterator == FileIndices.end()) {
|
||||
assert(FilelistPathArg != nullptr &&
|
||||
"Missing primary with no filelist");
|
||||
Diags.diagnose(SourceLoc(), diag::error_primary_file_not_found,
|
||||
primaryFile, filelistPath());
|
||||
return true;
|
||||
}
|
||||
Inputs.addPrimaryInputFilename(iterator->second);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} // namespace swift
|
||||
|
||||
// This is a separate function so that it shows up in stack traces.
|
||||
LLVM_ATTRIBUTE_NOINLINE
|
||||
static void debugFailWithAssertion() {
|
||||
@@ -224,7 +366,8 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
||||
}
|
||||
}
|
||||
|
||||
Opts.Inputs.setInputFilenamesAndPrimaryInput(Diags, Args);
|
||||
if (ArgsToFrontendInputsConverter(Diags, Args, Opts.Inputs).convert())
|
||||
return true;
|
||||
|
||||
Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
|
||||
|
||||
@@ -323,7 +466,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
||||
}
|
||||
|
||||
if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
|
||||
Opts.Inputs.hasPrimaryInput()) {
|
||||
Opts.Inputs.havePrimaryInputs()) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
|
||||
return true;
|
||||
}
|
||||
@@ -711,7 +854,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
|
||||
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) {
|
||||
Opts.ImplicitObjCHeaderPath = A->getValue();
|
||||
Opts.SerializeBridgingHeader |=
|
||||
!Opts.Inputs.getPrimaryInput() && !Opts.ModuleOutputPath.empty();
|
||||
!Opts.Inputs.havePrimaryInputs() && !Opts.ModuleOutputPath.empty();
|
||||
}
|
||||
|
||||
for (const Arg *A : Args.filtered(OPT_import_module)) {
|
||||
@@ -1464,11 +1607,10 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
|
||||
// in other classes.
|
||||
if (!SILOpts.SILOutputFileNameForDebugging.empty()) {
|
||||
Opts.MainInputFilename = SILOpts.SILOutputFileNameForDebugging;
|
||||
} else if (FrontendOpts.Inputs.getPrimaryInput() &&
|
||||
FrontendOpts.Inputs.getPrimaryInput()->isFilename()) {
|
||||
unsigned Index = FrontendOpts.Inputs.getPrimaryInput()->Index;
|
||||
Opts.MainInputFilename = FrontendOpts.Inputs.getInputFilenames()[Index];
|
||||
} else if (FrontendOpts.Inputs.hasUniqueInputFilename()) {
|
||||
} else if (const Optional<StringRef> filename =
|
||||
FrontendOpts.Inputs.getOptionalUniquePrimaryInputFilename()) {
|
||||
Opts.MainInputFilename = filename.getValue();
|
||||
} else if (FrontendOpts.Inputs.haveUniqueInputFilename()) {
|
||||
Opts.MainInputFilename = FrontendOpts.Inputs.getFilenameOfFirstInput();
|
||||
}
|
||||
Opts.OutputFilenames = FrontendOpts.OutputFilenames;
|
||||
|
||||
@@ -157,7 +157,7 @@ bool CompilerInstance::setup(const CompilerInvocation &Invok) {
|
||||
Invocation.getLangOptions().EnableAccessControl = false;
|
||||
|
||||
const Optional<SelectedInput> &PrimaryInput =
|
||||
Invocation.getFrontendOptions().Inputs.getPrimaryInput();
|
||||
Invocation.getFrontendOptions().Inputs.getOptionalPrimaryInput();
|
||||
|
||||
// Add the memory buffers first, these will be associated with a filename
|
||||
// and they can replace the contents of an input filename.
|
||||
@@ -187,7 +187,7 @@ bool CompilerInstance::setup(const CompilerInvocation &Invok) {
|
||||
for (unsigned i = 0,
|
||||
e = Invocation.getFrontendOptions().Inputs.inputFilenameCount();
|
||||
i != e; ++i) {
|
||||
bool hasError = setupForFileAt(i);
|
||||
bool hasError = setUpForFileAt(i);
|
||||
if (hasError) {
|
||||
return true;
|
||||
}
|
||||
@@ -726,7 +726,7 @@ void CompilerInstance::freeContextAndSIL() {
|
||||
PrimarySourceFile = nullptr;
|
||||
}
|
||||
|
||||
bool CompilerInstance::setupForFileAt(unsigned i) {
|
||||
bool CompilerInstance::setUpForFileAt(unsigned i) {
|
||||
bool MainMode = (Invocation.getInputKind() == InputFileKind::IFK_Swift);
|
||||
bool SILMode = (Invocation.getInputKind() == InputFileKind::IFK_SIL);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ using namespace swift;
|
||||
using namespace llvm::opt;
|
||||
|
||||
bool FrontendInputs::shouldTreatAsLLVM() const {
|
||||
if (hasUniqueInputFilename()) {
|
||||
if (haveUniqueInputFilename()) {
|
||||
StringRef Input(getFilenameOfFirstInput());
|
||||
return llvm::sys::path::extension(Input).endswith(LLVM_BC_EXTENSION) ||
|
||||
llvm::sys::path::extension(Input).endswith(LLVM_IR_EXTENSION);
|
||||
@@ -43,24 +43,25 @@ StringRef FrontendInputs::baseNameOfOutput(const llvm::opt::ArgList &Args,
|
||||
return llvm::sys::path::stem(pifn);
|
||||
}
|
||||
bool UserSpecifiedModuleName = Args.getLastArg(options::OPT_module_name);
|
||||
if (!UserSpecifiedModuleName && hasUniqueInputFilename()) {
|
||||
if (!UserSpecifiedModuleName && haveUniqueInputFilename()) {
|
||||
return llvm::sys::path::stem(getFilenameOfFirstInput());
|
||||
}
|
||||
return ModuleName;
|
||||
}
|
||||
|
||||
bool FrontendInputs::shouldTreatAsSIL() const {
|
||||
if (hasUniqueInputFilename()) {
|
||||
if (haveUniqueInputFilename()) {
|
||||
// If we have exactly one input filename, and its extension is "sil",
|
||||
// treat the input as SIL.
|
||||
StringRef Input(getFilenameOfFirstInput());
|
||||
return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
|
||||
}
|
||||
StringRef Input = primaryInputFilenameIfAny();
|
||||
if (!Input.empty()) {
|
||||
// If we have a primary input and it's a filename with extension "sil",
|
||||
// If we have one primary input and it's a filename with extension "sil",
|
||||
// treat the input as SIL.
|
||||
return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
|
||||
if (const Optional<StringRef> filename =
|
||||
getOptionalUniquePrimaryInputFilename()) {
|
||||
return llvm::sys::path::extension(filename.getValue())
|
||||
.endswith(SIL_EXTENSION);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -69,15 +70,15 @@ bool FrontendInputs::verifyInputs(DiagnosticEngine &Diags, bool TreatAsSIL,
|
||||
bool isREPLRequested,
|
||||
bool isNoneRequested) const {
|
||||
if (isREPLRequested) {
|
||||
if (hasInputFilenames()) {
|
||||
if (haveInputFilenames()) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
|
||||
return true;
|
||||
}
|
||||
} else if (TreatAsSIL && hasPrimaryInput()) {
|
||||
} else if (TreatAsSIL && havePrimaryInputs()) {
|
||||
// If we have the SIL as our primary input, we can waive the one file
|
||||
// requirement as long as all the other inputs are SIBs.
|
||||
for (unsigned i = 0, e = inputFilenameCount(); i != e; ++i) {
|
||||
if (i == getPrimaryInput()->Index)
|
||||
if (i == getOptionalUniquePrimaryInput()->Index)
|
||||
continue;
|
||||
|
||||
StringRef File(getInputFilenames()[i]);
|
||||
@@ -88,12 +89,12 @@ bool FrontendInputs::verifyInputs(DiagnosticEngine &Diags, bool TreatAsSIL,
|
||||
}
|
||||
}
|
||||
} else if (TreatAsSIL) {
|
||||
if (!hasUniqueInputFilename()) {
|
||||
if (!haveUniqueInputFilename()) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
|
||||
return true;
|
||||
}
|
||||
} else if (!isNoneRequested) {
|
||||
if (!hasInputFilenames()) {
|
||||
if (!haveInputFilenames()) {
|
||||
Diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
|
||||
return true;
|
||||
}
|
||||
@@ -108,66 +109,6 @@ void FrontendInputs::transformInputFilenames(
|
||||
}
|
||||
}
|
||||
|
||||
void FrontendInputs::setInputFilenamesAndPrimaryInput(
|
||||
DiagnosticEngine &Diags, llvm::opt::ArgList &Args) {
|
||||
if (const Arg *filelistPath = Args.getLastArg(options::OPT_filelist)) {
|
||||
readInputFileList(Diags, Args, filelistPath);
|
||||
return;
|
||||
}
|
||||
for (const Arg *A :
|
||||
Args.filtered(options::OPT_INPUT, options::OPT_primary_file)) {
|
||||
if (A->getOption().matches(options::OPT_INPUT)) {
|
||||
addInputFilename(A->getValue());
|
||||
} else if (A->getOption().matches(options::OPT_primary_file)) {
|
||||
setPrimaryInput(SelectedInput(inputFilenameCount()));
|
||||
addInputFilename(A->getValue());
|
||||
} else {
|
||||
llvm_unreachable("Unknown input-related argument!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to read an input file list file.
|
||||
///
|
||||
/// Returns false on error.
|
||||
void FrontendInputs::readInputFileList(DiagnosticEngine &diags,
|
||||
llvm::opt::ArgList &Args,
|
||||
const llvm::opt::Arg *filelistPath) {
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
|
||||
llvm::MemoryBuffer::getFile(filelistPath->getValue());
|
||||
if (!buffer) {
|
||||
diags.diagnose(SourceLoc(), diag::cannot_open_file,
|
||||
filelistPath->getValue(), buffer.getError().message());
|
||||
return;
|
||||
}
|
||||
|
||||
const Arg *primaryFileArg = Args.getLastArg(options::OPT_primary_file);
|
||||
unsigned primaryFileIndex = 0;
|
||||
|
||||
bool foundPrimaryFile = false;
|
||||
|
||||
for (StringRef line : make_range(llvm::line_iterator(*buffer.get()), {})) {
|
||||
addInputFilename(line);
|
||||
|
||||
if (foundPrimaryFile || primaryFileArg == nullptr)
|
||||
continue;
|
||||
if (line == primaryFileArg->getValue())
|
||||
foundPrimaryFile = true;
|
||||
else
|
||||
++primaryFileIndex;
|
||||
}
|
||||
|
||||
if (primaryFileArg && !foundPrimaryFile) {
|
||||
diags.diagnose(SourceLoc(), diag::error_primary_file_not_found,
|
||||
primaryFileArg->getValue(), filelistPath->getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
if (primaryFileArg)
|
||||
setPrimaryInput(SelectedInput(primaryFileIndex));
|
||||
assert(!Args.hasArg(options::OPT_INPUT) && "mixing -filelist with inputs");
|
||||
}
|
||||
|
||||
bool FrontendOptions::actionHasOutput() const {
|
||||
switch (RequestedAction) {
|
||||
case ActionType::NoneAction:
|
||||
@@ -284,7 +225,7 @@ void FrontendOptions::setModuleName(DiagnosticEngine &Diags,
|
||||
}
|
||||
|
||||
StringRef FrontendOptions::originalPath() const {
|
||||
if (hasNamedOutputFile())
|
||||
if (haveNamedOutputFile())
|
||||
// Put the serialized diagnostics file next to the output file.
|
||||
return getSingleOutputFilename();
|
||||
|
||||
@@ -304,7 +245,7 @@ StringRef FrontendOptions::determineFallbackModuleName() const {
|
||||
return "REPL";
|
||||
}
|
||||
// In order to pass Driver/options.swift test must leave ModuleName empty
|
||||
if (!Inputs.hasInputFilenames()) {
|
||||
if (!Inputs.haveInputFilenames()) {
|
||||
return StringRef();
|
||||
}
|
||||
StringRef OutputFilename = getSingleOutputFilename();
|
||||
@@ -341,11 +282,11 @@ void FrontendOptions::setOutputFileList(swift::DiagnosticEngine &Diags,
|
||||
}
|
||||
|
||||
bool FrontendOptions::isOutputFileDirectory() const {
|
||||
return hasNamedOutputFile() &&
|
||||
return haveNamedOutputFile() &&
|
||||
llvm::sys::fs::is_directory(getSingleOutputFilename());
|
||||
}
|
||||
|
||||
bool FrontendOptions::isOutputFilePlainFile() const {
|
||||
return hasNamedOutputFile() &&
|
||||
return haveNamedOutputFile() &&
|
||||
!llvm::sys::fs::is_directory(getSingleOutputFilename());
|
||||
}
|
||||
|
||||
@@ -542,7 +542,7 @@ static bool performCompile(CompilerInstance &Instance,
|
||||
auto &LLVMContext = getGlobalLLVMContext();
|
||||
|
||||
// Load in bitcode file.
|
||||
assert(Invocation.getFrontendOptions().Inputs.hasUniqueInputFilename() &&
|
||||
assert(Invocation.getFrontendOptions().Inputs.haveUniqueInputFilename() &&
|
||||
"We expect a single input for bitcode input!");
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
|
||||
llvm::MemoryBuffer::getFileOrSTDIN(
|
||||
@@ -780,7 +780,7 @@ static bool performCompile(CompilerInstance &Instance,
|
||||
if (opts.Inputs.haveAPrimaryInputFile()) {
|
||||
FileUnit *PrimaryFile = PrimarySourceFile;
|
||||
if (!PrimaryFile) {
|
||||
auto Index = opts.Inputs.getPrimaryInput().getValue().Index;
|
||||
auto Index = opts.Inputs.getRequiredUniquePrimaryInput().Index;
|
||||
PrimaryFile = Instance.getMainModule()->getFiles()[Index];
|
||||
}
|
||||
astGuaranteedToCorrespondToSIL = !fileIsSIB(PrimaryFile);
|
||||
|
||||
@@ -447,8 +447,8 @@ const MigratorOptions &Migrator::getMigratorOptions() const {
|
||||
}
|
||||
|
||||
const StringRef Migrator::getInputFilename() const {
|
||||
auto PrimaryInput =
|
||||
StartInvocation.getFrontendOptions().Inputs.getPrimaryInput().getValue();
|
||||
auto PrimaryInput = StartInvocation.getFrontendOptions()
|
||||
.Inputs.getRequiredUniquePrimaryInput();
|
||||
return StartInvocation.getFrontendOptions()
|
||||
.Inputs.getInputFilenames()[PrimaryInput.Index];
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@ struct InvocationOptions {
|
||||
// Assert invocation with a primary file. We want to avoid full typechecking
|
||||
// for all files.
|
||||
assert(!this->PrimaryFile.empty());
|
||||
assert(this->Invok.getFrontendOptions().Inputs.hasPrimaryInput());
|
||||
assert(this->Invok.getFrontendOptions().Inputs.haveUniquePrimaryInput() &&
|
||||
"Must have exactly one primary input for code completion, etc.");
|
||||
}
|
||||
|
||||
void applyTo(CompilerInvocation &CompInvok) const;
|
||||
@@ -354,7 +355,7 @@ static void setModuleName(CompilerInvocation &Invocation) {
|
||||
|
||||
StringRef Filename = Invocation.getOutputFilename();
|
||||
if (Filename.empty()) {
|
||||
if (!Invocation.getFrontendOptions().Inputs.hasInputFilenames()) {
|
||||
if (!Invocation.getFrontendOptions().Inputs.haveInputFilenames()) {
|
||||
Invocation.setModuleName("__main__");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ static bool swiftCodeCompleteImpl(SwiftLangSupport &Lang,
|
||||
if (Failed) {
|
||||
return false;
|
||||
}
|
||||
if (!Invocation.getFrontendOptions().Inputs.hasInputFilenames()) {
|
||||
if (!Invocation.getFrontendOptions().Inputs.haveInputFilenames()) {
|
||||
Error = "no input filenames specified";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ void SwiftLangSupport::indexSource(StringRef InputFile,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Invocation.getFrontendOptions().Inputs.hasInputFilenames()) {
|
||||
if (!Invocation.getFrontendOptions().Inputs.haveInputFilenames()) {
|
||||
IdxConsumer.failed("no input filenames specified");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ private:
|
||||
std::vector<std::string> InputFilenames;
|
||||
|
||||
public:
|
||||
bool hasUniqueInputFilename() const { return InputFilenames.size() == 1; }
|
||||
bool haveUniqueInputFilename() const { return InputFilenames.size() == 1; }
|
||||
const std::string &getFilenameOfFirstInput() const {
|
||||
return InputFilenames[0];
|
||||
}
|
||||
@@ -131,7 +131,7 @@ int modulewrap_main(ArrayRef<const char *> Args, const char *Argv0,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!Invocation.hasUniqueInputFilename()) {
|
||||
if (!Invocation.haveUniqueInputFilename()) {
|
||||
Instance.getDiags().diagnose(SourceLoc(),
|
||||
diag::error_mode_requires_one_input_file);
|
||||
return 1;
|
||||
|
||||
@@ -1917,7 +1917,7 @@ static int doPrintSwiftFileInterface(const CompilerInvocation &InitInvok,
|
||||
bool AnnotatePrint) {
|
||||
CompilerInvocation Invocation(InitInvok);
|
||||
Invocation.addInputFilename(SourceFilename);
|
||||
Invocation.getFrontendOptions().Inputs.clearPrimaryInput();
|
||||
Invocation.getFrontendOptions().Inputs.setPrimaryInputToFirstFile();
|
||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||
CompilerInstance CI;
|
||||
// Display diagnostics to stderr.
|
||||
@@ -1948,7 +1948,7 @@ static int doPrintDecls(const CompilerInvocation &InitInvok,
|
||||
bool AnnotatePrint) {
|
||||
CompilerInvocation Invocation(InitInvok);
|
||||
Invocation.addInputFilename(SourceFilename);
|
||||
Invocation.getFrontendOptions().Inputs.clearPrimaryInput();
|
||||
Invocation.getFrontendOptions().Inputs.setPrimaryInputToFirstFile();
|
||||
Invocation.getLangOptions().AttachCommentsToDecls = true;
|
||||
CompilerInstance CI;
|
||||
// Display diagnostics to stderr.
|
||||
|
||||
Reference in New Issue
Block a user