Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -198,6 +198,8 @@ "precompiled header '%0' was ignored because '%1' is not first '-include'">; def warn_missing_sysroot : Warning<"no such sysroot directory: '%0'">, InGroup>; +def warn_incompatible_sysroot : Warning<"using sysroot for '%0' but targeting '%1'">, + InGroup>; def warn_debug_compression_unavailable : Warning<"cannot compress debug sections (zlib not installed)">, InGroup>; def warn_drv_enabling_rtti_with_exceptions : Warning< Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -496,6 +496,7 @@ return TargetVersion < VersionTuple(V0, V1, V2); } + StringRef getPlatformFamily() const; StringRef getOSLibraryNameSuffix() const; public: Index: lib/Driver/ToolChains.cpp =================================================================== --- lib/Driver/ToolChains.cpp +++ lib/Driver/ToolChains.cpp @@ -329,6 +329,23 @@ } } +StringRef Darwin::getPlatformFamily() const { + switch (TargetPlatform) { + case DarwinPlatformKind::MacOS: + return "MacOSX"; + case DarwinPlatformKind::IPhoneOS: + case DarwinPlatformKind::IPhoneOSSimulator: + return "iPhone"; + case DarwinPlatformKind::TvOS: + case DarwinPlatformKind::TvOSSimulator: + return "AppleTV"; + case DarwinPlatformKind::WatchOS: + case DarwinPlatformKind::WatchOSSimulator: + return "Watch"; + } + llvm_unreachable("Unsupported platform"); +} + StringRef Darwin::getOSLibraryNameSuffix() const { switch(TargetPlatform) { case DarwinPlatformKind::MacOS: @@ -541,27 +558,31 @@ if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { StringRef isysroot = A->getValue(); // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk - size_t BeginSDK = isysroot.rfind("SDKs/"); - size_t EndSDK = isysroot.rfind(".sdk"); - if (BeginSDK != StringRef::npos && EndSDK != StringRef::npos) { - StringRef SDK = isysroot.slice(BeginSDK + 5, EndSDK); - // Slice the version number out. - // Version number is between the first and the last number. - size_t StartVer = SDK.find_first_of("0123456789"); - size_t EndVer = SDK.find_last_of("0123456789"); - if (StartVer != StringRef::npos && EndVer > StartVer) { - StringRef Version = SDK.slice(StartVer, EndVer + 1); - if (SDK.startswith("iPhoneOS") || - SDK.startswith("iPhoneSimulator")) - iOSTarget = Version; - else if (SDK.startswith("MacOSX")) - OSXTarget = Version; - else if (SDK.startswith("WatchOS") || - SDK.startswith("WatchSimulator")) - WatchOSTarget = Version; - else if (SDK.startswith("AppleTVOS") || - SDK.startswith("AppleTVSimulator")) - TvOSTarget = Version; + llvm::sys::path::const_iterator SDKDir; + auto BeginSDK = llvm::sys::path::begin(isysroot); + auto EndSDK = llvm::sys::path::end(isysroot); + for (auto IT = BeginSDK; IT != EndSDK; ++IT) { + StringRef SDK = *IT; + if (SDK.endswith(".sdk")) { + // Slice the version number out. + // Version number is between the first and the last number. + size_t StartVer = SDK.find_first_of("0123456789"); + size_t EndVer = SDK.find_last_of("0123456789"); + if (StartVer != StringRef::npos && EndVer > StartVer) { + StringRef Version = SDK.slice(StartVer, EndVer + 1); + if (SDK.startswith("iPhoneOS") || + SDK.startswith("iPhoneSimulator")) + iOSTarget = Version; + else if (SDK.startswith("MacOSX")) + OSXTarget = Version; + else if (SDK.startswith("WatchOS") || + SDK.startswith("WatchSimulator")) + WatchOSTarget = Version; + else if (SDK.startswith("AppleTVOS") || + SDK.startswith("AppleTVSimulator")) + TvOSTarget = Version; + } + break; } } } @@ -697,6 +718,19 @@ Platform = WatchOSSimulator; setTarget(Platform, Major, Minor, Micro); + + if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) { + StringRef isysroot = A->getValue(); + // Assume SDK has path: SOME_PATH/SDKs/PlatformXX.YY.sdk + size_t BeginSDK = isysroot.rfind("SDKs/"); + size_t EndSDK = isysroot.rfind(".sdk"); + if (BeginSDK != StringRef::npos && EndSDK != StringRef::npos) { + StringRef SDK = isysroot.slice(BeginSDK + 5, EndSDK); + if (!SDK.startswith(getPlatformFamily())) + getDriver().Diag(diag::warn_incompatible_sysroot) + << SDK << getPlatformFamily(); + } + } } void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, Index: test/Driver/incompatible_sysroot.c =================================================================== --- /dev/null +++ test/Driver/incompatible_sysroot.c @@ -0,0 +1,12 @@ +// RUN: %clang -Wincompatible-sysroot -isysroot SDKs/MacOSX10.9.sdk -mios-version-min=9.0 -S -o - %s 2>&1 | FileCheck -check-prefix CHECK-OSX-IOS %s +// RUN: %clang -Wincompatible-sysroot -isysroot SDKs/iPhoneOS9.2.sdk -mwatchos-version-min=2.0 -S -o - %s 2>&1 | FileCheck -check-prefix CHECK-IOS-WATCHOS %s +// RUN: %clang -Wincompatible-sysroot -isysroot SDKs/iPhoneOS9.2.sdk -mtvos-version-min=9.0 -S -o - %s 2>&1 | FileCheck -check-prefix CHECK-IOS-TVOS %s +// RUN: %clang -Wincompatible-sysroot -isysroot SDKs/iPhoneSimulator9.2.sdk -mios-version-min=9.0 -S -o - %s 2>&1 | FileCheck -check-prefix CHECK-IOS-IOSSIM %s +// RUN: %clang -Wno-incompatible-sysroot -isysroot SDKs/MacOSX10.9.sdk -mios-version-min=9.0 -S -o - %s 2>&1 | FileCheck -check-prefix CHECK-OSX-IOS-DISABLED %s + +int main() { return 0; } +// CHECK-OSX-IOS: warning: using sysroot for 'MacOSX10.9' but targeting 'iPhone' +// CHECK-IOS-WATCHOS: warning: using sysroot for 'iPhoneOS9.2' but targeting 'Watch' +// CHECK-IOS-TVOS: warning: using sysroot for 'iPhoneOS9.2' but targeting 'AppleTV' +// CHECK-IOS-IOSSIM-NOT: warning: using sysroot for '{{.*}}' but targeting '{{.*}}' +// CHECK-OSX-IOS-DISABLED-NOT: warning: using sysroot for '{{.*}}' but targeting '{{.*}}'