Skip to content

Commit 5dbc33f

Browse files
committed
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
1 parent 7d881f8 commit 5dbc33f

File tree

5 files changed

+49
-8
lines changed

5 files changed

+49
-8
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ ERROR(error_no_frontend_args, frontend, none,
4646
ERROR(error_no_such_file_or_directory,frontend,none,
4747
"no such file or directory: '%0'", (StringRef))
4848

49+
ERROR(error_unsupported_target_os, frontend, none,
50+
"unsupported target OS: '%0'", (StringRef))
51+
52+
ERROR(error_unsupported_target_arch, frontend, none,
53+
"unsupported target architecture: '%0'", (StringRef))
54+
4955
ERROR(cannot_open_file,frontend,none,
5056
"cannot open file '%0' (%1)", (StringRef, StringRef))
5157
ERROR(cannot_open_serialized_file,frontend,none,

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ namespace swift {
146146

147147
/// Sets the target we are building for and updates configuration options
148148
/// to match.
149-
void setTarget(llvm::Triple triple);
149+
///
150+
/// \returns A pair - the first element is true if the OS was invalid.
151+
/// The second element is true if the Arch was invalid.
152+
std::pair<bool, bool> setTarget(llvm::Triple triple);
150153

151154
/// Returns the minimum platform version to which code will be deployed.
152155
///

lib/Basic/LangOptions.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ bool LangOptions::hasBuildConfigOption(StringRef Name) const {
3636
!= BuildConfigOptions.end();
3737
}
3838

39-
void LangOptions::setTarget(llvm::Triple triple) {
39+
std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
4040
clearAllTargetConfigOptions();
4141

4242
if (triple.getOS() == llvm::Triple::Darwin &&
@@ -57,6 +57,8 @@ void LangOptions::setTarget(llvm::Triple triple) {
5757
}
5858
Target = std::move(triple);
5959

60+
bool UnsupportedOS = false;
61+
6062
// Set the "os" target configuration.
6163
if (Target.isMacOSX())
6264
addTargetConfigOption("os", "OSX");
@@ -70,8 +72,11 @@ void LangOptions::setTarget(llvm::Triple triple) {
7072
addTargetConfigOption("os", "iOS");
7173
else if (triple.isOSLinux())
7274
addTargetConfigOption("os", "Linux");
73-
else
74-
llvm_unreachable("Unsupported target OS");
75+
else {
76+
UnsupportedOS = true;
77+
}
78+
79+
bool UnsupportedArch = false;
7580

7681
// Set the "arch" target configuration.
7782
switch (Target.getArch()) {
@@ -88,12 +93,17 @@ void LangOptions::setTarget(llvm::Triple triple) {
8893
addTargetConfigOption("arch", "x86_64");
8994
break;
9095
default:
91-
llvm_unreachable("Unsupported target architecture");
96+
UnsupportedArch = true;
9297
}
9398

99+
if (UnsupportedOS || UnsupportedArch)
100+
return { UnsupportedOS, UnsupportedArch };
101+
94102
// Set the "runtime" target configuration.
95103
if (EnableObjCInterop)
96104
addTargetConfigOption("_runtime", "_ObjC");
97105
else
98106
addTargetConfigOption("_runtime", "_Native");
107+
108+
return { false, false };
99109
}

lib/Frontend/CompilerInvocation.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,11 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
720720
Opts.EnableAppExtensionRestrictions |= Args.hasArg(OPT_enable_app_extension);
721721

722722
llvm::Triple Target = Opts.Target;
723-
if (const Arg *A = Args.getLastArg(OPT_target))
723+
StringRef TargetArg;
724+
if (const Arg *A = Args.getLastArg(OPT_target)) {
724725
Target = llvm::Triple(A->getValue());
726+
TargetArg = A->getValue();
727+
}
725728

726729
Opts.EnableObjCInterop = Target.isOSDarwin();
727730
if (auto A = Args.getLastArg(OPT_enable_objc_interop,
@@ -732,9 +735,23 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
732735

733736
// Must be processed after any other language options that could affect
734737
// target configuration options.
735-
Opts.setTarget(Target);
738+
bool UnsupportedOS, UnsupportedArch;
739+
std::tie(UnsupportedOS, UnsupportedArch) = Opts.setTarget(Target);
736740

737-
return false;
741+
SmallVector<StringRef, 3> TargetComponents;
742+
TargetArg.split(TargetComponents, "-");
743+
744+
if (UnsupportedArch) {
745+
auto TargetArgArch = TargetComponents.size() ? TargetComponents[0] : "";
746+
Diags.diagnose(SourceLoc(), diag::error_unsupported_target_arch, TargetArgArch);
747+
}
748+
749+
if (UnsupportedOS) {
750+
auto TargetArgOS = TargetComponents.size() > 2 ? TargetComponents.back() : "";
751+
Diags.diagnose(SourceLoc(), diag::error_unsupported_target_os, TargetArgOS);
752+
}
753+
754+
return UnsupportedOS || UnsupportedArch;
738755
}
739756

740757
static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args,

test/Frontend/invalid-target.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: not %swift %s -target 6502-apple-ios9.0 2>&1 | FileCheck %s -check-prefix=CHECKARCH
2+
// RUN: not %swift %s -target x86_64-apple-eyeOS 2>&1 | FileCheck %s -check-prefix=CHECKOS
3+
4+
// CHECKARCH: <unknown>:0: error: unsupported target architecture: '6502'
5+
// CHECKOS: <unknown>:0: error: unsupported target OS: 'eyeOS'

0 commit comments

Comments
 (0)