Index: lib/builtins/CMakeLists.txt =================================================================== --- lib/builtins/CMakeLists.txt +++ lib/builtins/CMakeLists.txt @@ -132,6 +132,7 @@ negvdi2.c negvsi2.c negvti2.c + os_version_check.c paritydi2.c paritysi2.c parityti2.c Index: lib/builtins/os_version_check.c =================================================================== --- lib/builtins/os_version_check.c +++ lib/builtins/os_version_check.c @@ -0,0 +1,115 @@ +/* ===-- os_version_check.c - OS version checking -------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements the function __isOSVersionAtLeast, used by + * Objective-C's @available + * + * ===----------------------------------------------------------------------=== + */ + +#ifdef __APPLE__ + +#include +#include +#include +#include +#include +#include +#include + +/* These three variables hold the host's OS version. */ +static int32_t GlobalMajor, GlobalMinor, GlobalSubminor; +static dispatch_once_t DispatchOnceCounter; + +/* Find and parse the SystemVersion.plist file. */ +static void parseSystemVersionPList(void *Unused) { + (void)Unused; + + char *PListPath = "/System/Library/CoreServices/SystemVersion.plist"; + +#if TARGET_OS_SIMULATOR + char *PListPathPrefix = getenv("IPHONE_SIMULATOR_ROOT"); + if (!PListPathPrefix) + return; + char FullPath[strlen(PListPathPrefix) + strlen(PListPath) + 1]; + strcpy(FullPath, PListPathPrefix); + strcat(FullPath, PListPath); + PListPath = FullPath; +#endif + FILE *PropertyList = fopen(PListPath, "r"); + if (!PropertyList) + return; + + /* Dynamically allocated stuff. */ + CFDictionaryRef PListRef = NULL; + CFDataRef FileContentsRef = NULL; + UInt8 *PListBuf = NULL; + + fseek(PropertyList, 0, SEEK_END); + long PListFileSize = ftell(PropertyList); + if (PListFileSize < 0) + goto Fail; + rewind(PropertyList); + + PListBuf = malloc((size_t)PListFileSize); + if (!PListBuf) + goto Fail; + + size_t NumRead = fread(PListBuf, 1, (size_t)PListFileSize, PropertyList); + if (NumRead != (size_t)PListFileSize) + goto Fail; + + /* Get the file buffer into CF's format. We pass in a null allocator here * + * because we free PListBuf ourselves */ + FileContentsRef = CFDataCreateWithBytesNoCopy( + NULL, PListBuf, (CFIndex)NumRead, kCFAllocatorNull); + if (!FileContentsRef) + goto Fail; + + if (&CFPropertyListCreateWithData) + PListRef = CFPropertyListCreateWithData( + NULL, FileContentsRef, kCFPropertyListImmutable, NULL, NULL); + else + PListRef = CFPropertyListCreateFromXMLData(NULL, FileContentsRef, + kCFPropertyListImmutable, NULL); + if (!PListRef) + goto Fail; + + CFTypeRef OpaqueValue = + CFDictionaryGetValue(PListRef, CFSTR("ProductVersion")); + if (!OpaqueValue || CFGetTypeID(OpaqueValue) != CFStringGetTypeID()) + goto Fail; + + char VersionStr[32]; + if (!CFStringGetCString((CFStringRef)OpaqueValue, VersionStr, + sizeof(VersionStr), kCFStringEncodingUTF8)) + goto Fail; + sscanf(VersionStr, "%d.%d.%d", &GlobalMajor, &GlobalMinor, &GlobalSubminor); + +Fail: + if (PListRef) + CFRelease(PListRef); + if (FileContentsRef) + CFRelease(FileContentsRef); + free(PListBuf); + fclose(PropertyList); +} + +int32_t __isOSVersionAtLeast(int32_t Major, int32_t Minor, int32_t Subminor) { + /* Populate the global version variables, if they haven't already. */ + dispatch_once_f(&DispatchOnceCounter, NULL, parseSystemVersionPList); + + if (Major < GlobalMajor) return 1; + if (Major > GlobalMajor) return 0; + if (Minor < GlobalMinor) return 1; + if (Minor > GlobalMinor) return 0; + return Subminor <= GlobalSubminor; +} + +#endif Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -5,9 +5,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/lit.common.configured.in ${CMAKE_CURRENT_BINARY_DIR}/lit.common.configured) -# BlocksRuntime and builtins testsuites are not yet ported to lit. +# BlocksRuntime (and most of builtins) testsuites are not yet ported to lit. # add_subdirectory(BlocksRuntime) -# add_subdirectory(builtins) set(SANITIZER_COMMON_LIT_TEST_DEPS) if(COMPILER_RT_STANDALONE_BUILD) @@ -39,6 +38,9 @@ # Run sanitizer tests only if we're sure that clang would produce # working binaries. if(COMPILER_RT_CAN_EXECUTE_TESTS) + if(COMPILER_RT_BUILD_BUILTINS) + add_subdirectory(builtins) + endif() if(COMPILER_RT_HAS_ASAN) add_subdirectory(asan) endif() Index: test/builtins/CMakeLists.txt =================================================================== --- test/builtins/CMakeLists.txt +++ test/builtins/CMakeLists.txt @@ -0,0 +1,15 @@ +set(BUILTINS_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +set(BUILTINS_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS} builtins) +set(BUILTINS_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/TestCases) + +# Test cases. +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg +) + +add_lit_testsuite(check-builtins "Running the Builtins tests" + ${BUILTINS_TESTSUITES} + DEPENDS ${BUILTINS_TEST_DEPS}) +set_target_properties(check-builtins PROPERTIES FOLDER "Compiler-RT Misc") Index: test/builtins/TestCases/Darwin/lit.local.cfg =================================================================== --- test/builtins/TestCases/Darwin/lit.local.cfg +++ test/builtins/TestCases/Darwin/lit.local.cfg @@ -0,0 +1,9 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +root = getRoot(config) + +if root.host_os not in ['Darwin']: + config.unsupported = True Index: test/builtins/TestCases/Darwin/os_version_check_test.c =================================================================== --- test/builtins/TestCases/Darwin/os_version_check_test.c +++ test/builtins/TestCases/Darwin/os_version_check_test.c @@ -0,0 +1,19 @@ +// RUN: %clang %s -o %t -mmacosx-version-min=10.5 -framework CoreFoundation -DMAJOR=%macos_version_major -DMINOR=%macos_version_minor -DSUBMINOR=%macos_version_subminor +// RUN: %run %t + +int __isOSVersionAtLeast(int Major, int Minor, int Subminor); + +int main() { + if (!__isOSVersionAtLeast(MAJOR, MINOR, SUBMINOR)) + return 1; + if (__isOSVersionAtLeast(MAJOR, MINOR, SUBMINOR + 1)) + return 1; + if (SUBMINOR && __isOSVersionAtLeast(MAJOR + 1, MINOR, SUBMINOR - 1)) + return 1; + if (SUBMINOR && !__isOSVersionAtLeast(MAJOR, MINOR, SUBMINOR - 1)) + return 1; + if (MAJOR && !__isOSVersionAtLeast(MAJOR - 1, MINOR + 1, SUBMINOR)) + return 1; + + return 0; +} Index: test/builtins/lit.cfg =================================================================== --- test/builtins/lit.cfg +++ test/builtins/lit.cfg @@ -0,0 +1,20 @@ +# -*- Python -*- + +import os + +# Setup config name. +config.name = 'Builtins' + +# Setup source root. +config.test_source_root = os.path.dirname(__file__) + +# Test suffixes. +config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm'] + +# Define %clang and %clangxx substitutions to use in test RUN lines. +config.substitutions.append( ("%clang ", " " + config.clang + " ") ) + +if config.host_os == 'Darwin': + config.substitutions.append( ("%macos_version_major", str(config.darwin_osx_version[0])) ) + config.substitutions.append( ("%macos_version_minor", str(config.darwin_osx_version[1])) ) + config.substitutions.append( ("%macos_version_subminor", str(config.darwin_osx_version[2])) ) Index: test/builtins/lit.site.cfg.in =================================================================== --- test/builtins/lit.site.cfg.in +++ test/builtins/lit.site.cfg.in @@ -0,0 +1,7 @@ +@LIT_SITE_CFG_IN_HEADER@ + +# Load common config for all compiler-rt lit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") + +# Load tool-specific config that would do the real work. +lit_config.load_config(config, "@BUILTINS_LIT_SOURCE_DIR@/lit.cfg") Index: test/lit.common.cfg =================================================================== --- test/lit.common.cfg +++ test/lit.common.cfg @@ -129,6 +129,7 @@ try: osx_version = subprocess.check_output(["sw_vers", "-productVersion"]) osx_version = tuple(int(x) for x in osx_version.split('.')) + config.darwin_osx_version = osx_version if osx_version >= (10, 11): config.available_features.add('osx-autointerception') config.available_features.add('osx-ld64-live_support')