1# ===----------------------------------------------------------------------===## 2# 3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4# See https://llvm.org/LICENSE.txt for license information. 5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6# 7# ===----------------------------------------------------------------------===## 8 9from libcxx.test.dsl import * 10from lit.BooleanExpression import BooleanExpression 11import re 12import shutil 13import subprocess 14import sys 15 16_isAnyClang = lambda cfg: "__clang__" in compilerMacros(cfg) 17_isAppleClang = lambda cfg: "__apple_build_version__" in compilerMacros(cfg) 18_isAnyGCC = lambda cfg: "__GNUC__" in compilerMacros(cfg) 19_isClang = lambda cfg: _isAnyClang(cfg) and not _isAppleClang(cfg) 20_isGCC = lambda cfg: _isAnyGCC(cfg) and not _isAnyClang(cfg) 21_isAnyClangOrGCC = lambda cfg: _isAnyClang(cfg) or _isAnyGCC(cfg) 22_isClExe = lambda cfg: not _isAnyClangOrGCC(cfg) 23_isMSVC = lambda cfg: "_MSC_VER" in compilerMacros(cfg) 24_msvcVersion = lambda cfg: (int(compilerMacros(cfg)["_MSC_VER"]) // 100, int(compilerMacros(cfg)["_MSC_VER"]) % 100) 25 26def _getAndroidDeviceApi(cfg): 27 return int( 28 programOutput( 29 cfg, 30 r""" 31 #include <android/api-level.h> 32 #include <stdio.h> 33 int main() { 34 printf("%d\n", android_get_device_api_level()); 35 return 0; 36 } 37 """, 38 ) 39 ) 40 41 42def _mingwSupportsModules(cfg): 43 # Only mingw headers are known to work with libc++ built as a module, 44 # at the moment. 45 if not "__MINGW32__" in compilerMacros(cfg): 46 return False 47 # For mingw headers, check for a version known to support being built 48 # as a module. 49 return sourceBuilds( 50 cfg, 51 """ 52 #include <_mingw_mac.h> 53 #if __MINGW64_VERSION_MAJOR < 12 54 #error Headers known to be incompatible 55 #elif __MINGW64_VERSION_MAJOR == 12 56 // The headers were fixed to work with libc++ modules during 57 // __MINGW64_VERSION_MAJOR == 12. The headers became compatible 58 // with libc++ built as a module in 59 // 1652e9241b5d8a5a779c6582b1c3c4f4a7cc66e5 (Apr 2024), but the 60 // following commit 8c13b28ace68f2c0094d45121d59a4b951b533ed 61 // removed the now unused __mingw_static_ovr define. Use this 62 // as indicator for whether we've got new enough headers. 63 #ifdef __mingw_static_ovr 64 #error Headers too old 65 #endif 66 #else 67 // __MINGW64_VERSION_MAJOR > 12 should be ok. 68 #endif 69 int main() { return 0; } 70 """, 71 ) 72 73 74# Lit features are evaluated in order. Some checks may require the compiler detection to have 75# run first in order to work properly. 76DEFAULT_FEATURES = [ 77 # gcc-style-warnings detects compilers that understand -Wno-meow flags, unlike MSVC's compiler driver cl.exe. 78 Feature(name="gcc-style-warnings", when=_isAnyClangOrGCC), 79 Feature(name="cl-style-warnings", when=_isClExe), 80 Feature(name="apple-clang", when=_isAppleClang), 81 Feature( 82 name=lambda cfg: "apple-clang-{__clang_major__}".format(**compilerMacros(cfg)), 83 when=_isAppleClang, 84 ), 85 Feature( 86 name=lambda cfg: "apple-clang-{__clang_major__}.{__clang_minor__}".format(**compilerMacros(cfg)), 87 when=_isAppleClang, 88 ), 89 Feature( 90 name=lambda cfg: "apple-clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}".format(**compilerMacros(cfg)), 91 when=_isAppleClang, 92 ), 93 Feature(name="clang", when=_isClang), 94 Feature( 95 name=lambda cfg: "clang-{__clang_major__}".format(**compilerMacros(cfg)), 96 when=_isClang, 97 ), 98 Feature( 99 name=lambda cfg: "clang-{__clang_major__}.{__clang_minor__}".format(**compilerMacros(cfg)), 100 when=_isClang, 101 ), 102 Feature( 103 name=lambda cfg: "clang-{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}".format(**compilerMacros(cfg)), 104 when=_isClang, 105 ), 106 # Note: Due to a GCC bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104760), we must disable deprecation warnings 107 # on GCC or spurious diagnostics are issued. 108 # 109 # TODO: 110 # - Enable -Wplacement-new with GCC. 111 # - Enable -Wclass-memaccess with GCC. 112 Feature( 113 name="gcc", 114 when=_isGCC, 115 actions=[ 116 AddCompileFlag("-D_LIBCPP_DISABLE_DEPRECATION_WARNINGS"), 117 AddCompileFlag("-Wno-placement-new"), 118 AddCompileFlag("-Wno-class-memaccess"), 119 AddFeature("GCC-ALWAYS_INLINE-FIXME"), 120 ], 121 ), 122 Feature( 123 name=lambda cfg: "gcc-{__GNUC__}".format(**compilerMacros(cfg)), when=_isGCC 124 ), 125 Feature( 126 name=lambda cfg: "gcc-{__GNUC__}.{__GNUC_MINOR__}".format(**compilerMacros(cfg)), 127 when=_isGCC, 128 ), 129 Feature( 130 name=lambda cfg: "gcc-{__GNUC__}.{__GNUC_MINOR__}.{__GNUC_PATCHLEVEL__}".format(**compilerMacros(cfg)), 131 when=_isGCC, 132 ), 133 Feature(name="msvc", when=_isMSVC), 134 Feature(name=lambda cfg: "msvc-{}".format(*_msvcVersion(cfg)), when=_isMSVC), 135 Feature(name=lambda cfg: "msvc-{}.{}".format(*_msvcVersion(cfg)), when=_isMSVC), 136 137 Feature( 138 name="thread-safety", 139 when=lambda cfg: hasCompileFlag(cfg, "-Werror=thread-safety"), 140 actions=[AddCompileFlag("-Werror=thread-safety")], 141 ), 142 Feature( 143 name="diagnose-if-support", 144 when=lambda cfg: hasCompileFlag(cfg, "-Wuser-defined-warnings"), 145 actions=[AddCompileFlag("-Wuser-defined-warnings")], 146 ), 147 # Tests to validate whether the compiler has a way to set the maximum number 148 # of steps during constant evaluation. Since the flag differs per compiler 149 # store the "valid" flag as a feature. This allows passing the proper compile 150 # flag to the compiler: 151 # // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=12345678 152 # // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=12345678 153 Feature( 154 name="has-fconstexpr-steps", 155 when=lambda cfg: hasCompileFlag(cfg, "-fconstexpr-steps=1"), 156 ), 157 Feature( 158 name="has-fconstexpr-ops-limit", 159 when=lambda cfg: hasCompileFlag(cfg, "-fconstexpr-ops-limit=1"), 160 ), 161 Feature(name="has-fblocks", when=lambda cfg: hasCompileFlag(cfg, "-fblocks")), 162 Feature( 163 name="-fsized-deallocation", 164 when=lambda cfg: hasCompileFlag(cfg, "-fsized-deallocation"), 165 ), 166 Feature( 167 name="-faligned-allocation", 168 when=lambda cfg: hasCompileFlag(cfg, "-faligned-allocation"), 169 ), 170 Feature( 171 name="fdelayed-template-parsing", 172 when=lambda cfg: hasCompileFlag(cfg, "-fdelayed-template-parsing"), 173 ), 174 Feature( 175 name="has-fobjc-arc", 176 when=lambda cfg: hasCompileFlag(cfg, "-xobjective-c++ -fobjc-arc") 177 and sys.platform.lower().strip() == "darwin", 178 ), # TODO: this doesn't handle cross-compiling to Apple platforms. 179 Feature( 180 name="objective-c++", 181 when=lambda cfg: hasCompileFlag(cfg, "-xobjective-c++ -fobjc-arc"), 182 ), 183 Feature( 184 name="verify-support", 185 when=lambda cfg: hasCompileFlag(cfg, "-Xclang -verify-ignore-unexpected"), 186 ), 187 Feature( 188 name="add-latomic-workaround", # https://github.com/llvm/llvm-project/issues/73361 189 when=lambda cfg: sourceBuilds( 190 cfg, "int main(int, char**) { return 0; }", ["-latomic"] 191 ), 192 actions=[AddLinkFlag("-latomic")], 193 ), 194 Feature( 195 name="has-64-bit-atomics", 196 when=lambda cfg: sourceBuilds( 197 cfg, 198 """ 199 #include <atomic> 200 struct Large { char storage[64/8]; }; 201 std::atomic<Large> x; 202 int main(int, char**) { (void)x.load(); (void)x.is_lock_free(); return 0; } 203 """, 204 ), 205 ), 206 Feature( 207 name="has-1024-bit-atomics", 208 when=lambda cfg: sourceBuilds( 209 cfg, 210 """ 211 #include <atomic> 212 struct Large { char storage[1024/8]; }; 213 std::atomic<Large> x; 214 int main(int, char**) { (void)x.load(); (void)x.is_lock_free(); return 0; } 215 """, 216 ), 217 ), 218 # Tests that require 64-bit architecture 219 Feature( 220 name="32-bit-pointer", 221 when=lambda cfg: sourceBuilds( 222 cfg, 223 """ 224 int main(int, char**) { 225 static_assert(sizeof(void *) == 4); 226 } 227 """, 228 ), 229 ), 230 # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.20348.0): 231 # https://developercommunity.visualstudio.com/t/utf-8-locales-break-ctype-functions-for-wchar-type/1653678 232 Feature( 233 name="win32-broken-utf8-wchar-ctype", 234 when=lambda cfg: not "_LIBCPP_HAS_LOCALIZATION" in compilerMacros(cfg) 235 or compilerMacros(cfg)["_LIBCPP_HAS_LOCALIZATION"] == "1" 236 and "_WIN32" in compilerMacros(cfg) 237 and not programSucceeds( 238 cfg, 239 """ 240 #include <locale.h> 241 #include <wctype.h> 242 int main(int, char**) { 243 setlocale(LC_ALL, "en_US.UTF-8"); 244 return towlower(L'\\xDA') != L'\\xFA'; 245 } 246 """, 247 ), 248 ), 249 # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.19041.0). 250 # https://developercommunity.visualstudio.com/t/printf-formatting-with-g-outputs-too/1660837 251 Feature( 252 name="win32-broken-printf-g-precision", 253 when=lambda cfg: "_WIN32" in compilerMacros(cfg) 254 and not programSucceeds( 255 cfg, 256 """ 257 #include <stdio.h> 258 #include <string.h> 259 int main(int, char**) { 260 char buf[100]; 261 snprintf(buf, sizeof(buf), "%#.*g", 0, 0.0); 262 return strcmp(buf, "0."); 263 } 264 """, 265 ), 266 ), 267 # Check for a Windows UCRT bug (not fixed upstream yet). 268 # With UCRT, printf("%a", 0.0) produces "0x0.0000000000000p+0", 269 # while other C runtimes produce just "0x0p+0". 270 # https://developercommunity.visualstudio.com/t/Printf-formatting-of-float-as-hex-prints/1660844 271 Feature( 272 name="win32-broken-printf-a-precision", 273 when=lambda cfg: "_WIN32" in compilerMacros(cfg) 274 and not programSucceeds( 275 cfg, 276 """ 277 #include <stdio.h> 278 #include <string.h> 279 int main(int, char**) { 280 char buf[100]; 281 snprintf(buf, sizeof(buf), "%a", 0.0); 282 return strcmp(buf, "0x0p+0"); 283 } 284 """, 285 ), 286 ), 287 # Check for Glibc < 2.27, where the ru_RU.UTF-8 locale had 288 # mon_decimal_point == ".", which our tests don't handle. 289 Feature( 290 name="glibc-old-ru_RU-decimal-point", 291 when=lambda cfg: not "_LIBCPP_HAS_LOCALIZATION" in compilerMacros(cfg) 292 or compilerMacros(cfg)["_LIBCPP_HAS_LOCALIZATION"] == "1" 293 and not programSucceeds( 294 cfg, 295 """ 296 #include <locale.h> 297 #include <string.h> 298 int main(int, char**) { 299 setlocale(LC_ALL, "ru_RU.UTF-8"); 300 return strcmp(localeconv()->mon_decimal_point, ","); 301 } 302 """, 303 ), 304 ), 305 Feature( 306 name="has-unix-headers", 307 when=lambda cfg: sourceBuilds( 308 cfg, 309 """ 310 #include <unistd.h> 311 #include <sys/wait.h> 312 int main(int, char**) { 313 int fd[2]; 314 return pipe(fd); 315 } 316 """, 317 ), 318 ), 319 # Whether Bash can run on the executor. 320 # This is not always the case, for example when running on embedded systems. 321 # 322 # For the corner case of bash existing, but it being missing in the path 323 # set in %{exec} as "--env PATH=one-single-dir", the executor does find 324 # and executes bash, but bash then can't find any other common shell 325 # utilities. Test executing "bash -c 'bash --version'" to see if bash 326 # manages to find binaries to execute. 327 Feature( 328 name="executor-has-no-bash", 329 when=lambda cfg: runScriptExitCode(cfg, ["%{exec} bash -c 'bash --version'"]) != 0, 330 ), 331 # Whether module support for the platform is available. 332 Feature( 333 name="has-no-cxx-module-support", 334 # The libc of these platforms have functions with internal linkage. 335 # This is not allowed per C11 7.1.2 Standard headers/6 336 # Any declaration of a library function shall have external linkage. 337 when=lambda cfg: "__ANDROID__" in compilerMacros(cfg) 338 or "__FreeBSD__" in compilerMacros(cfg) 339 or ("_WIN32" in compilerMacros(cfg) and not _mingwSupportsModules(cfg)) 340 or platform.system().lower().startswith("aix") 341 # Avoid building on platforms that don't support modules properly. 342 or not hasCompileFlag(cfg, "-Wno-reserved-module-identifier") 343 or not sourceBuilds( 344 cfg, 345 """ 346 export module test; 347 int main(int, char**) { return 0; } 348 """, 349 ), 350 ), 351 # The time zone validation tests compare the output of zdump against the 352 # output generated by <chrono>'s time zone support. 353 Feature( 354 name="has-no-zdump", 355 when=lambda cfg: runScriptExitCode(cfg, ["zdump --version"]) != 0, 356 ), 357] 358 359# Deduce and add the test features that that are implied by the #defines in 360# the <__config> header. 361# 362# For each macro of the form `_LIBCPP_XXX_YYY_ZZZ` defined below that 363# is defined after including <__config>, add a Lit feature called 364# `libcpp-xxx-yyy-zzz`. When a macro is defined to a specific value 365# (e.g. `_LIBCPP_ABI_VERSION=2`), the feature is `libcpp-xxx-yyy-zzz=<value>`. 366# 367# Note that features that are more strongly tied to libc++ are named libcpp-foo, 368# while features that are more general in nature are not prefixed with 'libcpp-'. 369macros = { 370 "_LIBCPP_NO_VCRUNTIME": "libcpp-no-vcruntime", 371 "_LIBCPP_ABI_VERSION": "libcpp-abi-version", 372 "_LIBCPP_ABI_BOUNDED_ITERATORS": "libcpp-has-abi-bounded-iterators", 373 "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING": "libcpp-has-abi-bounded-iterators-in-string", 374 "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR": "libcpp-has-abi-bounded-iterators-in-vector", 375 "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY": "libcpp-has-abi-bounded-iterators-in-std-array", 376 "_LIBCPP_ABI_BOUNDED_UNIQUE_PTR": "libcpp-has-abi-bounded-unique_ptr", 377 "_LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE": "libcpp-has-abi-fix-unordered-container-size-type", 378 "_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR": "libcpp-deprecated-abi-disable-pair-trivial-copy-ctor", 379 "_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING": "libcpp-abi-no-compressed-pair-padding", 380 "_LIBCPP_PSTL_BACKEND_LIBDISPATCH": "libcpp-pstl-backend-libdispatch", 381} 382for macro, feature in macros.items(): 383 DEFAULT_FEATURES.append( 384 Feature( 385 name=lambda cfg, m=macro, f=feature: f + ("={}".format(compilerMacros(cfg)[m]) if compilerMacros(cfg)[m] else ""), 386 when=lambda cfg, m=macro: m in compilerMacros(cfg), 387 ) 388 ) 389 390true_false_macros = { 391 "_LIBCPP_HAS_THREAD_API_EXTERNAL": "libcpp-has-thread-api-external", 392 "_LIBCPP_HAS_THREAD_API_PTHREAD": "libcpp-has-thread-api-pthread", 393} 394for macro, feature in true_false_macros.items(): 395 DEFAULT_FEATURES.append( 396 Feature( 397 name=feature, 398 when=lambda cfg, m=macro: m in compilerMacros(cfg) 399 and compilerMacros(cfg)[m] == "1", 400 ) 401 ) 402 403inverted_macros = { 404 "_LIBCPP_HAS_TIME_ZONE_DATABASE": "no-tzdb", 405 "_LIBCPP_HAS_FILESYSTEM": "no-filesystem", 406 "_LIBCPP_HAS_LOCALIZATION": "no-localization", 407 "_LIBCPP_HAS_THREADS": "no-threads", 408 "_LIBCPP_HAS_MONOTONIC_CLOCK": "no-monotonic-clock", 409 "_LIBCPP_HAS_WIDE_CHARACTERS": "no-wide-characters", 410 "_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS": "libcpp-has-no-availability-markup", 411 "_LIBCPP_HAS_RANDOM_DEVICE": "no-random-device", 412 "_LIBCPP_HAS_UNICODE": "libcpp-has-no-unicode", 413 "_LIBCPP_HAS_TERMINAL": "no-terminal", 414} 415for macro, feature in inverted_macros.items(): 416 DEFAULT_FEATURES.append( 417 Feature( 418 name=feature, 419 when=lambda cfg, m=macro: m in compilerMacros(cfg) 420 and compilerMacros(cfg)[m] == "0", 421 ) 422 ) 423 424# Mapping from canonical locale names (used in the tests) to possible locale 425# names on various systems. Each locale is considered supported if any of the 426# alternative names is supported. 427locales = { 428 "en_US.UTF-8": ["en_US.UTF-8", "en_US.utf8", "English_United States.1252"], 429 "fr_FR.UTF-8": ["fr_FR.UTF-8", "fr_FR.utf8", "French_France.1252"], 430 "ja_JP.UTF-8": ["ja_JP.UTF-8", "ja_JP.utf8", "Japanese_Japan.923"], 431 "ru_RU.UTF-8": ["ru_RU.UTF-8", "ru_RU.utf8", "Russian_Russia.1251"], 432 "zh_CN.UTF-8": ["zh_CN.UTF-8", "zh_CN.utf8", "Chinese_China.936"], 433 "fr_CA.ISO8859-1": ["fr_CA.ISO8859-1", "French_Canada.1252"], 434 "cs_CZ.ISO8859-2": ["cs_CZ.ISO8859-2", "Czech_Czech Republic.1250"], 435} 436for locale, alts in locales.items(): 437 # Note: Using alts directly in the lambda body here will bind it to the value at the 438 # end of the loop. Assigning it to a default argument works around this issue. 439 DEFAULT_FEATURES.append( 440 Feature( 441 name="locale.{}".format(locale), 442 when=lambda cfg, alts=alts: hasAnyLocale(cfg, alts), 443 ) 444 ) 445 446 447# Add features representing the target platform name: darwin, linux, windows, etc... 448DEFAULT_FEATURES += [ 449 Feature(name="darwin", when=lambda cfg: "__APPLE__" in compilerMacros(cfg)), 450 Feature(name="windows", when=lambda cfg: "_WIN32" in compilerMacros(cfg)), 451 Feature( 452 name="windows-dll", 453 when=lambda cfg: "_WIN32" in compilerMacros(cfg) 454 and sourceBuilds( 455 cfg, 456 """ 457 #include <iostream> 458 int main(int, char**) { return 0; } 459 """, 460 ) 461 and programSucceeds( 462 cfg, 463 """ 464 #include <iostream> 465 #include <windows.h> 466 #include <winnt.h> 467 int main(int, char**) { 468 // Get a pointer to a data member that gets linked from the C++ 469 // library. This must be a data member (functions can get 470 // thunk inside the calling executable), and must not be 471 // something that is defined inline in headers. 472 void *ptr = &std::cout; 473 // Get a handle to the current main executable. 474 void *exe = GetModuleHandle(NULL); 475 // The handle points at the PE image header. Navigate through 476 // the header structure to find the size of the PE image (the 477 // executable). 478 PIMAGE_DOS_HEADER dosheader = (PIMAGE_DOS_HEADER)exe; 479 PIMAGE_NT_HEADERS ntheader = (PIMAGE_NT_HEADERS)((BYTE *)dosheader + dosheader->e_lfanew); 480 PIMAGE_OPTIONAL_HEADER peheader = &ntheader->OptionalHeader; 481 void *exeend = (BYTE*)exe + peheader->SizeOfImage; 482 // Check if the tested pointer - the data symbol from the 483 // C++ library - is located within the exe. 484 if (ptr >= exe && ptr <= exeend) 485 return 1; 486 // Return success if it was outside of the executable, i.e. 487 // loaded from a DLL. 488 return 0; 489 } 490 """, 491 ), 492 actions=[AddCompileFlag("-DTEST_WINDOWS_DLL")], 493 ), 494 Feature(name="linux", when=lambda cfg: "__linux__" in compilerMacros(cfg)), 495 Feature(name="android", when=lambda cfg: "__ANDROID__" in compilerMacros(cfg)), 496 Feature( 497 name=lambda cfg: "android-device-api={}".format(_getAndroidDeviceApi(cfg)), 498 when=lambda cfg: "__ANDROID__" in compilerMacros(cfg), 499 ), 500 Feature( 501 name="LIBCXX-ANDROID-FIXME", 502 when=lambda cfg: "__ANDROID__" in compilerMacros(cfg), 503 ), 504 Feature(name="netbsd", when=lambda cfg: "__NetBSD__" in compilerMacros(cfg)), 505 Feature(name="freebsd", when=lambda cfg: "__FreeBSD__" in compilerMacros(cfg)), 506 Feature( 507 name="LIBCXX-FREEBSD-FIXME", 508 when=lambda cfg: "__FreeBSD__" in compilerMacros(cfg), 509 ), 510 Feature( 511 name="LIBCXX-PICOLIBC-FIXME", 512 when=lambda cfg: sourceBuilds( 513 cfg, 514 """ 515 #include <string.h> 516 #ifndef __PICOLIBC__ 517 #error not picolibc 518 #endif 519 int main(int, char**) { return 0; } 520 """, 521 ), 522 ), 523 Feature( 524 name="LIBCXX-AMDGPU-FIXME", 525 when=lambda cfg: "__AMDGPU__" in compilerMacros(cfg), 526 ), 527 Feature( 528 name="LIBCXX-NVPTX-FIXME", 529 when=lambda cfg: "__NVPTX__" in compilerMacros(cfg), 530 ), 531 Feature( 532 name="can-create-symlinks", 533 when=lambda cfg: "_WIN32" not in compilerMacros(cfg) 534 or programSucceeds( 535 cfg, 536 # Creation of symlinks require elevated privileges on Windows unless 537 # Windows developer mode is enabled. 538 """ 539 #include <stdio.h> 540 #include <windows.h> 541 int main() { 542 CHAR tempDirPath[MAX_PATH]; 543 DWORD tempPathRet = GetTempPathA(MAX_PATH, tempDirPath); 544 if (tempPathRet == 0 || tempPathRet > MAX_PATH) { 545 return 1; 546 } 547 548 CHAR tempFilePath[MAX_PATH]; 549 UINT uRetVal = GetTempFileNameA( 550 tempDirPath, 551 "cxx", // Prefix 552 0, // Unique=0 also implies file creation. 553 tempFilePath); 554 if (uRetVal == 0) { 555 return 1; 556 } 557 558 CHAR symlinkFilePath[MAX_PATH]; 559 int ret = sprintf_s(symlinkFilePath, MAX_PATH, "%s_symlink", tempFilePath); 560 if (ret == -1) { 561 DeleteFileA(tempFilePath); 562 return 1; 563 } 564 565 // Requires either administrator, or developer mode enabled. 566 BOOL bCreatedSymlink = CreateSymbolicLinkA(symlinkFilePath, 567 tempFilePath, 568 SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); 569 if (!bCreatedSymlink) { 570 DeleteFileA(tempFilePath); 571 return 1; 572 } 573 574 DeleteFileA(tempFilePath); 575 DeleteFileA(symlinkFilePath); 576 return 0; 577 } 578 """, 579 ), 580 ), 581] 582 583# Add features representing the build host platform name. 584# The build host could differ from the target platform for cross-compilation. 585DEFAULT_FEATURES += [ 586 Feature(name="buildhost={}".format(sys.platform.lower().strip())), 587 # sys.platform can often be represented by a "sub-system", such as 'win32', 'cygwin', 'mingw', freebsd13 & etc. 588 # We define a consolidated feature on a few platforms. 589 Feature( 590 name="buildhost=windows", 591 when=lambda cfg: platform.system().lower().startswith("windows"), 592 ), 593 Feature( 594 name="buildhost=freebsd", 595 when=lambda cfg: platform.system().lower().startswith("freebsd"), 596 ), 597 Feature( 598 name="buildhost=aix", 599 when=lambda cfg: platform.system().lower().startswith("aix"), 600 ), 601] 602 603# Detect whether GDB is on the system, has Python scripting and supports 604# adding breakpoint commands. If so add a substitution to access it. 605def check_gdb(cfg): 606 gdb_path = shutil.which("gdb") 607 if gdb_path is None: 608 return False 609 610 # Check that we can set breakpoint commands, which was added in 8.3. 611 # Using the quit command here means that gdb itself exits, not just 612 # the "python <...>" command. 613 test_src = """\ 614try: 615 gdb.Breakpoint(\"main\").commands=\"foo\" 616except AttributeError: 617 gdb.execute(\"quit 1\") 618gdb.execute(\"quit\")""" 619 620 try: 621 stdout = subprocess.check_output( 622 [gdb_path, "-ex", "python " + test_src, "--batch"], 623 stderr=subprocess.DEVNULL, 624 universal_newlines=True, 625 ) 626 except subprocess.CalledProcessError: 627 # We can't set breakpoint commands 628 return False 629 630 # Check we actually ran the Python 631 return not "Python scripting is not supported" in stdout 632 633 634DEFAULT_FEATURES += [ 635 Feature( 636 name="host-has-gdb-with-python", 637 when=check_gdb, 638 actions=[AddSubstitution("%{gdb}", lambda cfg: shutil.which("gdb"))], 639 ) 640] 641 642# Helpers to define correspondances between LLVM versions and vendor system versions. 643# Those are used for backdeployment features below, do not use directly in tests. 644DEFAULT_FEATURES += [ 645 Feature( 646 name="_target-has-llvm-18", 647 when=lambda cfg: BooleanExpression.evaluate( 648 "target={{.+}}-apple-macosx{{15(.[0-9]+)?(.[0-9]+)?}}", 649 cfg.available_features, 650 ), 651 ), 652 Feature( 653 name="_target-has-llvm-17", 654 when=lambda cfg: BooleanExpression.evaluate( 655 "_target-has-llvm-18 || target={{.+}}-apple-macosx{{14.[4-9](.[0-9]+)?}} || target={{.+}}-apple-macosx{{1[5-9]([.].+)?}}", 656 cfg.available_features, 657 ), 658 ), 659 Feature( 660 name="_target-has-llvm-16", 661 when=lambda cfg: BooleanExpression.evaluate( 662 "_target-has-llvm-17 || target={{.+}}-apple-macosx{{14.[0-3](.[0-9]+)?}}", 663 cfg.available_features, 664 ), 665 ), 666 Feature( 667 name="_target-has-llvm-15", 668 when=lambda cfg: BooleanExpression.evaluate( 669 "_target-has-llvm-16 || target={{.+}}-apple-macosx{{13.[4-9](.[0-9]+)?}}", 670 cfg.available_features, 671 ), 672 ), 673 Feature( 674 name="_target-has-llvm-14", 675 when=lambda cfg: BooleanExpression.evaluate( 676 "_target-has-llvm-15", 677 cfg.available_features, 678 ), 679 ), 680 Feature( 681 name="_target-has-llvm-13", 682 when=lambda cfg: BooleanExpression.evaluate( 683 "_target-has-llvm-14 || target={{.+}}-apple-macosx{{13.[0-3](.[0-9]+)?}}", 684 cfg.available_features, 685 ), 686 ), 687 Feature( 688 name="_target-has-llvm-12", 689 when=lambda cfg: BooleanExpression.evaluate( 690 "_target-has-llvm-13 || target={{.+}}-apple-macosx{{12.[3-9](.[0-9]+)?}}", 691 cfg.available_features, 692 ), 693 ), 694 Feature( 695 name="_target-has-llvm-11", 696 when=lambda cfg: BooleanExpression.evaluate( 697 "_target-has-llvm-12 || target={{.+}}-apple-macosx{{(11.[0-9]|12.[0-2])(.[0-9]+)?}}", 698 cfg.available_features, 699 ), 700 ), 701 Feature( 702 name="_target-has-llvm-10", 703 when=lambda cfg: BooleanExpression.evaluate( 704 "_target-has-llvm-11", 705 cfg.available_features, 706 ), 707 ), 708 Feature( 709 name="_target-has-llvm-9", 710 when=lambda cfg: BooleanExpression.evaluate( 711 "_target-has-llvm-10 || target={{.+}}-apple-macosx{{10.15(.[0-9]+)?}}", 712 cfg.available_features, 713 ), 714 ), 715] 716 717# Define features for back-deployment testing. 718# 719# These features can be used to XFAIL tests that fail when deployed on (or compiled 720# for) an older system. For example, if a test exhibits a bug in the libc++ on a 721# particular system version, or if it uses a symbol that is not available on an 722# older version of the dylib, it can be marked as XFAIL with these features. 723# 724# We have two families of Lit features: 725# 726# The first one is `using-built-library-before-llvm-XYZ`. These features encode the 727# fact that the test suite is being *run* against a version of the shared/static library 728# that predates LLVM version XYZ. This is useful to represent the use case of compiling 729# a program against the latest libc++ but then deploying it and running it on an older 730# system with an older version of the (usually shared) library. 731# 732# This feature is built up using the target triple passed to the compiler and the 733# `stdlib=system` Lit feature, which encodes that we're running against the same library 734# as described by the target triple. 735# 736# The second set of features is `availability-<FEATURE>-missing`. This family of Lit 737# features encodes the presence of availability markup in the libc++ headers. This is 738# useful to check that a test fails specifically when compiled for a given deployment 739# target, such as when testing availability markup where we want to make sure that 740# using the annotated facility on a deployment target that doesn't support it will fail 741# at compile time. This can be achieved by creating a `.verify.cpp` test that checks for 742# the right errors and marking the test as `REQUIRES: availability-<FEATURE>-missing`. 743# 744# This feature is built up using the presence of availability markup detected inside 745# __config, the flavor of the library being tested and the target triple passed to the 746# compiler. 747# 748# Note that both families of Lit features are similar but different in important ways. 749# For example, tests for availability markup should be expected to produce diagnostics 750# regardless of whether we're running against a system library, as long as we're using 751# a libc++ flavor that enables availability markup. Similarly, a test could fail when 752# run against the system library of an older version of FreeBSD, even though FreeBSD 753# doesn't provide availability markup at the time of writing this. 754for version in ("9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"): 755 DEFAULT_FEATURES.append( 756 Feature( 757 name="using-built-library-before-llvm-{}".format(version), 758 when=lambda cfg, v=version: BooleanExpression.evaluate( 759 "stdlib=system && !_target-has-llvm-{}".format(v), 760 cfg.available_features, 761 ), 762 ) 763 ) 764 765DEFAULT_FEATURES += [ 766 # Tests that require std::filesystem support in the built library 767 Feature( 768 name="availability-filesystem-missing", 769 when=lambda cfg: BooleanExpression.evaluate( 770 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-9)", 771 cfg.available_features, 772 ), 773 ), 774 # Tests that require the C++20 synchronization library (P1135R6 implemented by https://llvm.org/D68480) in the built library 775 Feature( 776 name="availability-synchronization_library-missing", 777 when=lambda cfg: BooleanExpression.evaluate( 778 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-11)", 779 cfg.available_features, 780 ), 781 ), 782 # Tests that require https://wg21.link/P0482 support in the built library 783 Feature( 784 name="availability-char8_t_support-missing", 785 when=lambda cfg: BooleanExpression.evaluate( 786 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-12)", 787 cfg.available_features, 788 ), 789 ), 790 # Tests that require std::to_chars(floating-point) in the built library 791 Feature( 792 name="availability-fp_to_chars-missing", 793 when=lambda cfg: BooleanExpression.evaluate( 794 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-14)", 795 cfg.available_features, 796 ), 797 ), 798 # Tests that require __libcpp_verbose_abort support in the built library 799 Feature( 800 name="availability-verbose_abort-missing", 801 when=lambda cfg: BooleanExpression.evaluate( 802 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-15)", 803 cfg.available_features, 804 ), 805 ), 806 # Tests that require std::pmr support in the built library 807 Feature( 808 name="availability-pmr-missing", 809 when=lambda cfg: BooleanExpression.evaluate( 810 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-16)", 811 cfg.available_features, 812 ), 813 ), 814 # Tests that require support for <print> and std::print in <ostream> in the built library. 815 Feature( 816 name="availability-print-missing", 817 when=lambda cfg: BooleanExpression.evaluate( 818 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-18)", 819 cfg.available_features, 820 ), 821 ), 822 # Tests that require time zone database support in the built library 823 Feature( 824 name="availability-tzdb-missing", 825 when=lambda cfg: BooleanExpression.evaluate( 826 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-19)", 827 cfg.available_features, 828 ), 829 ), 830 # Tests that require std::from_chars(floating-point) in the built library 831 Feature( 832 name="availability-fp_from_chars-missing", 833 when=lambda cfg: BooleanExpression.evaluate( 834 "!libcpp-has-no-availability-markup && (stdlib=apple-libc++ && !_target-has-llvm-20)", 835 cfg.available_features, 836 ), 837 ), 838] 839