Don't crash the frontend if a bad target is given

Provide a chance to emit a diagnostic instead.

rdar://problem/20931800

Swift SVN r28940
This commit is contained in:
David Farler
2015-05-23 00:58:05 +00:00
parent 7d881f8440
commit 5dbc33f8ac
5 changed files with 49 additions and 8 deletions

View File

@@ -46,6 +46,12 @@ ERROR(error_no_frontend_args, frontend, none,
ERROR(error_no_such_file_or_directory,frontend,none, ERROR(error_no_such_file_or_directory,frontend,none,
"no such file or directory: '%0'", (StringRef)) "no such file or directory: '%0'", (StringRef))
ERROR(error_unsupported_target_os, frontend, none,
"unsupported target OS: '%0'", (StringRef))
ERROR(error_unsupported_target_arch, frontend, none,
"unsupported target architecture: '%0'", (StringRef))
ERROR(cannot_open_file,frontend,none, ERROR(cannot_open_file,frontend,none,
"cannot open file '%0' (%1)", (StringRef, StringRef)) "cannot open file '%0' (%1)", (StringRef, StringRef))
ERROR(cannot_open_serialized_file,frontend,none, ERROR(cannot_open_serialized_file,frontend,none,

View File

@@ -146,7 +146,10 @@ namespace swift {
/// Sets the target we are building for and updates configuration options /// Sets the target we are building for and updates configuration options
/// to match. /// to match.
void setTarget(llvm::Triple triple); ///
/// \returns A pair - the first element is true if the OS was invalid.
/// The second element is true if the Arch was invalid.
std::pair<bool, bool> setTarget(llvm::Triple triple);
/// Returns the minimum platform version to which code will be deployed. /// Returns the minimum platform version to which code will be deployed.
/// ///

View File

@@ -36,7 +36,7 @@ bool LangOptions::hasBuildConfigOption(StringRef Name) const {
!= BuildConfigOptions.end(); != BuildConfigOptions.end();
} }
void LangOptions::setTarget(llvm::Triple triple) { std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
clearAllTargetConfigOptions(); clearAllTargetConfigOptions();
if (triple.getOS() == llvm::Triple::Darwin && if (triple.getOS() == llvm::Triple::Darwin &&
@@ -57,6 +57,8 @@ void LangOptions::setTarget(llvm::Triple triple) {
} }
Target = std::move(triple); Target = std::move(triple);
bool UnsupportedOS = false;
// Set the "os" target configuration. // Set the "os" target configuration.
if (Target.isMacOSX()) if (Target.isMacOSX())
addTargetConfigOption("os", "OSX"); addTargetConfigOption("os", "OSX");
@@ -70,8 +72,11 @@ void LangOptions::setTarget(llvm::Triple triple) {
addTargetConfigOption("os", "iOS"); addTargetConfigOption("os", "iOS");
else if (triple.isOSLinux()) else if (triple.isOSLinux())
addTargetConfigOption("os", "Linux"); addTargetConfigOption("os", "Linux");
else else {
llvm_unreachable("Unsupported target OS"); UnsupportedOS = true;
}
bool UnsupportedArch = false;
// Set the "arch" target configuration. // Set the "arch" target configuration.
switch (Target.getArch()) { switch (Target.getArch()) {
@@ -88,12 +93,17 @@ void LangOptions::setTarget(llvm::Triple triple) {
addTargetConfigOption("arch", "x86_64"); addTargetConfigOption("arch", "x86_64");
break; break;
default: default:
llvm_unreachable("Unsupported target architecture"); UnsupportedArch = true;
} }
if (UnsupportedOS || UnsupportedArch)
return { UnsupportedOS, UnsupportedArch };
// Set the "runtime" target configuration. // Set the "runtime" target configuration.
if (EnableObjCInterop) if (EnableObjCInterop)
addTargetConfigOption("_runtime", "_ObjC"); addTargetConfigOption("_runtime", "_ObjC");
else else
addTargetConfigOption("_runtime", "_Native"); addTargetConfigOption("_runtime", "_Native");
return { false, false };
} }

View File

@@ -720,8 +720,11 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.EnableAppExtensionRestrictions |= Args.hasArg(OPT_enable_app_extension); Opts.EnableAppExtensionRestrictions |= Args.hasArg(OPT_enable_app_extension);
llvm::Triple Target = Opts.Target; llvm::Triple Target = Opts.Target;
if (const Arg *A = Args.getLastArg(OPT_target)) StringRef TargetArg;
if (const Arg *A = Args.getLastArg(OPT_target)) {
Target = llvm::Triple(A->getValue()); Target = llvm::Triple(A->getValue());
TargetArg = A->getValue();
}
Opts.EnableObjCInterop = Target.isOSDarwin(); Opts.EnableObjCInterop = Target.isOSDarwin();
if (auto A = Args.getLastArg(OPT_enable_objc_interop, if (auto A = Args.getLastArg(OPT_enable_objc_interop,
@@ -732,9 +735,23 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
// Must be processed after any other language options that could affect // Must be processed after any other language options that could affect
// target configuration options. // target configuration options.
Opts.setTarget(Target); bool UnsupportedOS, UnsupportedArch;
std::tie(UnsupportedOS, UnsupportedArch) = Opts.setTarget(Target);
return false; SmallVector<StringRef, 3> TargetComponents;
TargetArg.split(TargetComponents, "-");
if (UnsupportedArch) {
auto TargetArgArch = TargetComponents.size() ? TargetComponents[0] : "";
Diags.diagnose(SourceLoc(), diag::error_unsupported_target_arch, TargetArgArch);
}
if (UnsupportedOS) {
auto TargetArgOS = TargetComponents.size() > 2 ? TargetComponents.back() : "";
Diags.diagnose(SourceLoc(), diag::error_unsupported_target_os, TargetArgOS);
}
return UnsupportedOS || UnsupportedArch;
} }
static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args, static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args,

View File

@@ -0,0 +1,5 @@
// RUN: not %swift %s -target 6502-apple-ios9.0 2>&1 | FileCheck %s -check-prefix=CHECKARCH
// RUN: not %swift %s -target x86_64-apple-eyeOS 2>&1 | FileCheck %s -check-prefix=CHECKOS
// CHECKARCH: <unknown>:0: error: unsupported target architecture: '6502'
// CHECKOS: <unknown>:0: error: unsupported target OS: 'eyeOS'