llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-driver Author: Ian Anderson (ian-twilightcoder) <details> <summary>Changes</summary> DarwinSDKInfo::getPlatformPrefix(...) is passed the effective target triple which has undergone modifications from the original -target value, which can sometimes even include changes to the triple's environment. That will cause it to fail to match the platform infos, not get a platform prefix, and get incorrect default search paths. In the case where a triple doesn't match, check all platform infos, and if they all have the same platform prefix, then use that. DarwinSDKInfo::supportsTriple(...) doesn't try to match the architecture of the triple. That makes it not emit -Wincompatible-sysroot e.g. when trying to use arm64 against a sufficiently old macOS SDK or when still trying to build ppc for macOS. Instead of parsing values from SDKSettings.json into a Triple, storing the probably-relevant components, and then comparing those against a full Triple, just store the parsed triple and get rid of the custom comparison code. While this does make the matching problem above a little more fragile, in practice that's well mitigated by treating thumb* and arm* as equivalent, and it does allow for better diagnostics and overall simpler code. Clean up some unnecessary copies in DarwinSDKInfo and related code. Assisted-by: Claude Code rdar://172876443 --- Patch is 22.60 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/204061.diff 7 Files Affected: - (modified) clang/include/clang/Basic/DarwinSDKInfo.h (+28-36) - (modified) clang/lib/Basic/DarwinSDKInfo.cpp (+169-25) - (modified) clang/lib/Driver/ToolChains/Darwin.cpp (+6-12) - (modified) clang/lib/Driver/ToolChains/Darwin.h (+1-1) - (modified) clang/test/Driver/driverkit-path.c (+4) - (modified) clang/test/Driver/incompatible_sysroot.c (+5) - (modified) clang/unittests/Basic/DarwinSDKInfoTest.cpp (+3-4) ``````````diff diff --git a/clang/include/clang/Basic/DarwinSDKInfo.h b/clang/include/clang/Basic/DarwinSDKInfo.h index 072846b17fa0a..2d55f4f61cd90 100644 --- a/clang/include/clang/Basic/DarwinSDKInfo.h +++ b/clang/include/clang/Basic/DarwinSDKInfo.h @@ -18,6 +18,7 @@ #include "llvm/Support/VersionTuple.h" #include "llvm/Support/VirtualFileSystem.h" #include "llvm/TargetParser/Triple.h" +#include <cassert> #include <optional> #include <string> @@ -36,32 +37,18 @@ class DarwinSDKInfo { /// definitions, in the SDK. struct SDKPlatformInfo { public: - SDKPlatformInfo(llvm::Triple::VendorType Vendor, llvm::Triple::OSType OS, - llvm::Triple::EnvironmentType Environment, - llvm::Triple::ObjectFormatType ObjectFormat, - StringRef PlatformPrefix) - : Vendor(Vendor), OS(OS), Environment(Environment), - ObjectFormat(ObjectFormat), PlatformPrefix(PlatformPrefix) {} - - llvm::Triple::VendorType getVendor() const { return Vendor; } - llvm::Triple::OSType getOS() const { return OS; } - llvm::Triple::EnvironmentType getEnvironment() const { return Environment; } - llvm::Triple::ObjectFormatType getObjectFormat() const { - return ObjectFormat; - } - StringRef getPlatformPrefix() const { return PlatformPrefix; } + using TripleStorageType = SmallVector<llvm::Triple, 5>; - bool operator==(const llvm::Triple &RHS) const { - return (Vendor == RHS.getVendor()) && (OS == RHS.getOS()) && - (Environment == RHS.getEnvironment()) && - (ObjectFormat == RHS.getObjectFormat()); + SDKPlatformInfo(TripleStorageType Triples, StringRef PlatformPrefix) + : Triples(std::move(Triples)), PlatformPrefix(PlatformPrefix) { + assert(!this->Triples.empty() && "Triples cannot be empty"); } + const TripleStorageType &getTriples() const { return Triples; } + StringRef getPlatformPrefix() const { return PlatformPrefix; } + private: - llvm::Triple::VendorType Vendor; - llvm::Triple::OSType OS; - llvm::Triple::EnvironmentType Environment; - llvm::Triple::ObjectFormatType ObjectFormat; + TripleStorageType Triples; std::string PlatformPrefix; }; @@ -190,11 +177,23 @@ class DarwinSDKInfo { VersionMappings = llvm::DenseMap<OSEnvPair::StorageType, std::optional<RelatedTargetVersionMapping>>()) - : FilePath(FilePath), OS(OS), Environment(Environment), Version(Version), - DisplayName(DisplayName), + : FilePath(std::move(FilePath)), OS(OS), Environment(Environment), + Version(Version), DisplayName(DisplayName), MaximumDeploymentTarget(MaximumDeploymentTarget), PlatformInfos(std::move(PlatformInfos)), - VersionMappings(std::move(VersionMappings)) {} + VersionMappings(std::move(VersionMappings)) { + assert(!this->PlatformInfos.empty() && "PlatformInfos cannot be empty"); + } + + /// Construct SDK Info inferred from the parameters rather than read from + /// SDKSettings.json. + /// + /// This will infer \c PlatformInfos from an SDK for the OS/Environment that + /// predates the introduction of SDKSettings.json, and will not infer version + /// mappings. + DarwinSDKInfo(llvm::Triple::OSType OS, + llvm::Triple::EnvironmentType Environment, VersionTuple Version, + StringRef DisplayName, VersionTuple MaximumDeploymentTarget); StringRef getFilePath() const { return FilePath; } @@ -206,20 +205,13 @@ class DarwinSDKInfo { const StringRef getDisplayName() const { return DisplayName; } - const SDKPlatformInfo &getCanonicalPlatformInfo() const { - return PlatformInfos[0]; + const llvm::Triple &getCanonicalPlatformTriple() const { + return PlatformInfos[0].getTriples()[0]; } - bool supportsTriple(llvm::Triple Triple) const { - return llvm::find(PlatformInfos, Triple) != PlatformInfos.end(); - } + bool supportsTriple(const llvm::Triple &Triple) const; - const StringRef getPlatformPrefix(llvm::Triple Triple) const { - auto PlatformInfoIt = llvm::find(PlatformInfos, Triple); - if (PlatformInfoIt == PlatformInfos.end()) - return StringRef(); - return PlatformInfoIt->getPlatformPrefix(); - } + StringRef getPlatformPrefix(const llvm::Triple &Triple) const; // Returns the optional, target-specific version mapping that maps from one // target to another target. diff --git a/clang/lib/Basic/DarwinSDKInfo.cpp b/clang/lib/Basic/DarwinSDKInfo.cpp index f7d02ef97f5a4..ece0eb61c27c5 100644 --- a/clang/lib/Basic/DarwinSDKInfo.cpp +++ b/clang/lib/Basic/DarwinSDKInfo.cpp @@ -12,6 +12,7 @@ #include "llvm/Support/JSON.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include "llvm/TargetParser/ARMTargetParser.h" #include <optional> using namespace clang; @@ -100,39 +101,118 @@ parseOSAndEnvironment(std::optional<StringRef> XcodePlatform) { return {OS, Environment}; } +static DarwinSDKInfo::PlatformInfoStorageType +legacyPlatformInfos(llvm::Triple::OSType SDKOS, + llvm::Triple::EnvironmentType SDKEnvironment) { + DarwinSDKInfo::PlatformInfoStorageType PlatformInfos; + // Synthesize platform infos for older SDKs from the first SDKs with + // SupportedTargets: macOS 10.15 (DriverKit 19.0), iOS 13.0, tvOS 13.0, + // watchOS 6.0. Older macOS SDKs supported ppc and i386 architectures, and + // maybe ppc64. Support for those is difficult to identify from the SDK, and + // so aren't listed here. Other older SDKs (especially iOS) most likely + // supported armv6 and armv7 architectures that aren't listed here either. + switch (SDKOS) { + case llvm::Triple::MacOSX: + PlatformInfos.push_back({{llvm::Triple("x86_64-apple-macosx")}, ""}); + // macOS 10.15 also has a Mac Catalyst supported target, but Mac Catalyst + // was new in that version so omit it for older versions. + break; + case llvm::Triple::DriverKit: + // DriverKit 19.0 only had SDKSettings.plist, which isn't used. So this code + // path is used in 19.x as well, not just earlier versions. + PlatformInfos.push_back( + {{llvm::Triple("x86_64-apple-driverkit")}, "/System/DriverKit"}); + break; + case llvm::Triple::IOS: + switch (SDKEnvironment) { + case llvm::Triple::UnknownEnvironment: + PlatformInfos.push_back( + {{llvm::Triple("armv7-apple-ios"), llvm::Triple("armv7s-apple-ios"), + llvm::Triple("arm64-apple-ios")}, + ""}); + break; + case llvm::Triple::Simulator: + PlatformInfos.push_back( + {{llvm::Triple("x86_64-apple-ios-simulator")}, ""}); + break; + default: + break; + } + break; + case llvm::Triple::TvOS: + switch (SDKEnvironment) { + case llvm::Triple::UnknownEnvironment: + PlatformInfos.push_back({{llvm::Triple("arm64-apple-tvos")}, ""}); + break; + case llvm::Triple::Simulator: + PlatformInfos.push_back( + {{llvm::Triple("x86_64-apple-tvos-simulator")}, ""}); + break; + default: + break; + } + break; + case llvm::Triple::WatchOS: + switch (SDKEnvironment) { + case llvm::Triple::UnknownEnvironment: + PlatformInfos.push_back({{llvm::Triple("armv7k-apple-watchos"), + llvm::Triple("arm64_32-apple-watchos")}, + ""}); + break; + case llvm::Triple::Simulator: + PlatformInfos.push_back( + {{llvm::Triple("x86_64-apple-watchos-simulator")}, ""}); + break; + default: + break; + } + break; + case llvm::Triple::BridgeOS: + PlatformInfos.push_back({{llvm::Triple("armv7-apple-bridgeos"), + llvm::Triple("armv7s-apple-bridgeos"), + llvm::Triple("arm64-apple-bridgeos")}, + ""}); + break; + default: + break; + } + return PlatformInfos; +} + static DarwinSDKInfo::PlatformInfoStorageType parsePlatformInfos( const llvm::json::Object &Obj, std::optional<StringRef> XcodePlatform, llvm::Triple::OSType SDKOS, llvm::Triple::EnvironmentType SDKEnvironment, VersionTuple Version) { DarwinSDKInfo::PlatformInfoStorageType PlatformInfos; auto SupportedTargets = Obj.getObject("SupportedTargets"); - if (!SupportedTargets) { - // For older SDKs that don't have SupportedTargets, infer one from the SDK's - // OS/Environment. - StringRef PlatformPrefix; - if (SDKOS == llvm::Triple::DriverKit) - PlatformPrefix = "/System/DriverKit"; - PlatformInfos.push_back({llvm::Triple::Apple, SDKOS, SDKEnvironment, - llvm::Triple::MachO, PlatformPrefix}); - return PlatformInfos; - } + if (!SupportedTargets) + return legacyPlatformInfos(SDKOS, SDKEnvironment); - for (auto SupportedTargetPair : *SupportedTargets) { - llvm::json::Object *SupportedTarget = + for (const auto &SupportedTargetPair : *SupportedTargets) { + const llvm::json::Object *SupportedTarget = SupportedTargetPair.getSecond().getAsObject(); + if (!SupportedTarget) + continue; + + auto Archs = SupportedTarget->getArray("Archs"); auto Vendor = SupportedTarget->getString("LLVMTargetTripleVendor"); auto OS = SupportedTarget->getString("LLVMTargetTripleSys"); - if (!Vendor || !OS) + if (!Archs || !Vendor || !OS) continue; - StringRef Arch = llvm::Triple::getArchName(llvm::Triple::UnknownArch); + DarwinSDKInfo::SDKPlatformInfo::TripleStorageType Triples; auto Environment = SupportedTarget->getString("LLVMTargetTripleEnvironment"); - llvm::Triple Triple; - if (Environment) - Triple = llvm::Triple(Arch, *Vendor, *OS, *Environment); - else - Triple = llvm::Triple(Arch, *Vendor, *OS); + for (const auto &ArchValue : *Archs) { + if (auto Arch = ArchValue.getAsString()) { + if (Environment && !Environment->empty()) + Triples.emplace_back(*Arch, *Vendor, *OS, *Environment); + else + Triples.emplace_back(*Arch, *Vendor, *OS); + } + } + if (Triples.empty()) + continue; // The key is either the Xcode platform, or a variant. The platform must be // the first entry in the returned PlatformInfoStorageType. @@ -147,19 +227,17 @@ static DarwinSDKInfo::PlatformInfoStorageType parsePlatformInfos( } else { // Older SDKs don't have SystemPrefix in SupportedTargets, manually add // their prefixes. - if ((Triple.getOS() == llvm::Triple::DriverKit) && + if ((Triples[0].getOS() == llvm::Triple::DriverKit) && (Version < VersionTuple(22, 1))) EffectivePlatformPrefix = "/System/DriverKit"; } } - DarwinSDKInfo::SDKPlatformInfo PlatformInfo( - Triple.getVendor(), Triple.getOS(), Triple.getEnvironment(), - Triple.getObjectFormat(), EffectivePlatformPrefix); if (PlatformOrVariant == XcodePlatform) - PlatformInfos.insert(PlatformInfos.begin(), PlatformInfo); + PlatformInfos.insert(PlatformInfos.begin(), + {std::move(Triples), EffectivePlatformPrefix}); else - PlatformInfos.push_back(PlatformInfo); + PlatformInfos.emplace_back(std::move(Triples), EffectivePlatformPrefix); } return PlatformInfos; } @@ -195,6 +273,8 @@ DarwinSDKInfo::parseDarwinSDKSettingsJSON(std::string FilePath, PlatformInfoStorageType PlatformInfos = parsePlatformInfos(*Obj, XcodePlatform, OSAndEnvironment.first, OSAndEnvironment.second, *Version); + if (PlatformInfos.empty()) + return std::nullopt; llvm::DenseMap<OSEnvPair::StorageType, std::optional<RelatedTargetVersionMapping>> VersionMappings; @@ -265,3 +345,67 @@ clang::parseDarwinSDKInfo(llvm::vfs::FileSystem &VFS, StringRef SDKRootPath) { return llvm::make_error<llvm::StringError>("invalid SDKSettings.json", llvm::inconvertibleErrorCode()); } + +DarwinSDKInfo::DarwinSDKInfo(llvm::Triple::OSType OS, + llvm::Triple::EnvironmentType Environment, + VersionTuple Version, StringRef DisplayName, + VersionTuple MaximumDeploymentTarget) + : DarwinSDKInfo("", OS, Environment, Version, DisplayName, + MaximumDeploymentTarget, + legacyPlatformInfos(OS, Environment)) {} + +static DarwinSDKInfo::PlatformInfoStorageType::const_iterator +findPlatformInfo(const DarwinSDKInfo::PlatformInfoStorageType &PlatformInfos, + const llvm::Triple &Triple) { + auto PlatformInfoIt = llvm::find_if( + PlatformInfos, + [&Triple](const DarwinSDKInfo::SDKPlatformInfo &PlatformInfo) { + const auto &Triples = PlatformInfo.getTriples(); + return llvm::find(Triples, Triple) != Triples.end(); + }); + + // The SDK specifies values for Xcode to use for the -target argument. It's + // hard to perfectly match the triple passed to this function against those + // values though. The passed in triple might have been computed from just + // -arch, or it might have been modified by -march and several other arguments + // that can effect any of the triple components. It's not really possible to + // account for all of the triple variations, but one common modification is + // that "arm" gets changed to "thumb". If the passed in triple is "thumb", try + // mapping it back to an "arm" triple since that's what the SDK will specify. + if (PlatformInfoIt == PlatformInfos.end() && + Triple.getArch() == llvm::Triple::thumb) { + StringRef ARMArch = llvm::Triple::getArchName(llvm::Triple::arm); + + // Preserve the sub-arch from the triple. + llvm::ARM::ArchKind ArchKind = llvm::ARM::parseArch(Triple.getArchName()); + StringRef SubArch = llvm::ARM::getSubArch(ArchKind); + + llvm::Triple ARMTriple(Triple); + ARMTriple.setArchName((ARMArch + SubArch).str()); + PlatformInfoIt = findPlatformInfo(PlatformInfos, ARMTriple); + } + + return PlatformInfoIt; +} + +bool DarwinSDKInfo::supportsTriple(const llvm::Triple &Triple) const { + return findPlatformInfo(PlatformInfos, Triple) != PlatformInfos.end(); +} + +StringRef DarwinSDKInfo::getPlatformPrefix(const llvm::Triple &Triple) const { + auto PlatformInfoIt = findPlatformInfo(PlatformInfos, Triple); + if (PlatformInfoIt != PlatformInfos.end()) + return PlatformInfoIt->getPlatformPrefix(); + + // This triple probably isn't supported by the SDK. However, almost every SDK + // just has a single prefix where all of its contents are, so return that. + StringRef PlatformPrefix = PlatformInfos[0].getPlatformPrefix(); + for (PlatformInfoIt = std::next(PlatformInfos.begin()); + PlatformInfoIt != PlatformInfos.end(); ++PlatformInfoIt) { + if (PlatformInfoIt->getPlatformPrefix() != PlatformPrefix) { + // This SDK has multiple prefixes, give up and return nothing. + return StringRef(); + } + } + return PlatformPrefix; +} diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 59744d1cb3e8c..c516690b2b8a8 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1221,7 +1221,7 @@ AppleMachO::~AppleMachO() {} MachO::~MachO() {} void Darwin::VerifyTripleForSDK(const llvm::opt::ArgList &Args, - const llvm::Triple Triple) const { + const llvm::Triple &Triple) const { if (SDKInfo) { if (!SDKInfo->supportsTriple(Triple)) getDriver().Diag(diag::warn_incompatible_sysroot) @@ -2043,15 +2043,14 @@ struct DarwinPlatform { } static DarwinPlatform createFromSDKInfo(StringRef SDKRoot, const DarwinSDKInfo &SDKInfo) { - const DarwinSDKInfo::SDKPlatformInfo PlatformInfo = - SDKInfo.getCanonicalPlatformInfo(); - const llvm::Triple::OSType OS = PlatformInfo.getOS(); + const llvm::Triple &PlatformTriple = SDKInfo.getCanonicalPlatformTriple(); + const llvm::Triple::OSType OS = PlatformTriple.getOS(); VersionTuple Version = SDKInfo.getVersion(); if (OS == llvm::Triple::MacOSX) Version = getVersionFromString( getSystemOrSDKMacOSVersion(Version.getAsString())); DarwinPlatform Result(InferredFromSDK, getPlatformFromOS(OS), Version); - Result.Environment = getEnvKindFromEnvType(PlatformInfo.getEnvironment()); + Result.Environment = getEnvKindFromEnvType(PlatformTriple.getEnvironment()); Result.InferSimulatorFromArch = false; Result.InferredSource = SDKRoot; return Result; @@ -2084,15 +2083,10 @@ struct DarwinPlatform { llvm::Triple::OSType OS = getOSFromPlatform(Platform); llvm::Triple::EnvironmentType EnvironmentType = getEnvTypeFromEnvKind(Environment); - StringRef PlatformPrefix = - (Platform == DarwinPlatformKind::DriverKit) ? "/System/DriverKit" : ""; - return DarwinSDKInfo("", OS, EnvironmentType, getOSVersion(), + return DarwinSDKInfo(OS, EnvironmentType, getOSVersion(), getDisplayName(Platform, Environment, getOSVersion()), /*MaximumDeploymentTarget=*/ - VersionTuple(getOSVersion().getMajor(), 0, 99), - {DarwinSDKInfo::SDKPlatformInfo( - llvm::Triple::Apple, OS, EnvironmentType, - llvm::Triple::MachO, PlatformPrefix)}); + VersionTuple(getOSVersion().getMajor(), 0, 99)); } private: diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index a737d2ac799c4..9ef57427f9621 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -390,7 +390,7 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public AppleMachO { void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const; void VerifyTripleForSDK(const llvm::opt::ArgList &Args, - const llvm::Triple Triple) const; + const llvm::Triple &Triple) const; protected: /// Lazily initialize the target platform from the triple when diff --git a/clang/test/Driver/driverkit-path.c b/clang/test/Driver/driverkit-path.c index a2fa06f47ea2e..e430b1ad6edeb 100644 --- a/clang/test/Driver/driverkit-path.c +++ b/clang/test/Driver/driverkit-path.c @@ -30,6 +30,10 @@ int main() { return 0; } // RUN: | FileCheck %s -DSDKROOT=%S/Inputs/DriverKit21.0.1.sdk -DRESOURCE_DIR=%clang-resource-dir --check-prefix=INC // RUN: %clang %s -target x86_64-apple-driverkit23.0 -isysroot %S/Inputs/DriverKit23.0.sdk -x c++ -### 2>&1 \ // RUN: | FileCheck %s -DSDKROOT=%S/Inputs/DriverKit23.0.sdk -DRESOURCE_DIR=%clang-resource-dir --check-prefix=INC +// RUN: %clang %s -target ppc-apple-driverkit23.0 -isysroot %S/Inputs/DriverKit23.0.sdk -x c++ -### 2>&1 \ +// RUN: | FileCheck %s -DSDKROOT=%S/Inputs/DriverKit23.0.sdk -DRESOURCE_DIR=%clang-resource-dir --check-prefix=INC +// RUN: %clang %s -target arm64-apple-driverkit23.0-macabi -isysroot %S/Inputs/DriverKit23.0.sdk -x c++ -### 2>&1 \ +// RUN: | FileCheck %s -DSDKROOT=%S/Inputs/DriverKit23.0.sdk -DRESOURCE_DIR=%clang-resource-dir --check-prefix=INC // // INC: "-isysroot" "[[SDKROOT]]" // INC: "-internal-isystem" "[[SDKROOT]]/System/DriverKit/usr/local/include" diff --git a/clang/test/Driver/incompatible_sysroot.c b/clang/test/Driver/incompatible_sysroot.c index 6bc8cd07d1f12..ed3d716c02871 100644 --- a/clang/test/Driver/incompatible_sysroot.c +++ b/clang/test/Driver/incompatible_sysroot.c @@ -1,4 +1,5 @@ // REQUIRES: x86-registered-target +// REQUIRES: arm-registered-target // REQUIRES: aarch64-registered-target // RUN: %clang -target x86_64-apple-darwin -Wincompatible-sysroot -isysroot SDKs/MacOSX10.9.sdk -mios-version-min=9.0 -S -o - %s 2>&1 | FileCheck -check-prefix CHECK-OSX-IOS %s @@ -9,6 +10,8 @@ // RUN: %clang -target x86_64-apple-darwin -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 -target x86_64-apple-darwin -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 +// RUN: %clang ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/204061 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
