diff --git a/License.txt b/License.txt index ea9d7675..fc780fd3 100644 --- a/License.txt +++ b/License.txt @@ -98,21 +98,26 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS" AND A -2. compiler_rt +2. compiler_rt and libc++ The compiler_rt library is dual licensed under both the University of Illinois "BSD-Like" license and the MIT license. As a user of this code you may choose to use it under either license. As a contributor, you agree to allow your code to be used under both. +The libc++ library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + Full text of the relevant licenses is included below. -============================================================================= +============================================================================== University of Illinois/NCSA Open Source License -Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT +Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT All rights reserved. @@ -124,72 +129,72 @@ Developed by: http://llvm.org -Permission is hereby granted, free of charge, to any person obtaining a copy of this -software and associated documentation files (the "Software"), to deal with the -Software without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -Software, and to permit persons to whom the Software is furnished to do so, subject -to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: -- Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimers. + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. -- Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimers in the documentation and/or -other materials provided with the distribution. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. -- Neither the names of the LLVM Team, University of Illinois at Urbana-Champaign, -nor the names of its contributors may be used to endorse or romote products derived -from this Software without specific prior written permission. + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS WITH THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. -============================================================================= +============================================================================== -Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT +Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT -Permission is hereby granted, free of charge, to any person obtaining a copy of this -software and associated documentation files (the "Software"), to deal in the Software -without restriction, including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. ============================================================================= Copyrights and Licenses for Third Party Software Distributed with LLVM: ============================================================================= -The LLVM software contains code written by third parties. Such software will have its -own individual LICENSE.TXT file in the directory in which it appears. -This file will describe the copyrights, license, and restrictions which apply to that code. +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. -The disclaimer of warranty in the University of Illinois Open Source License applies to all -code in the LLVM Distribution, and nothing in any of the other licenses gives permission to -use the names of the LLVM Team or the University of Illinois to endorse or promote products -derived from this Software. - -The following pieces of software have additional or alternate copyrights, licenses, and/or -restrictions: - -Program Directory -------- --------- -mach_override lib/interception/mach_override +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + 3. DLmalloc diff --git a/README.md b/README.md index efacc006..7fb387cd 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,11 @@ Contributing ------- See CONTRIBUTING.md for details. +What's New +---------- +Added pre-release libc++ to enable C++11 inside the enclave. +See sdk/tlibcxx/README.sgx for details. + Documentation ------------- - [Intel(R) SGX for Linux\* OS][1] project home page on [01.org](https://01.org) diff --git a/SampleCode/Cxx11SGXDemo/App/App.cpp b/SampleCode/Cxx11SGXDemo/App/App.cpp new file mode 100644 index 00000000..1fa81e34 --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/App/App.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +# include +# include +# define MAX_PATH FILENAME_MAX + +#include "sgx_urts.h" +#include "sgx_uae_service.h" +#include "App.h" +#include "Enclave_u.h" + +/* Global EID shared by multiple threads */ +sgx_enclave_id_t global_eid = 0; + +typedef struct _sgx_errlist_t { + sgx_status_t err; + const char *msg; + const char *sug; /* Suggestion */ +} sgx_errlist_t; + +/* Error code returned by sgx_create_enclave */ +static sgx_errlist_t sgx_errlist[] = { + { + SGX_ERROR_UNEXPECTED, + "Unexpected error occurred.", + NULL + }, + { + SGX_ERROR_INVALID_PARAMETER, + "Invalid parameter.", + NULL + }, + { + SGX_ERROR_OUT_OF_MEMORY, + "Out of memory.", + NULL + }, + { + SGX_ERROR_ENCLAVE_LOST, + "Power transition occurred.", + "Please refer to the sample \"PowerTransition\" for details." + }, + { + SGX_ERROR_INVALID_ENCLAVE, + "Invalid enclave image.", + NULL + }, + { + SGX_ERROR_INVALID_ENCLAVE_ID, + "Invalid enclave identification.", + NULL + }, + { + SGX_ERROR_INVALID_SIGNATURE, + "Invalid enclave signature.", + NULL + }, + { + SGX_ERROR_OUT_OF_EPC, + "Out of EPC memory.", + NULL + }, + { + SGX_ERROR_NO_DEVICE, + "Invalid SGX device.", + "Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards." + }, + { + SGX_ERROR_MEMORY_MAP_CONFLICT, + "Memory map conflicted.", + NULL + }, + { + SGX_ERROR_INVALID_METADATA, + "Invalid enclave metadata.", + NULL + }, + { + SGX_ERROR_DEVICE_BUSY, + "SGX device was busy.", + NULL + }, + { + SGX_ERROR_INVALID_VERSION, + "Enclave version was invalid.", + NULL + }, + { + SGX_ERROR_INVALID_ATTRIBUTE, + "Enclave was not authorized.", + NULL + }, + { + SGX_ERROR_ENCLAVE_FILE_ACCESS, + "Can't open enclave file.", + NULL + }, + { + SGX_ERROR_NDEBUG_ENCLAVE, + "The enclave is signed as product enclave, and can not be created as debuggable enclave.", + NULL + }, +}; + +/* Check error conditions for loading enclave */ +void print_error_message(sgx_status_t ret) +{ + size_t idx = 0; + size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0]; + + for (idx = 0; idx < ttl; idx++) { + if(ret == sgx_errlist[idx].err) { + if(NULL != sgx_errlist[idx].sug) + printf("Info: %s\n", sgx_errlist[idx].sug); + printf("Error: %s\n", sgx_errlist[idx].msg); + break; + } + } + + if (idx == ttl) + printf("Error: Unexpected error occurred.\n"); +} + +/* Initialize the enclave: + * Step 1: try to retrieve the launch token saved by last transaction + * Step 2: call sgx_create_enclave to initialize an enclave instance + * Step 3: save the launch token if it is updated + */ +int initialize_enclave(void) +{ + char token_path[MAX_PATH] = {'\0'}; + sgx_launch_token_t token = {0}; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + int updated = 0; + + /* Step 1: try to retrieve the launch token saved by last transaction + * if there is no token, then create a new one. + */ + /* try to get the token saved in $HOME */ + const char *home_dir = getpwuid(getuid())->pw_dir; + + if (home_dir != NULL && + (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) { + /* compose the token path */ + strncpy(token_path, home_dir, strlen(home_dir)); + strncat(token_path, "/", strlen("/")); + strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1); + } else { + /* if token path is too long or $HOME is NULL */ + strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)); + } + + FILE *fp = fopen(token_path, "rb"); + if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) { + printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path); + } + + if (fp != NULL) { + /* read the token from saved file */ + size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp); + if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) { + /* if token is invalid, clear the buffer */ + memset(&token, 0x0, sizeof(sgx_launch_token_t)); + printf("Warning: Invalid launch token read from \"%s\".\n", token_path); + } + } + /* Step 2: call sgx_create_enclave to initialize an enclave instance */ + /* Debug Support: set 2nd parameter to 1 */ + ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL); + if (ret != SGX_SUCCESS) { + print_error_message(ret); + if (fp != NULL) fclose(fp); + return -1; + } + + /* Step 3: save the launch token if it is updated */ + if (updated == FALSE || fp == NULL) { + /* if the token is not updated, or file handler is invalid, do not perform saving */ + if (fp != NULL) fclose(fp); + return 0; + } + + /* reopen the file with write capablity */ + fp = freopen(token_path, "wb", fp); + if (fp == NULL) return 0; + size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp); + if (write_num != sizeof(sgx_launch_token_t)) + printf("Warning: Failed to save launch token to \"%s\".\n", token_path); + fclose(fp); + return 0; +} + +/* OCall functions */ +void ocall_print_string(const char *str) +{ + /* Proxy/Bridge will check the length and null-terminate + * the input string to prevent buffer overflow. + */ + printf("%s", str); +} + + +/* Application entry */ +int SGX_CDECL main(int argc, char *argv[]) +{ + (void)(argc); + (void)(argv); + + + /* Initialize the enclave */ + if(initialize_enclave() < 0){ + printf("Enter a character before exit ...\n"); + getchar(); + return -1; + } + + + /* Utilize trusted libraries */ + ecall_libcxx_functions(); + + /* Destroy the enclave */ + sgx_destroy_enclave(global_eid); + + printf("Info: Cxx11DemoEnclave successfully returned.\n"); + + //printf("Enter a character before exit ...\n"); + //getchar(); + return 0; +} + diff --git a/SampleCode/Cxx11SGXDemo/App/App.h b/SampleCode/Cxx11SGXDemo/App/App.h new file mode 100644 index 00000000..13d2e961 --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/App/App.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _APP_H_ +#define _APP_H_ + +#include +#include +#include +#include + +#include "sgx_error.h" /* sgx_status_t */ +#include "sgx_eid.h" /* sgx_enclave_id_t */ + +#ifndef TRUE +# define TRUE 1 +#endif + +#ifndef FALSE +# define FALSE 0 +#endif + +#if defined(__GNUC__) +# define TOKEN_FILENAME "enclave.token" +# define ENCLAVE_FILENAME "enclave.signed.so" +#endif + +extern sgx_enclave_id_t global_eid; /* global enclave id */ + +#if defined(__cplusplus) +extern "C" { +#endif + +void ecall_libcxx_functions(void); + + +#if defined(__cplusplus) +} +#endif + +#endif /* !_APP_H_ */ diff --git a/SampleCode/Cxx11SGXDemo/App/TrustedLibrary/Libcxx.cpp b/SampleCode/Cxx11SGXDemo/App/TrustedLibrary/Libcxx.cpp new file mode 100644 index 00000000..a407bd3f --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/App/TrustedLibrary/Libcxx.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include + +#include "../App.h" +#include "Enclave_u.h" +#include + +/* ecall_libcxx_functions: + * Invokes standard C++11 functions. + */ + + //This function is part of mutex demo +void demo_counter_without_mutex() +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_mutex_demo_no_protection(global_eid); + if (ret != SGX_SUCCESS) + abort(); +} + +//This function is part of mutex demo +void demo_counter_mutex() +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_mutex_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); +} + +//This function is used by processing thread of condition variable demo +void demo_cond_var_run() +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_condition_variable_run(global_eid); + if (ret != SGX_SUCCESS) + abort(); +} + +//This function is used by the loader thread of condition variable demo +void demo_cond_var_load() +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + ret = ecall_condition_variable_load(global_eid); + if (ret != SGX_SUCCESS) + abort(); +} + +// Examples for C++11 library and compiler features +void ecall_libcxx_functions(void) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + // Example for lambda function feature: + ret = ecall_lambdas_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for auto feature: + ret = ecall_auto_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for decltype: + ret = ecall_decltype_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for strongly_typed_enum: + ret = ecall_strongly_typed_enum_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for range based for loops: + ret = ecall_range_based_for_loops_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for static_assert: + ret = ecall_static_assert_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for virtual function controls : override, final, default, and delete + ret = ecall_virtual_function_control_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for delegating_constructors: + ret = ecall_delegating_constructors_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for std::function: + ret = ecall_std_function_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for algorithms (std::all_of, std::any_of, std::none_of): + ret = ecall_cxx11_algorithms_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for variadic_templates feature: + ret = ecall_variadic_templates_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for SFINAE: + ret = ecall_SFINAE_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for initializer_list: + ret = ecall_initializer_list_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for rvalue: + ret = ecall_rvalue_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for nullptr: + ret = ecall_nullptr_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for enum class: + ret = ecall_enum_class_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for new container classes (unordered_set, unordered_map, unordered_multiset, and unordered_multimap): + ret = ecall_new_container_classes_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for tuple: + ret = ecall_tuple_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + // Example for shared_ptr: + ret = ecall_shared_ptr_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + // Example for atomic: + ret = ecall_atomic_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + +//The following threads are part of mutex demo + std::thread t1(demo_counter_without_mutex); + std::thread t2(demo_counter_without_mutex); + std::thread t3(demo_counter_without_mutex); + t1.join(); + t2.join(); + t3.join(); + ret = ecall_print_final_value_no_protection(global_eid); + if (ret != SGX_SUCCESS) + abort(); + + + +//The following threads are part of mutex demo + std::thread tm1(demo_counter_mutex); + std::thread tm2(demo_counter_mutex); + std::thread tm3(demo_counter_mutex); + tm1.join(); + tm2.join(); + tm3.join(); + ret = ecall_print_final_value_mutex_demo(global_eid); + if (ret != SGX_SUCCESS) + abort(); + +//The following threads are part of condition variable demo + std::thread th1(demo_cond_var_run); + std::thread th2(demo_cond_var_load); + th2.join(); + th1.join(); + +} + diff --git a/SampleCode/Cxx11SGXDemo/Enclave/Enclave.config.xml b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.config.xml new file mode 100644 index 00000000..a94d12f0 --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.config.xml @@ -0,0 +1,12 @@ + + + 0 + 0 + 0x40000 + 0x100000 + 10 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/SampleCode/Cxx11SGXDemo/Enclave/Enclave.cpp b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.cpp new file mode 100644 index 00000000..a013a31e --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include /* vsnprintf */ + +#include "Enclave.h" +#include "Enclave_t.h" /* print_string */ + +/* + * printf: + * Invokes OCALL to display the enclave buffer to the terminal. + */ +void printf(const char *fmt, ...) +{ + char buf[BUFSIZ] = {'\0'}; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, BUFSIZ, fmt, ap); + va_end(ap); + ocall_print_string(buf); +} diff --git a/SampleCode/Cxx11SGXDemo/Enclave/Enclave.edl b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.edl new file mode 100644 index 00000000..379a8b69 --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.edl @@ -0,0 +1,24 @@ +/* Enclave.edl - Top EDL file. */ + +enclave { + + + /* Import ECALL/OCALL from sub-directory EDLs. + * [from]: specifies the location of EDL file. + * [import]: specifies the functions to import, + * [*]: implies to import all functions. + */ + + from "TrustedLibrary/Libcxx.edl" import *; + from "sgx_tstdc.edl" import sgx_thread_wait_untrusted_event_ocall, sgx_thread_set_untrusted_event_ocall, sgx_thread_setwait_untrusted_events_ocall, sgx_thread_set_multiple_untrusted_events_ocall; + + /* + * ocall_print_string - invokes OCALL to display string buffer inside the enclave. + * [in]: copy the string buffer to App outside. + * [string]: specifies 'str' is a NULL terminated buffer. + */ + untrusted { + void ocall_print_string([in, string] const char *str); + }; + +}; diff --git a/SampleCode/Cxx11SGXDemo/Enclave/Enclave.h b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.h new file mode 100644 index 00000000..3ad6c0b3 --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2016 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _ENCLAVE_H_ +#define _ENCLAVE_H_ + +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +void printf(const char *fmt, ...); + +#if defined(__cplusplus) +} +#endif + +#endif /* !_ENCLAVE_H_ */ diff --git a/SampleCode/Cxx11SGXDemo/Enclave/Enclave.lds b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.lds new file mode 100644 index 00000000..e3d9d0ee --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/Enclave.lds @@ -0,0 +1,9 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + local: + *; +}; diff --git a/SampleCode/Cxx11SGXDemo/Enclave/Enclave_debug.lds b/SampleCode/Cxx11SGXDemo/Enclave/Enclave_debug.lds new file mode 100644 index 00000000..f5f35d5b --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/Enclave_debug.lds @@ -0,0 +1,10 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; diff --git a/SampleCode/Cxx11SGXDemo/Enclave/Enclave_private.pem b/SampleCode/Cxx11SGXDemo/Enclave/Enclave_private.pem new file mode 100644 index 00000000..529d07be --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/Enclave_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ +AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ +ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr +nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b +3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H +ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD +5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW +KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC +1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe +K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z +AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q +ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 +JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 +5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 +wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 +osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm +WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i +Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 +xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd +vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD +Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a +cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC +0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ +gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo +gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t +k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz +Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 +O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 +afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom +e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G +BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv +fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN +t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 +yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp +6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg +WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH +NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= +-----END RSA PRIVATE KEY----- diff --git a/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp b/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp new file mode 100644 index 00000000..afe0c0c4 --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp @@ -0,0 +1,919 @@ +/** +* Copyright(C) 2011-2016 Intel Corporation All Rights Reserved. +* +* The source code, information and material ("Material") contained herein is +* owned by Intel Corporation or its suppliers or licensors, and title to such +* Material remains with Intel Corporation or its suppliers or licensors. The +* Material contains proprietary information of Intel or its suppliers and +* licensors. The Material is protected by worldwide copyright laws and treaty +* provisions. No part of the Material may be used, copied, reproduced, +* modified, published, uploaded, posted, transmitted, distributed or disclosed +* in any way without Intel's prior express written permission. No license +* under any patent, copyright or other intellectual property rights in the +* Material is granted to or conferred upon you, either expressly, by +* implication, inducement, estoppel or otherwise. Any license under such +* intellectual property rights must be express and approved by Intel in +* writing. +* +* *Third Party trademarks are the property of their respective owners. +* +* Unless otherwise agreed by Intel in writing, you may not remove or alter +* this notice or any other notice embedded in Materials by Intel or Intel's +* suppliers or licensors in any way. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../Enclave.h" +#include "Enclave_t.h" + + +// Feature name : Lambda functions +// Feature description : It is used to create a function object that can capture variables in scope. +// Demo description : Shows lambda capture options and a some basic usages. +void ecall_lambdas_demo() +{ + // Lambdas capture options: + int local_var = 0; + + [] { return true; }; // captures nothing + + [&] { return ++local_var; }; // captures all variable by reference + [&local_var] { return ++local_var; }; // captures local_var by reference + [&, local_var] { return local_var; }; // captures all by reference except local_var + + [=] { return local_var; }; // captures all variable by value + [local_var] { return local_var; }; // captures local_var by value + [=, &local_var] { return ++local_var; }; // captures all variable by value except local_var + + // Sample usages for lamdbas: + std::vector< int> v { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + printf("[Lambdas] Initial array using lambdas: { "); + + // Print the elements in an array using lambdas + std::for_each(std::begin(v), std::end(v), [](int elem) { printf("%d ", elem); }); //capture specification + printf("}.\n"); + + // Find the first odd number using lambda as an unary predicate when calling find_if. + auto first_odd_element = std::find_if(std::begin(v), std::end(v), [=](int elem) { return elem % 2 == 1; }); + + if (first_odd_element != std::end(v)) + printf("[Lambdas] First odd element in the array is %d. \n", *first_odd_element); + else + printf("[Lambdas] No odd element found in the array.\n"); + + // Count the even numbers using a lambda function as an unary predicate when calling count_if. + long long number_of_even_elements = std::count_if(std::begin(v), std::end(v), [=](int val) { return val % 2 == 0; }); + printf("[Lambdas] Number of even elements in the array is %lld.\n", number_of_even_elements); + + // Sort the elements of an array using lambdas + std::sort(std::begin(v), std::end(v), [](int e1, int e2) {return e2 < e1; }); + + // Print the elements in an array using lambdas + printf("[Lambdas] Array after sort: { "); + std::for_each(std::begin(v), std::end(v), [](int elem) { printf("%d ", elem); }); + printf("}. \n"); + printf("\n"); // end of demo +} + + +// Feature name : auto +// Feature description : It is used for type deduction +// Demo description : Shows basic usages of auto specifier with different types. + +// Helper function for ecall_auto_demo: +void sample_func_auto_demo() +{ + printf("[auto] Function sample_func_auto_demo is called. \n"); +} + +void ecall_auto_demo() +{ + double local_var = 0.0; + + auto a = 7; // Type of variable a is deduced to be int + printf("[auto] Type of a is int. typeid = %s.\n", typeid(a).name()); + + const auto b1 = local_var, *b2 = &local_var; // auto can be used with modifiers like const or &. + printf("[auto] Type of b1 is const double. typeid = %s.\n", typeid(b1).name()); + printf("[auto] Type of b2 is const double*. typeid = %s.\n", typeid(b2).name()); + (void)b1; + (void)b2; + + auto c = 0, *d = &a; // multiple variable initialization if the deduced type does match + printf("[auto] Type of c is int. typeid = %s.\n", typeid(c).name()); + printf("[auto] Type of d is int*. typeid = %s.\n", typeid(d).name()); + (void)c; + (void)d; + + auto lambda = [] {}; // can be used to define lambdas + printf("[auto] Type of lambda is [] {}. typeid = %s.\n", typeid(lambda).name()); + (void)lambda; + + auto func = sample_func_auto_demo; // can be used to deduce type of function + printf("[auto] Type of func is void(__cdecl*)(void). typeid = %s.\n", typeid(func).name()); + func(); + + printf("\n"); // end of demo +} + +// Feature name : decltype +// Feature description : It is used for type deduction +// Demo description : Shows basic usages of decltype specifier with different types. +void ecall_decltype_demo() +{ + int a = 0 ; + decltype(a) b = 0; // create an element of the same type as another element + printf("[decltype] Type of b is int. typeid = %s.\n", typeid(b).name()); + + double c = 0; + decltype(a + c) sum = a + c; // deduce type of a sum of elements of different types and create an element of that type. + // most usefull in templates. + printf("[decltype] Type of sum is double. typeid = %s.\n", typeid(sum).name()); + (void)sum; + (void)b; + printf("\n"); // end of demo +} + +// Feature name : enum classes +// Feature description : A new type of enum that solves problems found in old enum like : +// unscoping of enum values and the possibility to compare them with int +// Demo description : Shows basic usages of enum classes. +void ecall_strongly_typed_enum_demo() +{ + // In enum class the underlying type can be set. In the case bellow it is char. + enum class DaysOfWeek : char { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }; + + // initialization of variable of type DaysOfWeek + DaysOfWeek random_day = DaysOfWeek::MONDAY; + (void)random_day; + + // In is not mandatory to specify the underlying type. + enum class Weekend { SATURDAY, SUNDAY }; + + // The two enum classes above: days_of_week and weekend ilustrate that it is now possible to have two enum classes with the same values in them. + + // end of demo +} + +// Feature name : Range based for loops +// Feature description : Easy to read way of accessing elements in an container. +// Demo description : Shows basic usage of range based for loop with c array and vector. +void ecall_range_based_for_loops_demo() +{ + char array_of_letters[] = { 'a','b','c','d' }; + std::vector vector_of_letters = { 'a','b','c','d' }; + + printf("[range_based_for_loops] Using range based for loops to print the content of an array: { "); + for (auto elem : array_of_letters) + printf("%c ", elem); + printf("}. \n"); + + printf("[range_based_for_loops] Using range based for loops to print the content of an vector: { "); + for (auto elem : vector_of_letters) + printf("%c ", elem); + printf("}.\n"); + + printf("\n"); // end of demo +} + + +// Feature name : static_assert +// Feature description : It is used to make assertions at compile time. +// Demo description : Shows basic usage of static_assert with compile time operation. +void ecall_static_assert_demo() +{ + static_assert(sizeof(int) < sizeof(double), "Error : sizeof(int) < sizeof(double) "); + const int a = 0; + static_assert(a == 0, "Error: value of a is not 0"); + + // end of demo +} + + +// Feature name : New virtual function controls : override, final, default, and delete +// Feature description : - delete : a deleted function cannot be inherited +// - final : a final function cannot be overrided in the derived class +// - default : intruction to the compiler to generate a default function +// - override : ensures that a virtual function from derived class overrides a function from base +// Demo description : Shows basic usage of new virtual function control. + +/* Helper class for ecall_virtual_function_control_demo.*/ +class Base +{ +public: + + virtual void f_cannot_be_inherited() final {}; + Base(const Base &) = delete; + Base() = default; + virtual void f_must_be_overrided() {}; +}; + +/* Helper class for ecall_virtual_function_control_demo.*/ +class Derived : Base +{ +public: + /* The code bellow in this comment does not compile. + The function cannot be override because it is declared with keyword final in base + virtual double f_cannot_be_inherited() {}; + */ + + /*The keyword override assures that the function overrides a base class member*/ + virtual void f_must_be_overrided() override {}; +}; + +void ecall_virtual_function_control_demo() +{ + // The default constructor will be called generated by the compiler with explicit keyword default + Base a; + // Trying to use the copy contructor will generate code that does not compile because it is deleted + // Base b = a; + + // end of demo +} + +// Feature name : Delegating constructors +// Feature description : A class constructors may have common code which can be delegated to a constructor to avoid code repetion +// Demo description : Shows basic usage of delegating constructors + +// Helper class for ecall_delegating_constructors +class DemoDelegatingConstructors +{ + int a, b, c; +public: + DemoDelegatingConstructors(int param_a, int param_b, int param_c) + { + this->a = param_a; + this->b = param_b; + this->c = param_c; + /*common initialization*/ + switch (c) + { + case 1: + printf("[delegating constructors] Called from DemoDelegatingConstructors(int a, int b). \n"); + break; + case 2: + printf("[delegating constructors] Called from DemoDelegatingConstructors(int a). \n"); + break; + default: + printf("[delegating constructors] Called from DemoDelegatingConstructors(int a, int b, int c).\n"); + break; + } + } + DemoDelegatingConstructors(int param_a, int param_b) : DemoDelegatingConstructors(param_a, param_b, 1) {} + DemoDelegatingConstructors(int param_a) : DemoDelegatingConstructors(param_a, 0, 2) {} +}; + +void ecall_delegating_constructors_demo() +{ + DemoDelegatingConstructors a(1, 2, 3); + DemoDelegatingConstructors b(1, 2); + DemoDelegatingConstructors c(1); + + printf("\n"); // end of demo +} + +// Feature name : std::function +// Feature description : It is used to store and invoke a callable +// Demo description : Shows basic usage of std::function + +// Helper class for ecall_std_function_demo: +void sample_std_function1() +{ + printf("[std_function] calling sample_std_function1\n"); +} + +void ecall_std_function_demo() +{ + // Example with functions + std::function funct = sample_std_function1; + funct(); + + //Example with lambda + std::function funct_lambda = [] { printf("[std_function] calling a lambda function\n"); }; + funct_lambda(); + + printf("\n"); // end of demo +} + +// Feature name : std::all_of, std::any_of, std::none_of +// Feature description : New C++11 algorithms +// Demo description : Shows basic usage of the std::all_of, std::any_of, std::none_of. +void ecall_cxx11_algorithms_demo() +{ + std::vector v = { 0, 1, 2, 3, 4, 5 }; + bool are_all_of = all_of(begin(v), end(v), [](int e) { return e % 2 == 0; }); + printf("[cxx11_algorithms] All elements in { 0 1 2 3 4 5 } are even is %s. \n", are_all_of ? "true" : "false"); + + bool are_any_of = any_of(begin(v), end(v), [](int e) { return e % 2 == 0; }); + printf("[cxx11_algorithms] Some elements in { 0 1 2 3 4 5 } are even is %s. \n", are_any_of ? "true" : "false"); + + bool are_none_of = none_of(begin(v), end(v), [](int e) { return e % 2 == 0; }); + printf("[cxx11_algorithms] Some elements in { 0 1 2 3 4 5 } are even is %s. \n", are_none_of ? "true" : "false"); + + printf("\n"); // end of demo +} + + +// Feature name : variadic templates +// Feature description : Templates that can have multiple arguments +// Demo description : Shows basic usage of variadic templates + +// Helper template for ecall_variadic_templates_demo: +template +T sum(T elem) +{ + return elem; +} + +template +T sum(T elem1, T elem2, Args... args) +{ + return elem1 + elem2 + sum(args...); +} + +void ecall_variadic_templates_demo() +{ + int computed_sum = sum(1, 2, 3, 4, 5); + printf("[variadic_templates] The sum of paramters (1, 2, 3, 4, 5) is %d. \n", computed_sum); + printf("\n"); // end of demo +} + +// Feature name : Substitution failure is not an error (SFINAE) +// Feature description : Describes the case where a substitution error in templates does not cause errors +// Demo description : Shows basic usage of SFINAE + +/*first candidate for substitution*/ +template void f(typename T::A*) { printf("[sfinae] First candidate for substitution is matched.\n"); }; + +/*second candidate for substitution*/ +template void f(T) { printf("[sfinae] Second candidate for substitution is matched.\n"); } + +void ecall_SFINAE_demo() +{ + f(0x0); // even if the first canditate substition will fail, the second one will pass + printf("\n"); // end of demo +} + +//Feature name : Initializer lists +//Feature description : An object of type std::initializer_list is a lightweight proxy object that provides access to an array of objects of type const T. +//Demo description : Demonstrates the usage of initializer list in the constructor of an object in enclave. +class Number +{ +public: + Number(const std::initializer_list &v) { + for (auto i : v) { + elements.push_back(i); + } + } + + void print_elements() { + printf("[initializer_list] The elements of the vector are:"); + for (auto item : elements) { + printf(" %d", item); + } + printf(".\n"); + } +private: + std::vector elements; +}; + +void ecall_initializer_list_demo() +{ + printf("[initializer_list] Using initializer list in the constructor. \n"); + Number m = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + m.print_elements(); + + printf("\n"); //end of demo +} + + +// Feature name : Rvalue references and move semantics; +// Feature description : They are used for memory usage optimazation by eliminating copy operations +// Demo description : Shows basic usage of rvalue, move constructor, and move operator + +// Helper class for ecall_rvalue_demo +class DemoBuffer +{ +public: + unsigned int size = 100; + char *buffer; + + DemoBuffer(int param_size) + { + this->size = param_size; + buffer = new char[size]; + printf("[rvalue] Called constructor : DemoBuffer(int size).\n"); + } + + // A typical copy constructor needs to alocate memory for a new copy + // Copying an big array is an expensive operation + DemoBuffer(const DemoBuffer & rhs) + { + this->size = rhs.size; + buffer = new char[rhs.size]; + memcpy(buffer, rhs.buffer, size); + printf("[rvalue] Called copy constructor : DemoBuffer(const DemoBuffer & rhs).\n"); + } + + // A typical move constructor can reuse the memory pointed by the buffer + DemoBuffer(DemoBuffer && rhs) + { + buffer = rhs.buffer; + size = rhs.size; + // reset state of rhs + rhs.buffer = NULL; + rhs.size = 0; + printf("[rvalue] Called move constructor : DemoBuffer(DemoBuffer && rhs).\n"); + } + ~DemoBuffer() + { + delete buffer; + } + +}; + +// Helper class for ecall_rvalue_demo +DemoBuffer foobar(int a) +{ + DemoBuffer x(100); + DemoBuffer y(100); + + if (a > 0) + return x; + else + return y; +} +void ecall_rvalue_demo() +{ + // This will call the constructor + printf("[rvalue] DemoBuffer a(100).\n"); + DemoBuffer a(100); + + printf("[rvalue] DemoBuffer foobar(100). \n"); + // Initializing variable d using a temporary object will result in a call to move constructor + // This is usefull because it reduces the memory cost of the operation. + DemoBuffer d(foobar(100)); + + // This will call the copy constructor. State of a will not change. + printf("[rvalue] DemoBuffer b(a).\n"); + DemoBuffer b(a); + + printf("[rvalue] DemoBuffer c(std::move(a)).\n"); + // explicitly cast a to an rvalue so that c will be created using move constructor. + // State of a is going to be reseted. + DemoBuffer c(std::move(a)); + + printf("\n"); // end of demo +} + +// Feature name : Nullptr +// Feature description : Resolves the issues of converting NULL to integral types +// Demo description : Shows basic usage of nullptr + +// overload candidate 1 +void nullptr_overload_candidate(int i) { + (void)i; + printf("[nullptr] called void nullptr_overload_candidate(int i).\n"); +} + +// overload candidate 2 +void nullptr_overload_candidate(int* ptr) { + (void)ptr; + printf("[nullptr] called void nullptr_overload_candidate(int* ptr).\n"); +} + +template +void Fwd(F f, A a) +{ + f(a); +} + +void g(int* i) +{ + (void)i; + printf("[nullptr] Function %s called\n", __FUNCTION__); +} + +// Feature name : +// Feature description : +// Demo description : +void ecall_nullptr_demo() +{ + // NULL can be converted to integral types() like int and will call overload candidate 1 + nullptr_overload_candidate(NULL); + + // nullptr can't be converted to integral types() like int and will call overload candidate 2 + nullptr_overload_candidate(nullptr); + + g(NULL); // Fine + g(0); // Fine + Fwd(g, nullptr); // Fine + //Fwd(g, NULL); // ERROR: No function g(int) + + printf("\n"); // end of demo +} + +// Feature name : Scoped enums +// Feature description : +// Demo description : +enum class Color { orange, brown, green = 30, blue, red }; + +void ecall_enum_class_demo() +{ + int n = 0; + Color color1 = Color::brown; + switch (color1) + { + case Color::orange: printf("[enum class] orange"); break; + case Color::brown: printf("[enum class] brown"); break; + case Color::green: printf("[enum class] green"); break; + case Color::blue: printf("[enum class] blue"); break; + case Color::red: printf("[enum class] red"); break; + } + // n = color1; // Not allowed: no scoped enum to int conversion + n = static_cast(color1); // OK, n = 1 + printf(" - int = %d\n", n); + + Color color2 = Color::red; + switch (color2) + { + case Color::orange: printf("[enum class] orange"); break; + case Color::brown: printf("[enum class] brown"); break; + case Color::green: printf("[enum class] green"); break; + case Color::blue: printf("[enum class] blue"); break; + case Color::red: printf("[enum class] red"); break; + } + n = static_cast(color2); // OK, n = 32 + printf(" - int = %d\n", n); + + Color color3 = Color::green; + switch (color3) + { + case Color::orange: printf("[enum class] orange"); break; + case Color::brown: printf("[enum class] brown"); break; + case Color::green: printf("[enum class] green"); break; + case Color::blue: printf("[enum class] blue"); break; + case Color::red: printf("[enum class] red"); break; + } + n = static_cast(color3); // OK, n = 30 + printf(" - int = %d\n", n); + printf("\n"); +} + +// Feature name : new container classes +// Feature description : unordered_set, unordered_map, unordered_multiset, and unordered_multimap +// Demo description : Shows basic usage of new container classes +void ecall_new_container_classes_demo() +{ + // unordered_set + // container used for fast acces that groups elements in buckets based on their hash + + std::unordered_set set_of_numbers = { 0, 1, 2, 3, 4, 5 }; + const int searchVal = 3; + std::unordered_set::const_iterator got = set_of_numbers.find(searchVal); + + if (got == set_of_numbers.end()) + printf("[new_container_classes] unordered_set { 0, 1, 2, 3, 4, 5} has value 3.\n"); + else + printf("[new_container_classes] unordered_set { 0, 1, 2, 3, 4, 5} it does not have value 3.\n"); + + // unordered_multiset + // container used for fast acces that groups non unique elements in buckets based on their hash + std::unordered_multiset multiset_of_numbers = { 0, 1, 2, 3, 3, 3 }; + printf("[new_container_classes] multiset_set { 0, 1, 2, 3, 3, 3} has %d elements with value %d.\n", + (int)multiset_of_numbers.count(searchVal), searchVal); + + // unordered_map + std::unordered_map grades{ { "A", 10 },{ "B", 8 },{ "C", 7 },{ "D", 5 },{ "E", 3 } }; + printf("[new_container_classes] unordered_map elements: {"); + for (auto pair : grades) { + printf("[%s %d] ", pair.first.c_str(), pair.second); + } + + printf("}.\n"); + + // unordered_multimap + std::unordered_multimap multimap_grades{ { "A", 10 },{ "B", 8 },{ "B", 7 },{ "E", 5 },{ "E", 3 },{ "E",1 } }; + + printf("[new_container_classes] unordered_multimap elements: {"); + for (auto pair : multimap_grades) { + printf("[%s %d] ", pair.first.c_str(), pair.second); + } + printf("}.\n"); + + printf("\n"); // end of demo +} + +// Feature name : Tuple +// Feature description : Objects that pack elements of multiple types which can be accessed by index +// Demo description : Shows basic usage of tuple: creation and access +void ecall_tuple_demo() +{ + // Create tuple using std::make_tuple + char array_of_letters[4] = {'A','B','C','D'}; + std::vector vector_of_letters = { 'A','B','C','D' }; + std::map map_of_letters = { {'B','b' } }; + + // Creating a tuple using a tuple constructor + std::tuple tuple_sample_with_constructor(42, "Sample tuple"); + (void)tuple_sample_with_constructor; + + // Creating a tuple using std::make_tuple + auto tuple_sample = std::make_tuple("", 1, 7.9, vector_of_letters, array_of_letters, map_of_letters); + + // Access the elements in tupleSample using std::get + printf("[tuple] show first element in TupleSample: %s. \n", std::get<0>(tuple_sample)); + printf("[tuple] show second element in TupleSample: %d. \n", std::get<1>(tuple_sample)); + printf("[tuple] show third element in TupleSample: %f. \n", std::get<2>(tuple_sample)); + + // Getting vector from a tuple + std::vector temp_vector = std::get<3>(tuple_sample); + (void)temp_vector; + + // Getting array from a tuple + int first_elem_of_array = std::get<4>(tuple_sample)[0]; + (void)first_elem_of_array; + + // Getting map from a tuple + std::map temp_map = std::get<5>(tuple_sample); + (void)temp_map; + printf("\n"); // end of demo +} + +// Feature name : new smart pointer +// Feature description : shared_ptr and unique_ptr +// Demo decription : Shows basic usage of smart pointers +// Helper class for ecall_shared_ptr_demo +class DemoSmartPtr +{ + std::string smartPointerType; +public: + DemoSmartPtr(std::string param_smartPointerType) + { + printf("[smart_ptr] In construct of object demo_smart_ptr using %s. \n", param_smartPointerType.c_str()); + this->smartPointerType = param_smartPointerType; + } + ~DemoSmartPtr() + { + printf("[smart_ptr] In deconstructor of object demo_smart_ptr using %s. \n", smartPointerType.c_str()); + } +}; + +void ecall_shared_ptr_demo() +{ + // std::shared_ptr is smart pointer that takes ownership of an object using a pointer + // The object is freed when the last smart_pointer does not point to it. + + // Creating a shared pointer using std::make_shared + auto shared_ptr = std::make_shared("smart_ptr."); // The constructor of DemoSmartPtr will be called here + + printf("[smart_ptr] shared_ptr reference count = %ld. \n", shared_ptr.use_count()); + auto shared_ptr2 = shared_ptr; + printf("[smart_ptr] shared_ptr reference count = %ld incresead after creating another shared pointer.\n", shared_ptr.use_count()); + shared_ptr2.reset(); + printf("[smart_ptr] shared_ptr reference count = %ld decresead after calling releasing ownership. \n", shared_ptr.use_count()); + + // std::unique_ptr is smart pointer that takes ownership of an object using a pointer + // it is different from smart_ptr in the sense that only one unique_ptr can take ownership + + std::unique_ptr unique_ptr(new DemoSmartPtr("unique_ptr")); + // When going out of scope both shared_ptr and unique_ptr release the objects they own + + // end of demo +} + +#if defined(__INTEL_COMPILER) +//Feature name : atomic +//Feature description: The atomic library provides components for fine-grained atomic operations allowing for lockless concurrent programming. +// Each atomic operation is indivisible with regards to any other atomic operation that involves the same object. +// Atomic objects are free of data races. +//Demo description : Demonstrates the usage of atomic types, objects and functions in enclave. +void ecall_atomic_demo() +{ + printf("[atomic] Atomic types, objects and functions demo.\n"); + + printf("[atomic_store] Defining an atomic_char object with an initial value of 5.\n"); + std::atomic_char atc(5); + printf("[atomic_store] The current value stored in the atomic object is: %d\n", atc.load()); + printf("[atomic_store] Replacing the value of the atomic object with a non-atomic value of 3.\n"); + std::atomic_store(&atc, 3); + printf("[atomic_store] The new value of the atomic object is: %d.\n", atc.load()); + + printf("\n"); + + printf("[atomic_store_explicit] Defining an atomic_short object with an initial value of 5.\n"); + std::atomic_short ats(5); + printf("[atomic_store_explicit] The current value stored in the atomic object is: %d.\n", ats.load()); + printf("[atomic_store_explicit] Replacing the value of the atomic object with a non-atomic value of 3.\n"); + std::atomic_store_explicit(&ats, 3, std::memory_order_seq_cst); + printf("[atomic_store] The new value of the atomic object is: %d.\n", ats.load()); + + printf("\n"); + + printf("[atomic_load] Defining an atomic_int object with an initial value of 4.\n"); + std::atomic_int ati1(4); + printf("[atomic_load] Obtaining the value of the atomic object and saving it in a int variable.\n"); + int val = std::atomic_load(&ati1); + printf("[atomic_load] The obtained value is %d.\n", val); + + printf("\n"); + + printf("[atomic_load_explicit] Defining an atomic_int object with an initial value of 2.\n"); + std::atomic_int ati2(2); + printf("[atomic_load_explicit] Obtaining the value of the atomic object and saving it in a int variable.\n"); + int val1 = std::atomic_load_explicit(&ati2, std::memory_order_seq_cst); + printf("[atomic_load_explicit] The obtained value is %d.\n", val1); + + printf("\n"); + + printf("[atomic_fetch_add] Defining an atomic_int object with an initial value of 7.\n"); + std::atomic_int ati(7); + printf("[atomic_fetch_add] The current value stored in the atomic object is: %d.\n", ati.load()); + printf("[atomic_fetch_add] Adding a non-atomic value of 8 to the atomic object.\n"); + std::atomic_fetch_add(&ati, 8); + printf("[atomic_fetch_add] The new value of the atomic object is: %d.\n", ati.load()); + + printf("\n"); + + printf("[atomic_fetch_add_explicit] Defining an atomic_uint object with an initial value of 7.\n"); + std::atomic_uint atui(7); + printf("[atomic_fetch_add_explicit] The current value stored in the atomic object is: %u.\n", atui.load()); + printf("[atomic_fetch_add_explicit] Adding a non-atomic value of 8 to the atomic object.\n"); + std::atomic_fetch_add_explicit(&atui, 8, std::memory_order_seq_cst); + printf("[atomic_fetch_add_explicit] The new value of the atomic object is: %u.\n", atui.load()); + + printf("\n"); + + printf("[atomic_fetch_sub] Defining an atomic_long object with an initial value of 20.\n"); + std::atomic_long atl(20); + printf("[atomic_fetch_sub] The current value stored in the atomic object is: %ld.\n", atl.load()); + printf("[atomic_fetch_sub] Substracting a non-atomic value of 8 from the value of the atomic object.\n"); + std::atomic_fetch_sub(&atl, 8); + printf("[atomic_fetch_sub] The new value of the atomic object is: %ld.\n", atl.load()); + + printf("\n"); + + printf("[atomic_fetch_sub_explicit] Defining an atomic_llong object with an initial value of 20.\n"); + std::atomic_llong atll(20); + printf("[atomic_fetch_sub_explicit] The current value stored in the atomic object is: %lld.\n", atll.load()); + printf("[atomic_fetch_sub_explicit] Adding a non-atomic value of 8 to the atomic object.\n"); + std::atomic_fetch_sub_explicit(&atll, 8, std::memory_order_seq_cst); + printf("[atomic_fetch_sub_explicit] The new value of the atomic object is: %lld.\n", atll.load()); + + printf("\n"); // end of demo +} +#else + void ecall_atomic_demo() {} +#endif /*defined(__INTEL_COMPILER)*/ + +//Feature name : mutex +//Feature description : The mutex class is a synchronization primitive that can be used to protect shared data +// from being simultaneously accessed by multiple threads. +//Demo description : Demonstrates mutex protection when incrementing values in multiple threads. + +//Structure used in mutex demo to show the behavior without using a mutex +struct CounterWithoutMutex { + int value; + + CounterWithoutMutex() : value(0) {} + + void increment() { + ++value; + } +}; + +CounterWithoutMutex counter_without_protection; + +//E-call used by mutex demo to perform the incrementation using a counter without mutex protection +void ecall_mutex_demo_no_protection() +{ + for (int i = 0; i < 100000; ++i) { + counter_without_protection.increment(); + } +} + +//E-call used by mutex demo to get the final value of the counter from enclave +void ecall_print_final_value_no_protection() +{ + printf("[mutex] Incrementing values in three threads without mutex protection, using a 100000 times loop. \n[mutex]Expected value is 300000. The final value is %d.\n", counter_without_protection.value); +} + + +//Structure used in mutex demo +struct CounterProtectedByMutex { + std::mutex mutex; + int value; + + CounterProtectedByMutex() : value(0) {} + + void increment() { + //locking the mutex to avoid simultaneous incrementation in different threads + mutex.lock(); + ++value; + //unlocking the mutex + mutex.unlock(); + } +}; + +CounterProtectedByMutex counter_with_protection; + +//E-call used by mutex demo to perform the actual incrementation +void ecall_mutex_demo() +{ + for (int i = 0; i < 100000; ++i) { + counter_with_protection.increment(); + } +} + +//E-call used by mutex demo to get the final value of the counter from enclave +void ecall_print_final_value_mutex_demo() +{ + printf("[mutex] Mutex protection when incrementing a value in 3 threads, using a 100000 times loop. \n[mutex]Expected value is 300000. The final value is %d.\n", counter_with_protection.value); +} + +#if defined(__INTEL_COMPILER) +//Feature name : condition_variable +//Feature description: The condition_variable class is a synchronization primitive that can be used to block a thread, +// or multiple threads at the same time, until another thread both modifies a shared variable (the condition), +// and notifies the condition_variable. +//Demo description : Demonstrates condition_variable usage in a two threads environment. One thread is used for loading the data and +// the other processes the loaded data. The thread for processing the data waits untill the data is loaded in the +// other thread and gets notified when loading is completed. + +//This class is used by condition variable demo +class DemoConditionVariable +{ + std::mutex mtx; + std::condition_variable cond_var; + bool data_loaded; +public: + DemoConditionVariable() + { + data_loaded = false; + } + void load_data() + { + //Simulating loading of the data + printf("[condition_variable] Loading Data...\n"); + { + // Locking the data structure + std::lock_guard guard(mtx); + // Setting the flag to true to signal load data completion + data_loaded = true; + } + // Notify to unblock the waiting thread + cond_var.notify_one(); + } + bool is_data_loaded() + { + return data_loaded; + } + void main_task() + { + printf("\n"); + printf("[condition_variable] Running condition variable demo.\n"); + + // Acquire the lock + std::unique_lock lck(mtx); + + printf("[condition_variable] Waiting for the data to be loaded in the other thread.\n"); + cond_var.wait(lck, std::bind(&DemoConditionVariable::is_data_loaded, this)); + printf("[condition_variable] Processing the loaded data.\n"); + printf("[condition_variable] Done.\n"); + } +}; + + +DemoConditionVariable app; + +//E-call used by condition_variable demo - processing thread + +void ecall_condition_variable_run() +{ + app.main_task(); +} + +//E-call used by condifion_variable demo - loader thread +void ecall_condition_variable_load() +{ + app.load_data(); +} +#else + void ecall_condition_variable_run() {} + void ecall_condition_variable_load() {} +#endif diff --git a/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.edl b/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.edl new file mode 100644 index 00000000..88ac6cc9 --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.edl @@ -0,0 +1,39 @@ +/* Libcxx.edl - EDL sample for trusted C++ library. */ + +enclave { + + /* + * A subset of the C++03 standard is supported. + */ + + trusted { + + public void ecall_lambdas_demo(void); + public void ecall_auto_demo(void); + public void ecall_decltype_demo(void); + public void ecall_strongly_typed_enum_demo(void); + public void ecall_range_based_for_loops_demo(void); + public void ecall_static_assert_demo(void); + public void ecall_virtual_function_control_demo(void); + public void ecall_delegating_constructors_demo(void); + public void ecall_std_function_demo(void); + public void ecall_cxx11_algorithms_demo(void); + public void ecall_variadic_templates_demo(void); + public void ecall_SFINAE_demo(void); + public void ecall_initializer_list_demo(void); + public void ecall_rvalue_demo(void); + public void ecall_nullptr_demo(void); + public void ecall_enum_class_demo(void); + public void ecall_new_container_classes_demo(void); + public void ecall_tuple_demo(void); + public void ecall_shared_ptr_demo(void); + public void ecall_atomic_demo(void); + public void ecall_mutex_demo(void); + public void ecall_print_final_value_mutex_demo(void); + public void ecall_mutex_demo_no_protection(void); + public void ecall_print_final_value_no_protection(void); + public void ecall_condition_variable_run(void); + public void ecall_condition_variable_load(void); + + }; +}; diff --git a/SampleCode/Cxx11SGXDemo/Makefile b/SampleCode/Cxx11SGXDemo/Makefile new file mode 100644 index 00000000..8b9e768c --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/Makefile @@ -0,0 +1,249 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +######## SGX SDK Settings ######## + +SGX_SDK ?= /opt/intel/sgxsdk +SGX_MODE ?= HW +SGX_ARCH ?= x64 +SGX_DEBUG ?= 1 + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g +else + SGX_COMMON_CFLAGS += -O2 +endif + +######## App Settings ######## + +ifneq ($(SGX_MODE), HW) + Urts_Library_Name := sgx_urts_sim +else + Urts_Library_Name := sgx_urts +endif + +App_Cpp_Files := App/App.cpp $(wildcard App/TrustedLibrary/*.cpp) +App_Include_Paths := -IInclude -IApp -I$(SGX_SDK)/include + +App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 +App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_uae_service_sim +else + App_Link_Flags += -lsgx_uae_service +endif + +App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) + +App_Name := app + +######## Enclave Settings ######## + +Enclave_Version_Script := Enclave/Enclave_debug.lds +ifeq ($(SGX_MODE), HW) +ifneq ($(SGX_DEBUG), 1) +ifneq ($(SGX_PRERELEASE), 1) + # Choose to use 'Enclave.lds' for HW release mode + Enclave_Version_Script = Enclave/Enclave.lds +endif +endif +endif + +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif +Crypto_Library_Name := sgx_tcrypto + +Enclave_Cpp_Files := Enclave/Enclave.cpp $(wildcard Enclave/TrustedLibrary/*.cpp) +Enclave_Include_Paths := -IInclude -IEnclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/libcxx -I$(SGX_SDK)/include/tlibc + +Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths) +Enclave_Cpp_Flags := $(Enclave_C_Flags) -nostdinc++ -std=c++11 + +# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries: +# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options, +# so that the whole content of trts is included in the enclave. +# 2. For other libraries, you just need to pull the required symbols. +# Use `--start-group' and `--end-group' to link these libraries. +# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options. +# Otherwise, you may get some undesirable errors. +Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 \ + -Wl,--version-script=$(Enclave_Version_Script) + +Enclave_Cpp_Objects := $(Enclave_Cpp_Files:.cpp=.o) + +Enclave_Name := enclave.so +Signed_Enclave_Name := enclave.signed.so +Enclave_Config_File := Enclave/Enclave.config.xml + +ifeq ($(SGX_MODE), HW) +ifeq ($(SGX_DEBUG), 1) + Build_Mode = HW_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = HW_PRERELEASE +else + Build_Mode = HW_RELEASE +endif +else +ifeq ($(SGX_DEBUG), 1) + Build_Mode = SIM_DEBUG +else ifeq ($(SGX_PRERELEASE), 1) + Build_Mode = SIM_PRERELEASE +else + Build_Mode = SIM_RELEASE +endif +endif + + +.PHONY: all run + +ifeq ($(Build_Mode), HW_RELEASE) +all: $(App_Name) $(Enclave_Name) + @echo "The project has been built in release hardware mode." + @echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave." + @echo "To sign the enclave use the command:" + @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)" + @echo "You can also sign the enclave using an external signing tool." + @echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW." +else +all: $(App_Name) $(Signed_Enclave_Name) +ifeq ($(Build_Mode), HW_DEBUG) + @echo "The project has been built in debug hardware mode." +else ifeq ($(Build_Mode), SIM_DEBUG) + @echo "The project has been built in debug simulation mode." +else ifeq ($(Build_Mode), HW_PRERELEASE) + @echo "The project has been built in pre-release hardware mode." +else ifeq ($(Build_Mode), SIM_PRERELEASE) + @echo "The project has been built in pre-release simulation mode." +else + @echo "The project has been built in release simulation mode." +endif +endif + +run: all +ifneq ($(Build_Mode), HW_RELEASE) + @$(CURDIR)/$(App_Name) + @echo "RUN => $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]" +endif + +######## App Objects ######## + +App/Enclave_u.c: $(SGX_EDGER8R) Enclave/Enclave.edl + @cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +App/Enclave_u.o: App/Enclave_u.c + @$(CC) $(App_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +App/%.o: App/%.cpp + @$(CXX) $(App_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(App_Name): App/Enclave_u.o $(App_Cpp_Objects) + @$(CXX) $^ -o $@ $(App_Link_Flags) + @echo "LINK => $@" + + +######## Enclave Objects ######## + +Enclave/Enclave_t.c: $(SGX_EDGER8R) Enclave/Enclave.edl + @cd Enclave && $(SGX_EDGER8R) --trusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include + @echo "GEN => $@" + +Enclave/Enclave_t.o: Enclave/Enclave_t.c + @$(CC) $(Enclave_C_Flags) -c $< -o $@ + @echo "CC <= $<" + +Enclave/%.o: Enclave/%.cpp + @$(CXX) $(Enclave_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) + @$(CXX) $^ -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Signed_Enclave_Name): $(Enclave_Name) + @$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) + @echo "SIGN => $@" + +.PHONY: clean + +clean: + @rm -f $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.* diff --git a/SampleCode/Cxx11SGXDemo/README.txt b/SampleCode/Cxx11SGXDemo/README.txt new file mode 100644 index 00000000..77924acb --- /dev/null +++ b/SampleCode/Cxx11SGXDemo/README.txt @@ -0,0 +1,44 @@ +----------------------- +Purpose of Cxx11SGXDemo +----------------------- + +The project demonstrates serveral C++11 features inside the Enclave: +- lambda expressions; +- rvalue references and move semantics; +- automatic type deduction with auto and decltype; +- nullptr type; +- strongly typed enum classes; +- Range-based for statements; +- static_assert keyword for compile-time assertion; +- initializer lists and uniform initialization syntax; +- New virtual function controls: override, final, default, and delete; +- delegating constructors; +- new container classes (unordered_set, unordered_map, unordered_multiset, and unordered_multimap); +- tuple class; +- function object wrapper; +- atomic, mutexes, condition_variables; +- new smart pointer classes: shared_ptr, unique_ptr; +- new c++ algorithms: all_off, any_of, none_of; +- variadic templates; +- SFINAE; + +--------------------------------------------- +How to Build/Execute the C++11 sample program +--------------------------------------------- +1. Install Intel(R) SGX SDK for Linux* OS +2. Build the project with the prepared Makefile: + a. Hardware Mode, Debug build: + $ make + b. Hardware Mode, Pre-release build: + $ make SGX_PRERELEASE=1 SGX_DEBUG=0 + c. Hardware Mode, Release build: + $ make SGX_DEBUG=0 + d. Simulation Mode, Debug build: + $ make SGX_MODE=SIM + e. Simulation Mode, Pre-release build: + $ make SGX_MODE=SIM SGX_PRERELEASE=1 SGX_DEBUG=0 + f. Simulation Mode, Release build: + $ make SGX_MODE=SIM SGX_DEBUG=0 +3. Execute the binary directly: + $ ./app +4. Remember to "make clean" before switching build mode diff --git a/linux/installer/common/sdk/BOMs/sdk_base.txt b/linux/installer/common/sdk/BOMs/sdk_base.txt index 4cb36ef4..0b80cf79 100644 --- a/linux/installer/common/sdk/BOMs/sdk_base.txt +++ b/linux/installer/common/sdk/BOMs/sdk_base.txt @@ -165,6 +165,20 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner /SampleCode/SampleEnclave/Makefile /package/SampleCode/SampleEnclave/Makefile 0 main STP /SampleCode/SampleEnclave/.project /package/SampleCode/SampleEnclave/.project 0 main STP /SampleCode/SampleEnclave/README.txt /package/SampleCode/SampleEnclave/README.txt 0 main STP +/SampleCode/Cxx11SGXDemo/App/App.cpp /package/SampleCode/Cxx11SGXDemo/App/App.cpp 0 main STP +/SampleCode/Cxx11SGXDemo/App/App.h /package/SampleCode/Cxx11SGXDemo/App/App.h 0 main STP +/SampleCode/Cxx11SGXDemo/App/TrustedLibrary/Libcxx.cpp /package/SampleCode/Cxx11SGXDemo/App/TrustedLibrary/Libcxx.cpp 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/Enclave.config.xml /package/SampleCode/Cxx11SGXDemo/Enclave/Enclave.config.xml 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/Enclave.cpp /package/SampleCode/Cxx11SGXDemo/Enclave/Enclave.cpp 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/Enclave.edl /package/SampleCode/Cxx11SGXDemo/Enclave/Enclave.edl 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/Enclave.h /package/SampleCode/Cxx11SGXDemo/Enclave/Enclave.h 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/Enclave_debug.lds /package/SampleCode/Cxx11SGXDemo/Enclave/Enclave_debug.lds 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/Enclave.lds /package/SampleCode/Cxx11SGXDemo/Enclave/Enclave.lds 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/Enclave_private.pem /package/SampleCode/Cxx11SGXDemo/Enclave/Enclave_private.pem 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp /package/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.cpp 0 main STP +/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.edl /package/SampleCode/Cxx11SGXDemo/Enclave/TrustedLibrary/Libcxx.edl 0 main STP +/SampleCode/Cxx11SGXDemo/Makefile /package/SampleCode/Cxx11SGXDemo/Makefile 0 main STP +/SampleCode/Cxx11SGXDemo/README.txt /package/SampleCode/Cxx11SGXDemo/README.txt 0 main STP /sdk/debugger_interface/linux/se_ptrace.c /package/ptrace/se_ptrace.c 0 main STP /sdk/sample_libcrypto/sample_libcrypto.h /package/SampleCode/RemoteAttestation/sample_libcrypto/sample_libcrypto.h 0 main STP /sdk/tlibstdcxx/stlport/algorithm /package/include/stlport/algorithm 0 main STP @@ -448,3 +462,152 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner /sdk/tlibstdcxx/stlport/vector /package/include/stlport/vector 0 main STP /sdk/tlibstdcxx/stlport/wchar.h /package/include/stlport/wchar.h 0 main STP /sdk/tlibstdcxx/stlport/wctype.h /package/include/stlport/wctype.h 0 main STP +/sdk/tlibcxx/include/algorithm /package/include/libcxx/algorithm 0 main STP +/sdk/tlibcxx/include/array /package/include/libcxx/array 0 main STP +/sdk/tlibcxx/include/atomic /package/include/libcxx/atomic 0 main STP +/sdk/tlibcxx/include/__bit_reference /package/include/libcxx/__bit_reference 0 main STP +/sdk/tlibcxx/include/bitset /package/include/libcxx/bitset 0 main STP +/sdk/tlibcxx/include/cassert /package/include/libcxx/cassert 0 main STP +/sdk/tlibcxx/include/ccomplex /package/include/libcxx/ccomplex 0 main STP +/sdk/tlibcxx/include/cctype /package/include/libcxx/cctype 0 main STP +/sdk/tlibcxx/include/cerrno /package/include/libcxx/cerrno 0 main STP +/sdk/tlibcxx/include/cfenv /package/include/libcxx/cfenv 0 main STP +/sdk/tlibcxx/include/cfloat /package/include/libcxx/cfloat 0 main STP +/sdk/tlibcxx/include/chrono /package/include/libcxx/chrono 0 main STP +/sdk/tlibcxx/include/cinttypes /package/include/libcxx/cinttypes 0 main STP +/sdk/tlibcxx/include/ciso646 /package/include/libcxx/ciso646 0 main STP +/sdk/tlibcxx/include/climits /package/include/libcxx/climits 0 main STP +/sdk/tlibcxx/include/clocale /package/include/libcxx/clocale 0 main STP +/sdk/tlibcxx/include/cmath /package/include/libcxx/cmath 0 main STP +/sdk/tlibcxx/include/codecvt /package/include/libcxx/codecvt 0 main STP +/sdk/tlibcxx/include/complex /package/include/libcxx/complex 0 main STP +/sdk/tlibcxx/include/complex.h /package/include/libcxx/complex.h 0 main STP +/sdk/tlibcxx/include/condition_variable /package/include/libcxx/condition_variable 0 main STP +/sdk/tlibcxx/include/__config /package/include/libcxx/__config 0 main STP +/sdk/tlibcxx/include/csetjmp /package/include/libcxx/csetjmp 0 main STP +/sdk/tlibcxx/include/csignal /package/include/libcxx/csignal 0 main STP +/sdk/tlibcxx/include/cstdarg /package/include/libcxx/cstdarg 0 main STP +/sdk/tlibcxx/include/cstdbool /package/include/libcxx/cstdbool 0 main STP +/sdk/tlibcxx/include/cstddef /package/include/libcxx/cstddef 0 main STP +/sdk/tlibcxx/include/cstdint /package/include/libcxx/cstdint 0 main STP +/sdk/tlibcxx/include/cstdio /package/include/libcxx/cstdio 0 main STP +/sdk/tlibcxx/include/cstdlib /package/include/libcxx/cstdlib 0 main STP +/sdk/tlibcxx/include/cstring /package/include/libcxx/cstring 0 main STP +/sdk/tlibcxx/include/ctgmath /package/include/libcxx/ctgmath 0 main STP +/sdk/tlibcxx/include/ctime /package/include/libcxx/ctime 0 main STP +/sdk/tlibcxx/include/ctype.h /package/include/libcxx/ctype.h 0 main STP +/sdk/tlibcxx/include/cwchar /package/include/libcxx/cwchar 0 main STP +/sdk/tlibcxx/include/cwctype /package/include/libcxx/cwctype 0 main STP +/sdk/tlibcxx/include/__debug /package/include/libcxx/__debug 0 main STP +/sdk/tlibcxx/include/deque /package/include/libcxx/deque 0 main STP +/sdk/tlibcxx/include/errno.h /package/include/libcxx/errno 0 main STP +/sdk/tlibcxx/include/exception /package/include/libcxx/exception 0 main STP +/sdk/tlibcxx/include/experimental/algorithm /package/include/libcxx/experimental/algorithm 0 main STP +/sdk/tlibcxx/include/experimental/any /package/include/libcxx/experimental/any 0 main STP +/sdk/tlibcxx/include/experimental/chrono /package/include/libcxx/experimental/chrono 0 main STP +/sdk/tlibcxx/include/experimental/__config /package/include/libcxx/experimental/__config 0 main STP +/sdk/tlibcxx/include/experimental/deque /package/include/libcxx/experimental/deque 0 main STP +/sdk/tlibcxx/include/experimental/dynarray /package/include/libcxx/experimental/dynarray 0 main STP +/sdk/tlibcxx/include/experimental/filesystem /package/include/libcxx/experimental/filesystem 0 main STP +/sdk/tlibcxx/include/experimental/forward_list /package/include/libcxx/experimental/forward_list 0 main STP +/sdk/tlibcxx/include/experimental/functional /package/include/libcxx/experimental/functional 0 main STP +/sdk/tlibcxx/include/experimental/iterator /package/include/libcxx/experimental/iterator 0 main STP +/sdk/tlibcxx/include/experimental/list /package/include/libcxx/experimental/list 0 main STP +/sdk/tlibcxx/include/experimental/map /package/include/libcxx/experimental/map 0 main STP +/sdk/tlibcxx/include/experimental/__memory /package/include/libcxx/experimental/__memory 0 main STP +/sdk/tlibcxx/include/experimental/memory_resource /package/include/libcxx/experimental/memory_resource 0 main STP +/sdk/tlibcxx/include/experimental/optional /package/include/libcxx/experimental/optional 0 main STP +/sdk/tlibcxx/include/experimental/propagate_const /package/include/libcxx/experimental/propagate_const 0 main STP +/sdk/tlibcxx/include/experimental/ratio /package/include/libcxx/experimental/ratio 0 main STP +/sdk/tlibcxx/include/experimental/regex /package/include/libcxx/experimental/regex 0 main STP +/sdk/tlibcxx/include/experimental/set /package/include/libcxx/experimental/set 0 main STP +/sdk/tlibcxx/include/experimental/string /package/include/libcxx/experimental/string 0 main STP +/sdk/tlibcxx/include/experimental/string_view /package/include/libcxx/experimental/string_view 0 main STP +/sdk/tlibcxx/include/experimental/system_error /package/include/libcxx/experimental/system_error 0 main STP +/sdk/tlibcxx/include/experimental/tuple /package/include/libcxx/experimental/tuple 0 main STP +/sdk/tlibcxx/include/experimental/type_traits /package/include/libcxx/experimental/type_traits 0 main STP +/sdk/tlibcxx/include/experimental/unordered_map /package/include/libcxx/experimental/unordered_map 0 main STP +/sdk/tlibcxx/include/experimental/unordered_set /package/include/libcxx/experimental/unordered_set 0 main STP +/sdk/tlibcxx/include/experimental/utility /package/include/libcxx/experimental/utility 0 main STP +/sdk/tlibcxx/include/experimental/vector /package/include/libcxx/experimental/vector 0 main STP +/sdk/tlibcxx/include/ext/__hash /package/include/libcxx/ext/__hash 0 main STP +/sdk/tlibcxx/include/ext/hash_map /package/include/libcxx/ext/hash_map 0 main STP +/sdk/tlibcxx/include/ext/hash_set /package/include/libcxx/ext/hash_set 0 main STP +/sdk/tlibcxx/include/float.h /package/include/libcxx/float.h 0 main STP +/sdk/tlibcxx/include/forward_list /package/include/libcxx/forward_list 0 main STP +/sdk/tlibcxx/include/fstream /package/include/libcxx/fstream 0 main STP +/sdk/tlibcxx/include/functional /package/include/libcxx/functional 0 main STP +/sdk/tlibcxx/include/__functional_03 /package/include/libcxx/__functional_03 0 main STP +/sdk/tlibcxx/include/__functional_base /package/include/libcxx/__functional_base 0 main STP +/sdk/tlibcxx/include/__functional_base_03 /package/include/libcxx/__functional_base_03 0 main STP +/sdk/tlibcxx/include/future /package/include/libcxx/future 0 main STP +/sdk/tlibcxx/include/__hash_table /package/include/libcxx/__hash_table 0 main STP +/sdk/tlibcxx/include/initializer_list /package/include/libcxx/initializer_list 0 main STP +/sdk/tlibcxx/include/inttypes.h /package/include/libcxx/inttypes.h 0 main STP +/sdk/tlibcxx/include/iomanip /package/include/libcxx/iomanip 0 main STP +/sdk/tlibcxx/include/ios /package/include/libcxx/ios 0 main STP +/sdk/tlibcxx/include/iosfwd /package/include/libcxx/iosfwd 0 main STP +/sdk/tlibcxx/include/iostream /package/include/libcxx/iostream 0 main STP +/sdk/tlibcxx/include/istream /package/include/libcxx/istream 0 main STP +/sdk/tlibcxx/include/iterator /package/include/libcxx/iterator 0 main STP +/sdk/tlibcxx/include/limits /package/include/libcxx/limits 0 main STP +/sdk/tlibcxx/include/list /package/include/libcxx/list 0 main STP +/sdk/tlibcxx/include/locale /package/include/libcxx/locale 0 main STP +/sdk/tlibcxx/include/__locale /package/include/libcxx/__locale 0 main STP +/sdk/tlibcxx/include/map /package/include/libcxx/map 0 main STP +/sdk/tlibcxx/include/math.h /package/include/libcxx/math.h 0 main STP +/sdk/tlibcxx/include/memory /package/include/libcxx/memory 0 main STP +/sdk/tlibcxx/include/mutex /package/include/libcxx/mutex 0 main STP +/sdk/tlibcxx/include/__mutex_base /package/include/libcxx/__mutex_base 0 main STP +/sdk/tlibcxx/include/new /package/include/libcxx/new 0 main STP +/sdk/tlibcxx/include/__nullptr /package/include/libcxx/__nullptr 0 main STP +/sdk/tlibcxx/include/numeric /package/include/libcxx/numeric 0 main STP +/sdk/tlibcxx/include/ostream /package/include/libcxx/ostream 0 main STP +/sdk/tlibcxx/include/queue /package/include/libcxx/queue 0 main STP +/sdk/tlibcxx/include/random /package/include/libcxx/random 0 main STP +/sdk/tlibcxx/include/ratio /package/include/libcxx/ratio 0 main STP +/sdk/tlibcxx/include/__refstring /package/include/libcxx/__refstring 0 main STP +/sdk/tlibcxx/include/regex /package/include/libcxx/regex 0 main STP +/sdk/tlibcxx/include/scoped_allocator /package/include/libcxx/scoped_allocator 0 main STP +/sdk/tlibcxx/include/set /package/include/libcxx/set 0 main STP +/sdk/tlibcxx/include/setjmp.h /package/include/libcxx/setjmp.h 0 main STP +/sdk/tlibcxx/include/__sgx /package/include/libcxx/__sgx 0 main STP +/sdk/tlibcxx/include/shared_mutex /package/include/libcxx/shared_mutex 0 main STP +/sdk/tlibcxx/include/__split_buffer /package/include/libcxx/__split_buffer 0 main STP +/sdk/tlibcxx/include/__sso_allocator /package/include/libcxx/__sso_allocator 0 main STP +/sdk/tlibcxx/include/sstream /package/include/libcxx/sstream 0 main STP +/sdk/tlibcxx/include/stack /package/include/libcxx/stack 0 main STP +/sdk/tlibcxx/include/stdbool.h /package/include/libcxx/stdbool.h 0 main STP +/sdk/tlibcxx/include/stddef.h /package/include/libcxx/stddef.h 0 main STP +/sdk/tlibcxx/include/stdexcept /package/include/libcxx/stdexcept 0 main STP +/sdk/tlibcxx/include/stdio.h /package/include/libcxx/stdio.h 0 main STP +/sdk/tlibcxx/include/stdlib.h /package/include/libcxx/stdlib.h 0 main STP +/sdk/tlibcxx/include/__std_stream /package/include/libcxx/__std_stream 0 main STP +/sdk/tlibcxx/include/streambuf /package/include/libcxx/streambuf 0 main STP +/sdk/tlibcxx/include/string /package/include/libcxx/string 0 main STP +/sdk/tlibcxx/include/string.h /package/include/libcxx/string.h 0 main STP +/sdk/tlibcxx/include/strstream /package/include/libcxx/strstream 0 main STP +/sdk/tlibcxx/include/support/sgx/sgx_condition_variable /package/include/libcxx/support/sgx/sgx_condition_variable 0 main STP +/sdk/tlibcxx/include/support/sgx/sgx_invoke /package/include/libcxx/support/sgx/sgx_invoke 0 main STP +/sdk/tlibcxx/include/support/sgx/sgx_mutex /package/include/libcxx/support/sgx/sgx_mutex 0 main STP +/sdk/tlibcxx/include/support/sgx/__sgx_mutex_base /package/include/libcxx/support/sgx/__sgx_mutex_base 0 main STP +/sdk/tlibcxx/include/support/sgx/__sgx_support /package/include/libcxx/support/sgx/__sgx_support 0 main STP +/sdk/tlibcxx/include/system_error /package/include/libcxx/system_error 0 main STP +/sdk/tlibcxx/include/tgmath.h /package/include/libcxx/tgmath.h 0 main STP +/sdk/tlibcxx/include/thread /package/include/libcxx/thread 0 main STP +/sdk/tlibcxx/include/__threading_support /package/include/libcxx/__threading_support 0 main STP +/sdk/tlibcxx/include/__tree /package/include/libcxx/__tree 0 main STP +/sdk/tlibcxx/include/tuple /package/include/libcxx/tuple 0 main STP +/sdk/tlibcxx/include/__tuple /package/include/libcxx/__tuple 0 main STP +/sdk/tlibcxx/include/typeindex /package/include/libcxx/typeindex 0 main STP +/sdk/tlibcxx/include/typeinfo /package/include/libcxx/typeinfo 0 main STP +/sdk/tlibcxx/include/type_traits /package/include/libcxx/type_traits 0 main STP +/sdk/tlibcxx/include/__undef___deallocate /package/include/libcxx/__undef___deallocate 0 main STP +/sdk/tlibcxx/include/__undef_min_max /package/include/libcxx/__undef_min_max 0 main STP +/sdk/tlibcxx/include/unordered_map /package/include/libcxx/unordered_map 0 main STP +/sdk/tlibcxx/include/unordered_set /package/include/libcxx/unordered_set 0 main STP +/sdk/tlibcxx/include/utility /package/include/libcxx/utility 0 main STP +/sdk/tlibcxx/include/valarray /package/include/libcxx/valarray 0 main STP +/sdk/tlibcxx/include/vector /package/include/libcxx/vector 0 main STP +/sdk/tlibcxx/include/wchar.h /package/include/libcxx/wchar.h 0 main STP +/sdk/tlibcxx/include/wctype.h /package/include/libcxx/wctype.h 0 main STP diff --git a/linux/installer/common/sdk/BOMs/sdk_x64.txt b/linux/installer/common/sdk/BOMs/sdk_x64.txt index c11deced..f16ac692 100644 --- a/linux/installer/common/sdk/BOMs/sdk_x64.txt +++ b/linux/installer/common/sdk/BOMs/sdk_x64.txt @@ -13,6 +13,7 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner /build/linux/libsgx_tservice_sim.a /package/lib64/libsgx_tservice_sim.a 0 main STP /build/linux/libsgx_tstdc.a /package/lib64/libsgx_tstdc.a 0 main STP /build/linux/libsgx_tstdcxx.a /package/lib64/libsgx_tstdcxx.a 0 main STP +/build/linux/libsgx_tcxx.a /package/lib64/libsgx_tcxx.a 0 main STP /build/linux/libsgx_tsetjmp.a /package/lib64/libsgx_tsetjmp.a 0 main STP /build/linux/libsgx_uae_service_deploy.so /package/lib64/libsgx_uae_service.so 0 main STP /build/linux/libsgx_uae_service_sim.so /package/lib64/libsgx_uae_service_sim.so 0 main STP @@ -20,6 +21,7 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner /build/linux/libsgx_urts_deploy.so /package/lib64/libsgx_urts.so 0 main STP /build/linux/libsgx_urts_sim.so /package/lib64/libsgx_urts_sim.so 0 main STP /build/linux/STLport_Changes_SGX.txt /package/lib64/STLport_Changes_SGX.txt 0 main STP +/build/linux/libc++_Changes_SGX.txt /package/lib64/libc++_Changes_SGX.txt 0 main STP /build/linux/sgx_config_cpusvn /package/bin/x64/sgx_config_cpusvn 0 main STP /build/linux/sgx_edger8r /package/bin/x64/sgx_edger8r 0 main STP /build/linux/sgx_sign /package/bin/x64/sgx_sign 0 main STP diff --git a/linux/installer/common/sdk/BOMs/sdk_x86.txt b/linux/installer/common/sdk/BOMs/sdk_x86.txt index 6555739e..3f685836 100644 --- a/linux/installer/common/sdk/BOMs/sdk_x86.txt +++ b/linux/installer/common/sdk/BOMs/sdk_x86.txt @@ -13,6 +13,7 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner /build/linux/libsgx_tservice_sim.a /package/lib/libsgx_tservice_sim.a 0 main STP /build/linux/libsgx_tstdc.a /package/lib/libsgx_tstdc.a 0 main STP /build/linux/libsgx_tstdcxx.a /package/lib/libsgx_tstdcxx.a 0 main STP +/build/linux/libsgx_tcxx.a /package/lib/libsgx_tcxx.a 0 main STP /build/linux/libsgx_tsetjmp.a /package/lib/libsgx_tsetjmp.a 0 main STP /build/linux/libsgx_uae_service_deploy.so /package/lib/libsgx_uae_service.so 0 main STP /build/linux/libsgx_uae_service_sim.so /package/lib/libsgx_uae_service_sim.so 0 main STP @@ -20,6 +21,7 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner /build/linux/libsgx_urts_deploy.so /package/lib/libsgx_urts.so 0 main STP /build/linux/libsgx_urts_sim.so /package/lib/libsgx_urts_sim.so 0 main STP /build/linux/STLport_Changes_SGX.txt /package/lib/STLport_Changes_SGX.txt 0 main STP +/build/linux/libc++_Changes_SGX.txt /package/lib/libc++_Changes_SGX.txt 0 main STP /build/linux/sgx_config_cpusvn /package/bin/x86/sgx_config_cpusvn 0 main STP /build/linux/sgx_edger8r /package/bin/x86/sgx_edger8r 0 main STP /build/linux/sgx_sign /package/bin/x86/sgx_sign 0 main STP diff --git a/sdk/Makefile.opt_lib b/sdk/Makefile.opt_lib index a23a38e4..3845dc05 100644 --- a/sdk/Makefile.opt_lib +++ b/sdk/Makefile.opt_lib @@ -34,6 +34,7 @@ # - Trusted libraries # - tstdc: libsgx_tstdc.a # - tstdcxx: libsgx_tstdcxx.a +# - tcxx: libsgx_tcxx.a # - tservice: libsgx_tservice.a # - trts: libsgx_trts.a # - tcrypto: libsgx_tcrypto.a @@ -53,6 +54,7 @@ include ../buildenv.mk LIBTLIBC := $(BUILD_DIR)/libsgx_tstdc.a LIBTLIBCXX := $(BUILD_DIR)/libsgx_tstdcxx.a +LIBTCXX := $(BUILD_DIR)/libsgx_tcxx.a LIBTSE := $(BUILD_DIR)/libsgx_tservice.a CHECK_OPT := @@ -72,7 +74,7 @@ all: $(CHECK_OPT) $(MAKE) components .PHONY: components -components: tstdc tstdcxx tservice trts tcrypto tkey_exchange ukey_exchange ptrace sample_crypto simulation signtool edger8r tsetjmp +components: tstdc tstdcxx tcxx tservice trts tcrypto tkey_exchange ukey_exchange ptrace sample_crypto simulation signtool edger8r tsetjmp # --------------------------------------------------- # tstdc @@ -139,6 +141,26 @@ tlibstdcxx: $(BUILD_DIR) $(MAKE) -C tlibstdcxx/ 2> /dev/null $(CP) tlibstdcxx/README.sgx $(BUILD_DIR)/STLport_Changes_SGX.txt +# --------------------------------------------------- +# tcxx +# includes: cpprt, tlibcxx +# --------------------------------------------------- +.PHONY: tcxx +tcxx: $(LIBTCXX) + +$(LIBTCXX): cpprt tlibcxx + @$(MKDIR) $(BUILD_DIR)/.cpprt $(BUILD_DIR)/.tlibcxx + @$(RM) -f $(BUILD_DIR)/.cpprt/* $(BUILD_DIR)/.tlibcxx/* + @cd $(BUILD_DIR)/.cpprt && $(AR) x $(LINUX_SDK_DIR)/cpprt/libcpprt.a + @cd $(BUILD_DIR)/.tlibcxx && $(AR) x $(LINUX_SDK_DIR)/tlibcxx/libcxx.a + $(AR) rcsD $@ $(BUILD_DIR)/.cpprt/*.o $(BUILD_DIR)/.tlibcxx/*.o + @$(RM) -rf $(BUILD_DIR)/.cpprt $(BUILD_DIR)/.tlibcxx + +.PHONY: tlibcxx +tlibcxx: $(BUILD_DIR) + $(MAKE) -C tlibcxx/ 2> /dev/null + $(CP) tlibcxx/README.sgx $(BUILD_DIR)/libc++_Changes_SGX.txt + # --------------------------------------------------- # tservice # includes: selib, tseal, tae_service, ec_dh_lib @@ -227,11 +249,12 @@ clean: $(MAKE) -C compiler-rt/ clean $(MAKE) -C cpprt clean $(MAKE) -C tlibstdcxx/ clean + $(MAKE) -C tlibcxx/ clean $(MAKE) -C tseal/linux/ clean $(MAKE) -C selib/linux/ clean $(MAKE) -C tae_service/ clean $(MAKE) -C trts/ clean - $(MAKE) -C tsetjmp/ clean + $(MAKE) -C tsetjmp/ clean $(MAKE) -C tlibcrypto/ clean $(MAKE) -C tkey_exchange/ clean $(MAKE) -C ukey_exchange/ clean @@ -242,4 +265,5 @@ clean: $(MAKE) -C edger8r/linux clean @$(RM) $(LIBTLIBC) $(LIBTLIBCXX) $(LIBTSE) @$(RM) $(BUILD_DIR)/STLport_Changes_SGX.txt + @$(RM) $(BUILD_DIR)/libc++_Changes_SGX.txt diff --git a/sdk/Makefile.source b/sdk/Makefile.source index 10b1e4c3..e745f6dd 100644 --- a/sdk/Makefile.source +++ b/sdk/Makefile.source @@ -34,6 +34,7 @@ # - Trusted libraries # - tstdc: libsgx_tstdc.a # - tstdcxx: libsgx_tstdcxx.a +# - tcxx: libsgx_tcxx.a # - tservice: libsgx_tservice.a # - trts: libsgx_trts.a # - tcrypto: libsgx_tcrypto.a @@ -53,10 +54,11 @@ include ../buildenv.mk LIBTLIBC := $(BUILD_DIR)/libsgx_tstdc.a LIBTLIBCXX := $(BUILD_DIR)/libsgx_tstdcxx.a +LIBTCXX := $(BUILD_DIR)/libsgx_tcxx.a LIBTSE := $(BUILD_DIR)/libsgx_tservice.a .PHONY: all -all: tstdc tstdcxx tservice trts tcrypto tkey_exchange ukey_exchange ptrace sample_crypto simulation signtool edger8r tsetjmp +all: tstdc tstdcxx tcxx tservice trts tcrypto tkey_exchange ukey_exchange ptrace sample_crypto simulation signtool edger8r tsetjmp # --------------------------------------------------- # tstdc @@ -119,6 +121,26 @@ tlibstdcxx: $(BUILD_DIR) $(MAKE) -C tlibstdcxx/ 2> /dev/null $(CP) tlibstdcxx/README.sgx $(BUILD_DIR)/STLport_Changes_SGX.txt +# --------------------------------------------------- +# tcxx +# includes: cpprt, tlibcxx +# --------------------------------------------------- +.PHONY: tcxx +tcxx: $(LIBTCXX) + +$(LIBTCXX): cpprt tlibcxx + @$(MKDIR) $(BUILD_DIR)/.cpprt $(BUILD_DIR)/.tlibcxx + @$(RM) -f $(BUILD_DIR)/.cpprt/* $(BUILD_DIR)/.tlibcxx/* + @cd $(BUILD_DIR)/.cpprt && $(AR) x $(LINUX_SDK_DIR)/cpprt/libcpprt.a + @cd $(BUILD_DIR)/.tlibcxx && $(AR) x $(LINUX_SDK_DIR)/tlibcxx/libcxx.a + $(AR) rcsD $@ $(BUILD_DIR)/.cpprt/*.o $(BUILD_DIR)/.tlibcxx/*.o + @$(RM) -rf $(BUILD_DIR)/.cpprt $(BUILD_DIR)/.tlibcxx + +.PHONY: tlibcxx +tlibcxx: $(BUILD_DIR) + $(MAKE) -C tlibcxx/ 2> /dev/null + $(CP) tlibcxx/README.sgx $(BUILD_DIR)/libc++_Changes_SGX.txt + # --------------------------------------------------- # tse # includes: selib, tseal, tae_service, ec_dh_lib @@ -209,6 +231,7 @@ clean: $(MAKE) -C compiler-rt/ clean $(MAKE) -C cpprt clean $(MAKE) -C tlibstdcxx/ clean + $(MAKE) -C tlibcxx/ clean $(MAKE) -C tseal/linux/ clean $(MAKE) -C selib/linux/ clean $(MAKE) -C tae_service/ clean @@ -224,4 +247,4 @@ clean: $(MAKE) -C edger8r/linux clean @$(RM) $(LIBTLIBC) $(LIBTLIBCXX) $(LIBTSE) @$(RM) $(BUILD_DIR)/STLport_Changes_SGX.txt - + @$(RM) $(BUILD_DIR)/libc++_Changes_SGX.txt diff --git a/sdk/tlibcxx/.arcconfig b/sdk/tlibcxx/.arcconfig new file mode 100644 index 00000000..c96fbc1b --- /dev/null +++ b/sdk/tlibcxx/.arcconfig @@ -0,0 +1,4 @@ +{ + "project_id" : "libcxx", + "conduit_uri" : "https://reviews.llvm.org/" +} diff --git a/sdk/tlibcxx/.gitignore b/sdk/tlibcxx/.gitignore new file mode 100644 index 00000000..b26d5f7a --- /dev/null +++ b/sdk/tlibcxx/.gitignore @@ -0,0 +1,54 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +#lib/ # We actually have things checked in to lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.cache +nosetests.xml +coverage.xml + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ diff --git a/sdk/tlibcxx/CMakeLists.txt b/sdk/tlibcxx/CMakeLists.txt new file mode 100644 index 00000000..d618e835 --- /dev/null +++ b/sdk/tlibcxx/CMakeLists.txt @@ -0,0 +1,434 @@ +# See www/CMake.html for instructions on how to build libcxx with CMake. + +#=============================================================================== +# Setup Project +#=============================================================================== +cmake_minimum_required(VERSION 3.4.3) + +if(POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) # Set MACOSX_RPATH=YES by default +endif() +if(POLICY CMP0022) + cmake_policy(SET CMP0022 NEW) # Required when interacting with LLVM and Clang +endif() + +# Add path for custom modules +set(CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" + ${CMAKE_MODULE_PATH} + ) + +# Find the LLVM sources and simulate LLVM CMake options. +include(HandleOutOfTreeLLVM) + +if (LIBCXX_BUILT_STANDALONE) + project(libcxx CXX C) + + set(PACKAGE_NAME libcxx) + set(PACKAGE_VERSION trunk-svn) + set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") + set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") +endif () + +if (LIBCXX_BUILT_STANDALONE AND NOT LLVM_FOUND) + message(WARNING "UNSUPPORTED LIBCXX CONFIGURATION DETECTED: " + "llvm-config not found and LLVM_PATH not defined.\n" + "Reconfigure with -DLLVM_CONFIG=path/to/llvm-config " + "or -DLLVM_PATH=path/to/llvm-source-root.") +endif() + +# Require out of source build. +include(MacroEnsureOutOfSourceBuild) +MACRO_ENSURE_OUT_OF_SOURCE_BUILD( + "${PROJECT_NAME} requires an out of source build. Please create a separate + build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there." + ) + +#=============================================================================== +# Setup CMake Options +#=============================================================================== + +# Basic options --------------------------------------------------------------- +option(LIBCXX_ENABLE_ASSERTIONS "Enable assertions independent of build mode." ON) +option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON) +option(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY "Build libc++experimental.a" ON) +option(LIBCXX_ENABLE_FILESYSTEM + "Build filesystem as part of libc++experimental.a" ${LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY}) +option(LIBCXX_INCLUDE_TESTS "Build the libc++ tests." ${LLVM_INCLUDE_TESTS}) +option(LIBCXX_INCLUDE_DOCS "Build the libc++ documentation." ${LLVM_INCLUDE_DOCS}) +set(LIBCXX_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING + "Define suffix of library directory name (32/64)") +option(LIBCXX_INSTALL_HEADERS "Install the libc++ headers." ON) +option(LIBCXX_INSTALL_LIBRARY "Install the libc++ library." ON) +option(LIBCXX_INSTALL_SUPPORT_HEADERS "Install libc++ support headers." ON) +option(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY "Install libc++experimental.a" OFF) +set(LIBCXX_ABI_VERSION 1 CACHE STRING "ABI version of libc++.") +option(LIBCXX_ABI_UNSTABLE "Unstable ABI of libc++." OFF) + +# ABI Library options --------------------------------------------------------- +set(LIBCXX_CXX_ABI "${LIBCXX_CXX_ABI}" CACHE STRING + "Specify C++ ABI library to use." FORCE) +set(CXXABIS none libcxxabi libcxxrt libstdc++ libsupc++) +set_property(CACHE LIBCXX_CXX_ABI PROPERTY STRINGS ;${CXXABIS}) + +# Setup the default options if LIBCXX_CXX_ABI is not specified. +if (NOT LIBCXX_CXX_ABI) + if (NOT DEFINED LIBCXX_BUILT_STANDALONE AND + IS_DIRECTORY "${CMAKE_SOURCE_DIR}/projects/libcxxabi") + set(LIBCXX_CXX_ABI_LIBNAME "libcxxabi") + set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${CMAKE_SOURCE_DIR}/projects/libcxxabi/include") + set(LIBCXX_CXX_ABI_INTREE 1) + else () + set(LIBCXX_CXX_ABI_LIBNAME "none") + endif () +else () + set(LIBCXX_CXX_ABI_LIBNAME "${LIBCXX_CXX_ABI}") +endif () + +# Use a static copy of the ABI library when linking libc++. This option +# cannot be used with LIBCXX_ENABLE_ABI_LINKER_SCRIPT. +option(LIBCXX_ENABLE_STATIC_ABI_LIBRARY "Statically link the ABI library" OFF) + +# Generate and install a linker script inplace of libc++.so. The linker script +# will link libc++ to the correct ABI library. This option is on by default +# On UNIX platforms other than Apple unless 'LIBCXX_ENABLE_STATIC_ABI_LIBRARY' +# is on. This option is also disabled when the ABI library is not specified +# or is specified to be "none". +set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE OFF) +if (LLVM_HAVE_LINK_VERSION_SCRIPT AND NOT LIBCXX_ENABLE_STATIC_ABI_LIBRARY + AND NOT LIBCXX_CXX_ABI_LIBNAME STREQUAL "none" + AND PYTHONINTERP_FOUND + AND LIBCXX_ENABLE_SHARED) + set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE ON) +endif() + +option(LIBCXX_ENABLE_ABI_LINKER_SCRIPT + "Use and install a linker script for the given ABI library" + ${ENABLE_LINKER_SCRIPT_DEFAULT_VALUE}) + +# Build libc++abi with libunwind. We need this option to determine whether to +# link with libunwind or libgcc_s while running the test cases. +option(LIBCXXABI_USE_LLVM_UNWINDER "Build and use the LLVM unwinder." OFF) + +# Target options -------------------------------------------------------------- +option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++." ${LLVM_BUILD_32_BITS}) +set(LIBCXX_SYSROOT "" CACHE STRING "Use alternate sysroot.") +set(LIBCXX_GCC_TOOLCHAIN "" CACHE STRING "Use alternate GCC toolchain.") + +# Feature options ------------------------------------------------------------- +option(LIBCXX_ENABLE_EXCEPTIONS "Use exceptions." ON) +option(LIBCXX_ENABLE_RTTI "Use run time type information." ON) +option(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE "Build libc++ with support for the global filesystem namespace." ON) +option(LIBCXX_ENABLE_STDIN "Build libc++ with support for stdin/std::cin." ON) +option(LIBCXX_ENABLE_STDOUT "Build libc++ with support for stdout/std::cout." ON) +option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON) +option(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS "Build libc++ with support for thread-unsafe C functions" ON) +option(LIBCXX_ENABLE_MONOTONIC_CLOCK + "Build libc++ with support for a monotonic clock. + This option may only be set to OFF when LIBCXX_ENABLE_THREADS=OFF." ON) +option(LIBCXX_HAS_MUSL_LIBC "Build libc++ with support for the Musl C library" OFF) +option(LIBCXX_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF) + +# Misc options ---------------------------------------------------------------- +# FIXME: Turn -pedantic back ON. It is currently off because it warns +# about #include_next which is used everywhere. +option(LIBCXX_ENABLE_PEDANTIC "Compile with pedantic enabled." OFF) +option(LIBCXX_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) +option(LIBCXX_DISABLE_MACRO_CONFLICT_WARNINGS "Disable #warnings about conflicting macros." OFF) + +option(LIBCXX_GENERATE_COVERAGE "Enable generating code coverage." OFF) +set(LIBCXX_COVERAGE_LIBRARY "" CACHE STRING + "The Profile-rt library used to build with code coverage") + +# Don't allow a user to accidentally overwrite the system libc++ installation on Darwin. +# If the user specifies -DCMAKE_INSTALL_PREFIX=/usr the install rules for libc++ +# will not be generated and a warning will be issued. +option(LIBCXX_OVERRIDE_DARWIN_INSTALL "Enable overwriting darwins libc++ installation." OFF) +mark_as_advanced(LIBCXX_OVERRIDE_DARWIN_INSTALL) # Don't show this option by default. + +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT LIBCXX_OVERRIDE_DARWIN_INSTALL) + if ("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr") + message(WARNING "Disabling libc++ install rules because installation would " + "overwrite the systems installation. Configure with " + "-DLIBCXX_OVERRIDE_DARWIN_INSTALL=ON to suppress this behaviour.") + mark_as_advanced(CLEAR LIBCXX_OVERRIDE_DARWIN_INSTALL) # Show the override option. + set(LIBCXX_INSTALL_HEADERS OFF) + set(LIBCXX_INSTALL_LIBRARY OFF) + endif() +endif() + +set(LIBCXX_CONFIGURE_IDE_DEFAULT OFF) +if (XCODE OR MSVC_IDE) + set(LIBCXX_CONFIGURE_IDE_DEFAULT ON) +endif() +option(LIBCXX_CONFIGURE_IDE "Configure libcxx for use within an IDE" + ${LIBCXX_CONFIGURE_IDE_DEFAULT}) + +#=============================================================================== +# Check option configurations +#=============================================================================== + +if (LIBCXX_ENABLE_FILESYSTEM AND NOT LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) + message(FATAL_ERROR + "LIBCXX_ENABLE_FILESYSTEM cannot be turned on when LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF") +endif() + +# Ensure LIBCXX_ENABLE_MONOTONIC_CLOCK is set to ON only when +# LIBCXX_ENABLE_THREADS is on. +if(LIBCXX_ENABLE_THREADS AND NOT LIBCXX_ENABLE_MONOTONIC_CLOCK) + message(FATAL_ERROR "LIBCXX_ENABLE_MONOTONIC_CLOCK can only be set to OFF" + " when LIBCXX_ENABLE_THREADS is also set to OFF.") +endif() + +if(LIBCXX_HAS_PTHREAD_API AND NOT LIBCXX_ENABLE_THREADS) + message(FATAL_ERROR "LIBCXX_HAS_PTHREAD_API can only be set to ON" + " when LIBCXX_ENABLE_THREADS is also set to ON.") +endif() + +# Ensure LLVM_USE_SANITIZER is not specified when LIBCXX_GENERATE_COVERAGE +# is ON. +if (LLVM_USE_SANITIZER AND LIBCXX_GENERATE_COVERAGE) + message(FATAL_ERROR "LLVM_USE_SANITIZER cannot be used with LIBCXX_GENERATE_COVERAGE") +endif() + +# Set LIBCXX_BUILD_32_BITS to (LIBCXX_BUILD_32_BITS OR LLVM_BUILD_32_BITS) +# and check that we can build with 32 bits if requested. +if (CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32) + if (LIBCXX_BUILD_32_BITS AND NOT LLVM_BUILD_32_BITS) # Don't duplicate the output from LLVM + message(STATUS "Building 32 bits executables and libraries.") + endif() +elseif(LIBCXX_BUILD_32_BITS) + message(FATAL_ERROR "LIBCXX_BUILD_32_BITS=ON is not supported on this platform.") +endif() + +# Check that this option is not enabled on Apple and emit a usage warning. +if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) + if (APPLE) + message(FATAL_ERROR "LIBCXX_ENABLE_STATIC_ABI_LIBRARY is not supported on OS X") + else() + message(WARNING "LIBCXX_ENABLE_STATIC_ABI_LIBRARY is an experimental option") + endif() +endif() + +if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) + if (APPLE) + message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT cannot be used on APPLE targets") + endif() + if (NOT PYTHONINTERP_FOUND) + message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT requires python but it was not found.") + endif() + if (NOT LIBCXX_ENABLE_SHARED) + message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT is only available for shared library builds.") + endif() +endif() + +if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) + message(FATAL_ERROR "Conflicting options given. + LIBCXX_ENABLE_STATIC_ABI_LIBRARY cannot be specified with + LIBCXX_ENABLE_ABI_LINKER_SCRIPT") +endif() + +if (LIBCXX_HAS_MUSL_LIBC AND NOT LIBCXX_INSTALL_SUPPORT_HEADERS) + message(FATAL_ERROR "LIBCXX_INSTALL_SUPPORT_HEADERS can not be turned off" + "when building for Musl with LIBCXX_HAS_MUSL_LIBC.") +endif() + +#=============================================================================== +# Configure System +#=============================================================================== + +set(LIBCXX_COMPILER ${CMAKE_CXX_COMPILER}) +set(LIBCXX_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(LIBCXX_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX}) + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) + +# Declare libc++ configuration variables. +# They are intended for use as follows: +# LIBCXX_CXX_FLAGS: General flags for both the compiler and linker. +# LIBCXX_COMPILE_FLAGS: Compile only flags. +# LIBCXX_LINK_FLAGS: Linker only flags. +set(LIBCXX_COMPILE_FLAGS "") +set(LIBCXX_LINK_FLAGS "") +set(LIBCXX_LIBRARIES "") + +# Include macros for adding and removing libc++ flags. +include(HandleLibcxxFlags) + +# Target flags ================================================================ +# These flags get added to CMAKE_CXX_FLAGS and CMAKE_C_FLAGS so that +# 'config-ix' use them during feature checks. It also adds them to both +# 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS' +add_target_flags_if(LIBCXX_BUILD_32_BITS "-m32") +add_target_flags_if(LIBCXX_TARGET_TRIPLE "-target ${LIBCXX_TARGET_TRIPLE}") +add_target_flags_if(LIBCXX_SYSROOT "--sysroot=${LIBCXX_SYSROOT}") +add_target_flags_if(LIBCXX_GCC_TOOLCHAIN "-gcc-toolchain ${LIBCXX_GCC_TOOLCHAIN}") + +# Configure compiler. +include(config-ix) + +# Configure coverage options. +if (LIBCXX_GENERATE_COVERAGE) + include(CodeCoverage) + set(CMAKE_BUILD_TYPE "COVERAGE" CACHE STRING "" FORCE) +endif() + +string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) + +#=============================================================================== +# Setup Compiler Flags +#=============================================================================== + +include(HandleLibCXXABI) # Setup the ABI library flags + +# Remove flags that may have snuck in. +remove_flags(-DNDEBUG -UNDEBUG -D_DEBUG + -stdlib=libc++ -stdlib=libstdc++ -lc++abi -m32) + +# FIXME(EricWF): See the FIXME on LIBCXX_ENABLE_PEDANTIC. +# Remove the -pedantic flag and -Wno-pedantic and -pedantic-errors +# so they don't get transformed into -Wno and -errors respectivly. +remove_flags(-Wno-pedantic -pedantic-errors -pedantic) + +# Required flags ============================================================== +add_compile_flags_if_supported(-std=c++11) +if (NOT MSVC AND NOT LIBCXX_SUPPORTS_STD_EQ_CXX11_FLAG) + message(FATAL_ERROR "C++11 is required but the compiler does not support -std=c++11") +endif() + +# On all systems the system c++ standard library headers need to be excluded. +# MSVC only has -X, which disables all default includes; including the crt. +# Thus, we do nothing and hope we don't accidentally include any of the C++ +# headers +add_compile_flags_if_supported(-nostdinc++) + + +# Warning flags =============================================================== +add_definitions(-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +add_compile_flags_if_supported( + -Wall -W -Wwrite-strings + -Wno-unused-parameter -Wno-long-long -Wno-user-defined-literals + -Wno-covered-switch-default + -Werror=return-type) +if (LIBCXX_ENABLE_WERROR) + add_compile_flags_if_supported(-Werror) + add_compile_flags_if_supported(-WX) +else() + # TODO(EricWF) Remove this. We shouldn't be suppressing errors when -Werror is + # added elsewhere. + add_compile_flags_if_supported(-Wno-error) +endif() +if (LIBCXX_ENABLE_PEDANTIC) + add_compile_flags_if_supported(-pedantic) +endif() +if (LIBCXX_DISABLE_MACRO_CONFLICT_WARNINGS) + add_definitions(-D_LIBCPP_DISABLE_MACRO_CONFLICT_WARNINGS) +endif() + +# Exception flags ============================================================= +if (LIBCXX_ENABLE_EXCEPTIONS) + # Catches C++ exceptions only and tells the compiler to assume that extern C + # functions never throw a C++ exception. + add_compile_flags_if_supported(-EHsc) +else() + add_definitions(-D_LIBCPP_NO_EXCEPTIONS) + add_compile_flags_if_supported(-EHs- -EHa-) + add_compile_flags_if_supported(-fno-exceptions) +endif() + +# RTTI flags ================================================================== +if (NOT LIBCXX_ENABLE_RTTI) + add_definitions(-D_LIBCPP_NO_RTTI) + add_compile_flags_if_supported(-GR-) + add_compile_flags_if_supported(-fno-rtti) +endif() + +# Assertion flags ============================================================= +define_if(LIBCXX_ENABLE_ASSERTIONS -UNDEBUG) +define_if_not(LIBCXX_ENABLE_ASSERTIONS -DNDEBUG) +if (LIBCXX_ENABLE_ASSERTIONS) + # MSVC doesn't like _DEBUG on release builds. See PR 4379. + define_if_not(MSVC -D_DEBUG) +endif() + +# Feature flags =============================================================== +define_if(MSVC -D_CRT_SECURE_NO_WARNINGS) + +# Sanitizer flags ============================================================= + +# Configure for sanitizers. If LIBCXX_BUILT_STANDALONE then we have to do +# the flag translation ourselves. Othewise LLVM's CMakeList.txt will handle it. +if (LIBCXX_BUILT_STANDALONE) + set(LLVM_USE_SANITIZER "" CACHE STRING + "Define the sanitizer used to build the library and tests") + # NOTE: LLVM_USE_SANITIZER checks for a UNIX like system instead of MSVC. + # But we don't have LLVM_ON_UNIX so checking for MSVC is the best we can do. + if (LLVM_USE_SANITIZER AND NOT MSVC) + add_flags_if_supported("-fno-omit-frame-pointer") + add_flags_if_supported("-gline-tables-only") + + if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" AND + NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO") + add_flags_if_supported("-gline-tables-only") + endif() + if (LLVM_USE_SANITIZER STREQUAL "Address") + add_flags("-fsanitize=address") + elseif (LLVM_USE_SANITIZER MATCHES "Memory(WithOrigins)?") + add_flags(-fsanitize=memory) + if (LLVM_USE_SANITIZER STREQUAL "MemoryWithOrigins") + add_flags("-fsanitize-memory-track-origins") + endif() + elseif (LLVM_USE_SANITIZER STREQUAL "Undefined") + add_flags("-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all") + elseif (LLVM_USE_SANITIZER STREQUAL "Thread") + add_flags(-fsanitize=thread) + else() + message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${LLVM_USE_SANITIZER}") + endif() + elseif(LLVM_USE_SANITIZER AND MSVC) + message(WARNING "LLVM_USE_SANITIZER is not supported on this platform.") + endif() +endif() + +# Configuration file flags ===================================================== +if (NOT LIBCXX_ABI_VERSION EQUAL "1") + config_define(${LIBCXX_ABI_VERSION} _LIBCPP_ABI_VERSION) +endif() +config_define_if(LIBCXX_ABI_UNSTABLE _LIBCPP_ABI_UNSTABLE) + +config_define_if_not(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE) +config_define_if_not(LIBCXX_ENABLE_STDIN _LIBCPP_HAS_NO_STDIN) +config_define_if_not(LIBCXX_ENABLE_STDOUT _LIBCPP_HAS_NO_STDOUT) +config_define_if_not(LIBCXX_ENABLE_THREADS _LIBCPP_HAS_NO_THREADS) +config_define_if_not(LIBCXX_ENABLE_MONOTONIC_CLOCK _LIBCPP_HAS_NO_MONOTONIC_CLOCK) +config_define_if_not(LIBCXX_ENABLE_THREAD_UNSAFE_C_FUNCTIONS _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS) + +config_define_if(LIBCXX_HAS_PTHREAD_API _LIBCPP_HAS_THREAD_API_PTHREAD) +config_define_if(LIBCXX_HAS_MUSL_LIBC _LIBCPP_HAS_MUSL_LIBC) + +if (LIBCXX_NEEDS_SITE_CONFIG) + configure_file( + include/__config_site.in + ${LIBCXX_BINARY_DIR}/__config_site + @ONLY) + # Provide the config definitions by included the generated __config_site + # file at compile time. + add_compile_flags("-include ${LIBCXX_BINARY_DIR}/__config_site") +endif() + +#=============================================================================== +# Setup Source Code And Tests +#=============================================================================== +include_directories(include) +add_subdirectory(include) +add_subdirectory(lib) + +if (LIBCXX_INCLUDE_TESTS) + add_subdirectory(test) +endif() +if (LIBCXX_INCLUDE_DOCS) + add_subdirectory(docs) +endif() diff --git a/sdk/tlibcxx/CREDITS.TXT b/sdk/tlibcxx/CREDITS.TXT new file mode 100644 index 00000000..ceb12c42 --- /dev/null +++ b/sdk/tlibcxx/CREDITS.TXT @@ -0,0 +1,142 @@ +This file is a partial list of people who have contributed to the LLVM/libc++ +project. If you have contributed a patch or made some other contribution to +LLVM/libc++, please submit a patch to this file to add yourself, and it will be +done! + +The list is sorted by surname and formatted to allow easy grepping and +beautification by scripts. The fields are: name (N), email (E), web-address +(W), PGP key ID and fingerprint (P), description (D), and snail-mail address +(S). + +N: Saleem Abdulrasool +E: compnerd@compnerd.org +D: Minor patches and Linux fixes. + +N: Dan Albert +E: danalbert@google.com +D: Android support and test runner improvements. + +N: Dimitry Andric +E: dimitry@andric.com +D: Visibility fixes, minor FreeBSD portability patches. + +N: Holger Arnold +E: holgerar@gmail.com +D: Minor fix. + +N: Ruben Van Boxem +E: vanboxem dot ruben at gmail dot com +D: Initial Windows patches. + +N: David Chisnall +E: theraven at theravensnest dot org +D: FreeBSD and Solaris ports, libcxxrt support, some atomics work. + +N: Marshall Clow +E: mclow.lists@gmail.com +E: marshall@idio.com +D: C++14 support, patches and bug fixes. + +N: Jonathan B Coe +E: jbcoe@me.com +D: Implementation of propagate_const. + +N: Eric Fiselier +E: eric@efcs.ca +D: LFTS support, patches and bug fixes. + +N: Bill Fisher +E: william.w.fisher@gmail.com +D: Regex bug fixes. + +N: Matthew Dempsky +E: matthew@dempsky.org +D: Minor patches and bug fixes. + +N: Google Inc. +D: Copyright owner and contributor of the CityHash algorithm + +N: Howard Hinnant +E: hhinnant@apple.com +D: Architect and primary author of libc++ + +N: Hyeon-bin Jeong +E: tuhertz@gmail.com +D: Minor patches and bug fixes. + +N: Argyrios Kyrtzidis +E: kyrtzidis@apple.com +D: Bug fixes. + +N: Bruce Mitchener, Jr. +E: bruce.mitchener@gmail.com +D: Emscripten-related changes. + +N: Michel Morin +E: mimomorin@gmail.com +D: Minor patches to is_convertible. + +N: Andrew Morrow +E: andrew.c.morrow@gmail.com +D: Minor patches and Linux fixes. + +N: Arvid Picciani +E: aep at exys dot org +D: Minor patches and musl port. + +N: Bjorn Reese +E: breese@users.sourceforge.net +D: Initial regex prototype + +N: Nico Rieck +E: nico.rieck@gmail.com +D: Windows fixes + +N: Jon Roelofs +E: jonathan@codesourcery.com +D: Remote testing, Newlib port, baremetal/single-threaded support. + +N: Jonathan Sauer +D: Minor patches, mostly related to constexpr + +N: Craig Silverstein +E: csilvers@google.com +D: Implemented Cityhash as the string hash function on 64-bit machines + +N: Richard Smith +D: Minor patches. + +N: Joerg Sonnenberger +E: joerg@NetBSD.org +D: NetBSD port. + +N: Stephan Tolksdorf +E: st@quanttec.com +D: Minor fix + +N: Michael van der Westhuizen +E: r1mikey at gmail dot com + +N: Larisse Voufo +D: Minor patches. + +N: Klaas de Vries +E: klaas at klaasgaaf dot nl +D: Minor bug fix. + +N: Zhang Xiongpang +E: zhangxiongpang@gmail.com +D: Minor patches and bug fixes. + +N: Xing Xue +E: xingxue@ca.ibm.com +D: AIX port + +N: Zhihao Yuan +E: lichray@gmail.com +D: Standard compatibility fixes. + +N: Jeffrey Yasskin +E: jyasskin@gmail.com +E: jyasskin@google.com +D: Linux fixes. diff --git a/sdk/tlibcxx/LICENSE.TXT b/sdk/tlibcxx/LICENSE.TXT new file mode 100644 index 00000000..339e232c --- /dev/null +++ b/sdk/tlibcxx/LICENSE.TXT @@ -0,0 +1,76 @@ +============================================================================== +libc++ License +============================================================================== + +The libc++ library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================== + +University of Illinois/NCSA +Open Source License + +Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== + +Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/sdk/tlibcxx/Makefile b/sdk/tlibcxx/Makefile new file mode 100644 index 00000000..ec74fd81 --- /dev/null +++ b/sdk/tlibcxx/Makefile @@ -0,0 +1,66 @@ +# +# Copyright (C) 2011-2016 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + + +include ../../buildenv.mk + +CFLAGS += $(ENCLAVE_CFLAGS) +CXXFLAGS += $(ENCLAVE_CXXFLAGS) + +CPPFLAGS += -I./include \ + -I$(COMMON_DIR)/inc \ + -I$(COMMON_DIR)/inc/stdc++ \ + -I$(COMMON_DIR)/inc/tlibc \ + -I$(COMMON_DIR)/inc/stdc++ \ + -I$(COMMON_DIR)/inc/internal \ + +CPPFLAGS += -I$(LINUX_SDK_DIR)/trts \ + -I$(LINUX_SDK_DIR)/trts/linux + +CPP_SRCS := $(wildcard src/*.cpp src/support/sgx/*.cpp) +CPP_OBJS := $(CPP_SRCS:.cpp=.o) + +OBJS := $(CPP_OBJS) + +LIBCXX_NAME = libcxx.a + +.PHONY:all +all: $(LIBCXX_NAME) + +$(LIBCXX_NAME): $(OBJS) + $(AR) rcs $(LIBCXX_NAME) $^ + +$(OBJS): %.o: %.cpp + $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $< -o $@ + +.PHONY: clean +clean: + @$(RM) $(LIBCXX_NAME) $(OBJS) diff --git a/sdk/tlibcxx/README.sgx b/sdk/tlibcxx/README.sgx new file mode 100644 index 00000000..0a808c24 --- /dev/null +++ b/sdk/tlibcxx/README.sgx @@ -0,0 +1,28 @@ + +Pre-release Notes: + * Added pre-release libc++ to enable C++11 inside the enclave. + * libsgx_tcxx is built and installed as part of the Intel SGX SDK. + * If the Intel SGX SDK is installed in /opt/intel/sgxsdk/, the library and header files will be installed + in /opt/intel/sgxsdk/lib64 and /opt/intel/sgxsdk/include/libcxx, respectively. + * This pre-release library has not been validated. + * See SampleCode/Cxx11SGXDemo for a sample enclave using some C++11 features. + + +Version: 3.9 + +Changes: + * Add __sgx to __config for SGX specific configuration. + * Define _LIBCPP_HAS_NO_THREADS, _LIBCPP_HAS_NO_STDIN, _LIBCPP_HAS_NO_STDOUT, _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE. + * Use SGX C++ runtime library (cpprt from libcxxrt project ) instead. + * Disable unsupported data types and interfaces. + * Disable features that depend on I/O operations. + * Use SGX mutex, condition variable and spinlock instead of libc++ implementation. + * Use sgx_read_rand for generating random numbers. + * Disable randon until we determine whether it's used safely. + * Do not include Windows/Linux system headers directly. + * Fix MSVC and GCC warnings with unused parameters. + +TODO: + * Merge SGX mutex and condition variable into libc++'s mutex and condition variable. + * Merge atomic support for ICC. + * Update cpprt (libcxxrt project) or replace with libcxxabi (component of LLVM project). diff --git a/sdk/tlibcxx/TODO.TXT b/sdk/tlibcxx/TODO.TXT new file mode 100644 index 00000000..bdb94de3 --- /dev/null +++ b/sdk/tlibcxx/TODO.TXT @@ -0,0 +1,56 @@ +This is meant to be a general place to list things that should be done "someday" + +3.8 Release Goals +================= +* LFTS v1 (EricWF, MClow) +* Filesystem TS (EricWF) +* ASIO TS (MClow) +* Improvements (MClow) +* Setup ABI Versioning policy (EricWF) +* Fix PR19302 - Fix UB in list and __tree. + + +ABI Related Tasks +================= +* Explicitly manage and verify symbols exported from the dylib. +* Explore using namespaces for managing symbol visibility. +* Introduce and document ABI versioning/evolution policy. + +CXX Runtime Library Tasks +========================= +* Cleanup #ifdef hell in sources files that supports the different ABI libraries. +* Fix that CMake always link to /usr/lib/libc++abi.dylib on OS X. +* Fix selection of ABI symbol list on OS X. +* Have CMake generate linker scripts for libc++.so that it properly links the + runtime library. +* Look into mirroring libsupc++'s typeinfo vtable layout when libsupc++/libstdc++ + is used as the runtime library. +* Audit libraries that CMake links into libc++. Are they all required? +* Investigate and document interoperability between libc++ and libstdc++ on + linux. Do this for every supported c++ runtime library. + +Atomic Related Tasks +==================== +* Enable mixing of clang and GCC atomics internally. Currently some + parts of libc++ use atomics only when clang provides them. + (see memory@5380 for an example) +* Audit use of libatomic builtins in with GCC. +* future should use for synchronization. + +Test Suite Tasks +================ +* Move all libc++ specific tests from test/std into test/libcxx. +* Improve how LIT handles compiler warnings. +* Improve the quality and portability of the locale test data. +* Convert failure tests to use Clang Verify. + +Misc Tasks +========== +* Find all sequences of >2 underscores and eradicate them. +* run clang-tidy on libc++ +* Document the "conditionally-supported" bits of libc++ +* Look at basic_string's move assignment operator, re LWG 2063 and POCMA +* libc++ is missing try_emplace +* Put a static_assert in std::allocator to deny const/volatile types (LWG 2447) +* Document support (or lack of) for C++11 libraries in C++03. +* Document supported compilers. diff --git a/sdk/tlibcxx/benchmarks/unordered_set_operations.bench.cpp b/sdk/tlibcxx/benchmarks/unordered_set_operations.bench.cpp new file mode 100644 index 00000000..c9ee689f --- /dev/null +++ b/sdk/tlibcxx/benchmarks/unordered_set_operations.bench.cpp @@ -0,0 +1,44 @@ +#include +#include +#include + +#include "benchmark/benchmark_api.h" + +template +std::vector getInputs(size_t N) { + std::vector inputs; + for (size_t i=0; i < N; ++i) { + inputs.push_back(i); + } + return inputs; +} + +template +void BM_SetInsert(benchmark::State& st, Container c, Inputs const& in) { + const auto end = in.end(); + while (st.KeepRunning()) { + c.clear(); + for (auto it = in.begin(); it != end; ++it) { + benchmark::DoNotOptimize(c.insert(*it)); + } + benchmark::DoNotOptimize(c); + } +} +BENCHMARK_CAPTURE(BM_SetInsert, uint32_insert, + std::unordered_set{}, getInputs(1024)); + +template +void BM_SetFind(benchmark::State& st, Container c, Inputs const& in) { + c.insert(in.begin(), in.end()); + const auto end = in.end(); + while (st.KeepRunning()) { + for (auto it = in.begin(); it != end; ++it) { + benchmark::DoNotOptimize(c.find(*it)); + } + } +} +BENCHMARK_CAPTURE(BM_SetFind, uint32_lookup, + std::unordered_set{}, getInputs(1024)); + + +BENCHMARK_MAIN() diff --git a/sdk/tlibcxx/cmake/Modules/CheckLibcxxAtomic.cmake b/sdk/tlibcxx/cmake/Modules/CheckLibcxxAtomic.cmake new file mode 100644 index 00000000..4ff34323 --- /dev/null +++ b/sdk/tlibcxx/cmake/Modules/CheckLibcxxAtomic.cmake @@ -0,0 +1,41 @@ +INCLUDE(CheckCXXSourceCompiles) + +# Sometimes linking against libatomic is required for atomic ops, if +# the platform doesn't support lock-free atomics. +# +# We could modify LLVM's CheckAtomic module and have it check for 64-bit +# atomics instead. However, we would like to avoid careless uses of 64-bit +# atomics inside LLVM over time on 32-bit platforms. + +function(check_cxx_atomics varname) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "-std=c++11 -nostdinc++ -isystem ${LIBCXX_SOURCE_DIR}/include") + if (${LIBCXX_GCC_TOOLCHAIN}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} --gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}") + endif() + check_cxx_source_compiles(" +#include +#include +std::atomic x; +std::atomic y; +int main() { + return x + y; +} +" ${varname}) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endfunction(check_cxx_atomics) + +check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB) +check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB) +# If not, check if the library exists, and atomics work with it. +if(NOT LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB) + if(LIBCXX_HAS_ATOMIC_LIB) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB) + if (NOT LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB) + message(WARNING "Host compiler must support std::atomic!") + endif() + else() + message(WARNING "Host compiler appears to require libatomic, but cannot find it.") + endif() +endif() diff --git a/sdk/tlibcxx/cmake/Modules/CodeCoverage.cmake b/sdk/tlibcxx/cmake/Modules/CodeCoverage.cmake new file mode 100644 index 00000000..addd10ab --- /dev/null +++ b/sdk/tlibcxx/cmake/Modules/CodeCoverage.cmake @@ -0,0 +1,36 @@ +find_program(CODE_COVERAGE_LCOV lcov) +if (NOT CODE_COVERAGE_LCOV) + message(FATAL_ERROR "Cannot find lcov...") +endif() + +find_program(CODE_COVERAGE_GENHTML genhtml) +if (NOT CODE_COVERAGE_GENHTML) + message(FATAL_ERROR "Cannot find genhtml...") +endif() + +set(CMAKE_CXX_FLAGS_COVERAGE "-g -O0 --coverage") + +function(setup_lcov_test_target_coverage target_name output_dir capture_dirs source_dirs) + file(MAKE_DIRECTORY ${output_dir}) + + set(CAPTURE_DIRS "") + foreach(cdir ${capture_dirs}) + list(APPEND CAPTURE_DIRS "-d;${cdir}") + endforeach() + + set(EXTRACT_DIRS "") + foreach(sdir ${source_dirs}) + list(APPEND EXTRACT_DIRS "'${sdir}/*'") + endforeach() + + message(STATUS "Capture Directories: ${CAPTURE_DIRS}") + message(STATUS "Extract Directories: ${EXTRACT_DIRS}") + + add_custom_target(generate-lib${target_name}-coverage + COMMAND ${CODE_COVERAGE_LCOV} --capture ${CAPTURE_DIRS} -o test_coverage.info + COMMAND ${CODE_COVERAGE_LCOV} --extract test_coverage.info ${EXTRACT_DIRS} -o test_coverage.info + COMMAND ${CODE_COVERAGE_GENHTML} --demangle-cpp test_coverage.info -o test_coverage + COMMAND ${CMAKE_COMMAND} -E remove test_coverage.info + WORKING_DIRECTORY ${output_dir} + COMMENT "Generating coverage results") +endfunction() diff --git a/sdk/tlibcxx/cmake/Modules/HandleLibCXXABI.cmake b/sdk/tlibcxx/cmake/Modules/HandleLibCXXABI.cmake new file mode 100644 index 00000000..c655adff --- /dev/null +++ b/sdk/tlibcxx/cmake/Modules/HandleLibCXXABI.cmake @@ -0,0 +1,110 @@ + +#=============================================================================== +# Add an ABI library if appropriate +#=============================================================================== + +# +# _setup_abi: Set up the build to use an ABI library +# +# Parameters: +# abidefines: A list of defines needed to compile libc++ with the ABI library +# abilib : The ABI library to link against. +# abifiles : A list of files (which may be relative paths) to copy into the +# libc++ build tree for the build. These files will also be +# installed alongside the libc++ headers. +# abidirs : A list of relative paths to create under an include directory +# in the libc++ build directory. +# +macro(setup_abi_lib abidefines abilib abifiles abidirs) + list(APPEND LIBCXX_COMPILE_FLAGS ${abidefines}) + set(LIBCXX_CXX_ABI_INCLUDE_PATHS "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" + CACHE PATH + "Paths to C++ ABI header directories separated by ';'." FORCE + ) + set(LIBCXX_CXX_ABI_LIBRARY_PATH "${LIBCXX_CXX_ABI_LIBRARY_PATH}" + CACHE PATH + "Paths to C++ ABI library directory" + ) + set(LIBCXX_CXX_ABI_LIBRARY ${abilib}) + set(LIBCXX_ABILIB_FILES ${abifiles}) + + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include") + foreach(_d ${abidirs}) + file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/${_d}") + endforeach() + + foreach(fpath ${LIBCXX_ABILIB_FILES}) + set(found FALSE) + foreach(incpath ${LIBCXX_CXX_ABI_INCLUDE_PATHS}) + if (EXISTS "${incpath}/${fpath}") + set(found TRUE) + get_filename_component(dstdir ${fpath} PATH) + get_filename_component(ifile ${fpath} NAME) + file(COPY "${incpath}/${fpath}" + DESTINATION "${CMAKE_BINARY_DIR}/include/${dstdir}" + ) + if (LIBCXX_INSTALL_HEADERS) + install(FILES "${CMAKE_BINARY_DIR}/include/${fpath}" + DESTINATION include/c++/v1/${dstdir} + COMPONENT libcxx + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + ) + endif() + list(APPEND abilib_headers "${CMAKE_BINARY_DIR}/include/${fpath}") + endif() + endforeach() + if (NOT found) + message(WARNING "Failed to find ${fpath}") + endif() + endforeach() + + add_custom_target(LIBCXX_CXX_ABI_DEPS DEPENDS ${abilib_headers}) + include_directories("${CMAKE_BINARY_DIR}/include") + +endmacro() + + +# Configure based on the selected ABI library. +if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR + "${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libsupc++") + set(_LIBSUPCXX_INCLUDE_FILES + cxxabi.h bits/c++config.h bits/os_defines.h bits/cpu_defines.h + bits/cxxabi_tweaks.h bits/cxxabi_forced.h + ) + if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++") + set(_LIBSUPCXX_DEFINES "-DLIBSTDCXX") + set(_LIBSUPCXX_LIBNAME stdc++) + else() + set(_LIBSUPCXX_DEFINES "") + set(_LIBSUPCXX_LIBNAME supc++) + endif() + setup_abi_lib( + "-D__GLIBCXX__ ${_LIBSUPCXX_DEFINES}" + "${_LIBSUPCXX_LIBNAME}" "${_LIBSUPCXX_INCLUDE_FILES}" "bits" + ) +elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi") + if (LIBCXX_CXX_ABI_INTREE) + # Link against just-built "cxxabi" target. + if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) + set(CXXABI_LIBNAME cxxabi_static) + else() + set(CXXABI_LIBNAME cxxabi_shared) + endif() + set(LIBCXX_LIBCPPABI_VERSION "2" PARENT_SCOPE) + else() + # Assume c++abi is installed in the system, rely on -lc++abi link flag. + set(CXXABI_LIBNAME "c++abi") + endif() + setup_abi_lib("-DLIBCXX_BUILDING_LIBCXXABI" + ${CXXABI_LIBNAME} "cxxabi.h;__cxxabi_config.h" "" + ) +elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt") + setup_abi_lib("-DLIBCXXRT" + "cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" "" + ) +elseif (NOT "${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "none") + message(FATAL_ERROR + "Currently libstdc++, libsupc++, libcxxabi, libcxxrt and none are " + "supported for c++ abi." + ) +endif () diff --git a/sdk/tlibcxx/cmake/Modules/HandleLibcxxFlags.cmake b/sdk/tlibcxx/cmake/Modules/HandleLibcxxFlags.cmake new file mode 100644 index 00000000..325c1bdf --- /dev/null +++ b/sdk/tlibcxx/cmake/Modules/HandleLibcxxFlags.cmake @@ -0,0 +1,194 @@ +# HandleLibcxxFlags - A set of macros used to setup the flags used to compile +# and link libc++. These macros add flags to the following CMake variables. +# - LIBCXX_COMPILE_FLAGS: flags used to compile libc++ +# - LIBCXX_LINK_FLAGS: flags used to link libc++ +# - LIBCXX_LIBRARIES: libraries to link libc++ to. + +include(CheckCXXCompilerFlag) + +unset(add_flag_if_supported) + +# Mangle the name of a compiler flag into a valid CMake identifier. +# Ex: --std=c++11 -> STD_EQ_CXX11 +macro(mangle_name str output) + string(STRIP "${str}" strippedStr) + string(REGEX REPLACE "^/" "" strippedStr "${strippedStr}") + string(REGEX REPLACE "^-+" "" strippedStr "${strippedStr}") + string(REGEX REPLACE "-+$" "" strippedStr "${strippedStr}") + string(REPLACE "-" "_" strippedStr "${strippedStr}") + string(REPLACE "=" "_EQ_" strippedStr "${strippedStr}") + string(REPLACE "+" "X" strippedStr "${strippedStr}") + string(TOUPPER "${strippedStr}" ${output}) +endmacro() + +# Remove a list of flags from all CMake variables that affect compile flags. +# This can be used to remove unwanted flags specified on the command line +# or added in other parts of LLVM's cmake configuration. +macro(remove_flags) + foreach(var ${ARGN}) + string(REPLACE "${var}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REPLACE "${var}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + string(REPLACE "${var}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + string(REPLACE "${var}" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + string(REPLACE "${var}" "" CMAKE_SHARED_MODULE_FLAGS "${CMAKE_SHARED_MODULE_FLAGS}") + remove_definitions(${var}) + endforeach() +endmacro(remove_flags) + +macro(check_flag_supported flag) + mangle_name("${flag}" flagname) + check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG") +endmacro() + +# Add a macro definition if condition is true. +macro(define_if condition def) + if (${condition}) + add_definitions(${def}) + endif() +endmacro() + +# Add a macro definition if condition is not true. +macro(define_if_not condition def) + if (NOT ${condition}) + add_definitions(${def}) + endif() +endmacro() + +# Add a macro definition to the __config_site file if the specified condition +# is 'true'. Note that '-D${def}' is not added. Instead it is expected that +# the build include the '__config_site' header. +macro(config_define_if condition def) + if (${condition}) + set(${def} ON) + set(LIBCXX_NEEDS_SITE_CONFIG ON) + endif() +endmacro() + +macro(config_define_if_not condition def) + if (NOT ${condition}) + set(${def} ON) + set(LIBCXX_NEEDS_SITE_CONFIG ON) + endif() +endmacro() + +macro(config_define value def) + set(${def} ${value}) + set(LIBCXX_NEEDS_SITE_CONFIG ON) +endmacro() + +# Add a list of flags to all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', +# 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS'. +macro(add_target_flags) + foreach(value ${ARGN}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${value}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${value}") + list(APPEND LIBCXX_COMPILE_FLAGS ${value}) + list(APPEND LIBCXX_LINK_FLAGS ${value}) + endforeach() +endmacro() + +# If the specified 'condition' is true then add a list of flags to +# all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBCXX_COMPILE_FLAGS' +# and 'LIBCXX_LINK_FLAGS'. +macro(add_target_flags_if condition) + if (${condition}) + add_target_flags(${ARGN}) + endif() +endmacro() + +# Add a specified list of flags to both 'LIBCXX_COMPILE_FLAGS' and +# 'LIBCXX_LINK_FLAGS'. +macro(add_flags) + foreach(value ${ARGN}) + list(APPEND LIBCXX_COMPILE_FLAGS ${value}) + list(APPEND LIBCXX_LINK_FLAGS ${value}) + endforeach() +endmacro() + +# If the specified 'condition' is true then add a list of flags to both +# 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS'. +macro(add_flags_if condition) + if (${condition}) + add_flags(${ARGN}) + endif() +endmacro() + +# Add each flag in the list to LIBCXX_COMPILE_FLAGS and LIBCXX_LINK_FLAGS +# if that flag is supported by the current compiler. +macro(add_flags_if_supported) + foreach(flag ${ARGN}) + mangle_name("${flag}" flagname) + check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG") + add_flags_if(LIBCXX_SUPPORTS_${flagname}_FLAG ${flag}) + endforeach() +endmacro() + +# Add a list of flags to 'LIBCXX_COMPILE_FLAGS'. +macro(add_compile_flags) + foreach(f ${ARGN}) + list(APPEND LIBCXX_COMPILE_FLAGS ${f}) + endforeach() +endmacro() + +# If 'condition' is true then add the specified list of flags to +# 'LIBCXX_COMPILE_FLAGS' +macro(add_compile_flags_if condition) + if (${condition}) + add_compile_flags(${ARGN}) + endif() +endmacro() + +# For each specified flag, add that flag to 'LIBCXX_COMPILE_FLAGS' if the +# flag is supported by the C++ compiler. +macro(add_compile_flags_if_supported) + foreach(flag ${ARGN}) + mangle_name("${flag}" flagname) + check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG") + add_compile_flags_if(LIBCXX_SUPPORTS_${flagname}_FLAG ${flag}) + endforeach() +endmacro() + +# Add a list of flags to 'LIBCXX_LINK_FLAGS'. +macro(add_link_flags) + foreach(f ${ARGN}) + list(APPEND LIBCXX_LINK_FLAGS ${f}) + endforeach() +endmacro() + +# If 'condition' is true then add the specified list of flags to +# 'LIBCXX_LINK_FLAGS' +macro(add_link_flags_if condition) + if (${condition}) + add_link_flags(${ARGN}) + endif() +endmacro() + +# For each specified flag, add that flag to 'LIBCXX_LINK_FLAGS' if the +# flag is supported by the C++ compiler. +macro(add_link_flags_if_supported) + foreach(flag ${ARGN}) + mangle_name("${flag}" flagname) + check_cxx_compiler_flag("${flag}" "LIBCXX_SUPPORTS_${flagname}_FLAG") + add_link_flags_if(LIBCXX_SUPPORTS_${flagname}_FLAG ${flag}) + endforeach() +endmacro() + +# Add a list of libraries or link flags to 'LIBCXX_LIBRARIES'. +macro(add_library_flags) + foreach(lib ${ARGN}) + list(APPEND LIBCXX_LIBRARIES ${lib}) + endforeach() +endmacro() + +# if 'condition' is true then add the specified list of libraries and flags +# to 'LIBCXX_LIBRARIES'. +macro(add_library_flags_if condition) + if(${condition}) + add_library_flags(${ARGN}) + endif() +endmacro() + +# Turn a comma separated CMake list into a space separated string. +macro(split_list listname) + string(REPLACE ";" " " ${listname} "${${listname}}") +endmacro() diff --git a/sdk/tlibcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake b/sdk/tlibcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake new file mode 100644 index 00000000..9c5dd810 --- /dev/null +++ b/sdk/tlibcxx/cmake/Modules/HandleOutOfTreeLLVM.cmake @@ -0,0 +1,130 @@ +macro(find_llvm_parts) +# Rely on llvm-config. + set(CONFIG_OUTPUT) + find_program(LLVM_CONFIG "llvm-config") + if(DEFINED LLVM_PATH) + set(LLVM_INCLUDE_DIR ${LLVM_INCLUDE_DIR} CACHE PATH "Path to llvm/include") + set(LLVM_PATH ${LLVM_PATH} CACHE PATH "Path to LLVM source tree") + set(LLVM_MAIN_SRC_DIR ${LLVM_PATH}) + set(LLVM_CMAKE_PATH "${LLVM_PATH}/cmake/modules") + elseif(LLVM_CONFIG) + message(STATUS "Found LLVM_CONFIG as ${LLVM_CONFIG}") + set(CONFIG_COMMAND ${LLVM_CONFIG} + "--includedir" + "--prefix" + "--src-root") + execute_process( + COMMAND ${CONFIG_COMMAND} + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE CONFIG_OUTPUT + ) + if(NOT HAD_ERROR) + string(REGEX REPLACE + "[ \t]*[\r\n]+[ \t]*" ";" + CONFIG_OUTPUT ${CONFIG_OUTPUT}) + else() + string(REPLACE ";" " " CONFIG_COMMAND_STR "${CONFIG_COMMAND}") + message(STATUS "${CONFIG_COMMAND_STR}") + message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") + endif() + + list(GET CONFIG_OUTPUT 0 INCLUDE_DIR) + list(GET CONFIG_OUTPUT 1 LLVM_OBJ_ROOT) + list(GET CONFIG_OUTPUT 2 MAIN_SRC_DIR) + + set(LLVM_INCLUDE_DIR ${INCLUDE_DIR} CACHE PATH "Path to llvm/include") + set(LLVM_BINARY_DIR ${LLVM_OBJ_ROOT} CACHE PATH "Path to LLVM build tree") + set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") + set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") + else() + set(LLVM_FOUND OFF) + return() + endif() + + if (NOT EXISTS ${LLVM_MAIN_SRC_DIR}) + set(LLVM_FOUND OFF) + message(WARNING "Not found: ${LLVM_MAIN_SRC_DIR}") + return() + endif() + + if(NOT EXISTS ${LLVM_CMAKE_PATH}) + set(LLVM_FOUND OFF) + message(WARNING "Not found: ${LLVM_CMAKE_PATH}") + return() + endif() + + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") + list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") + + set(LLVM_FOUND ON) +endmacro(find_llvm_parts) + + +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + set(LIBCXX_BUILT_STANDALONE 1) + message(STATUS "Configuring for standalone build.") + + find_llvm_parts() + + # LLVM Options -------------------------------------------------------------- + include(FindPythonInterp) + if( NOT PYTHONINTERP_FOUND ) + message(WARNING "Failed to find python interpreter. " + "The libc++ test suite will be disabled.") + set(LLVM_INCLUDE_TESTS OFF) + endif() + + if (NOT DEFINED LLVM_INCLUDE_TESTS) + set(LLVM_INCLUDE_TESTS ${LLVM_FOUND}) + endif() + if (NOT DEFINED LLVM_INCLUDE_DOCS) + set(LLVM_INCLUDE_DOCS ${LLVM_FOUND}) + endif() + if (NOT DEFINED LLVM_ENABLE_SPHINX) + set(LLVM_ENABLE_SPHINX OFF) + endif() + + # Required LIT Configuration ------------------------------------------------ + # Define the default arguments to use with 'lit', and an option for the user + # to override. + set(LIT_ARGS_DEFAULT "-sv --show-xfail --show-unsupported") + if (MSVC OR XCODE) + set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") + endif() + set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") + + # Required doc configuration + if (LLVM_ENABLE_SPHINX) + message(STATUS "Sphinx enabled.") + find_package(Sphinx REQUIRED) + else() + message(STATUS "Sphinx disabled.") + endif() + + # FIXME - This is cribbed from HandleLLVMOptions.cmake. + if(WIN32) + set(LLVM_HAVE_LINK_VERSION_SCRIPT 0) + if(CYGWIN) + set(LLVM_ON_WIN32 0) + set(LLVM_ON_UNIX 1) + else(CYGWIN) + set(LLVM_ON_WIN32 1) + set(LLVM_ON_UNIX 0) + endif(CYGWIN) + else(WIN32) + if(UNIX) + set(LLVM_ON_WIN32 0) + set(LLVM_ON_UNIX 1) + if(APPLE) + set(LLVM_HAVE_LINK_VERSION_SCRIPT 0) + else(APPLE) + set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) + endif(APPLE) + else(UNIX) + MESSAGE(SEND_ERROR "Unable to determine platform") + endif(UNIX) + endif(WIN32) + + # Add LLVM Functions -------------------------------------------------------- + include(AddLLVM OPTIONAL) +endif() diff --git a/sdk/tlibcxx/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake b/sdk/tlibcxx/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake new file mode 100644 index 00000000..a0669365 --- /dev/null +++ b/sdk/tlibcxx/cmake/Modules/MacroEnsureOutOfSourceBuild.cmake @@ -0,0 +1,18 @@ +# MACRO_ENSURE_OUT_OF_SOURCE_BUILD() + +macro( MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage ) + +string( COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource ) +if( _insource ) + message( SEND_ERROR "${_errorMessage}" ) + message( FATAL_ERROR + "In-source builds are not allowed. + CMake would overwrite the makefiles distributed with Compiler-RT. + Please create a directory and run cmake from there, passing the path + to this source directory as the last argument. + This process created the file `CMakeCache.txt' and the directory `CMakeFiles'. + Please delete them." + ) +endif( _insource ) + +endmacro( MACRO_ENSURE_OUT_OF_SOURCE_BUILD ) diff --git a/sdk/tlibcxx/cmake/config-ix.cmake b/sdk/tlibcxx/cmake/config-ix.cmake new file mode 100644 index 00000000..3e6c3599 --- /dev/null +++ b/sdk/tlibcxx/cmake/config-ix.cmake @@ -0,0 +1,20 @@ +include(CheckLibraryExists) +include(CheckCXXCompilerFlag) +include(CheckLibcxxAtomic) + +# Check compiler flags + +check_cxx_compiler_flag(/WX LIBCXX_HAS_WX_FLAG) +check_cxx_compiler_flag(/WX- LIBCXX_HAS_NO_WX_FLAG) +check_cxx_compiler_flag(/EHsc LIBCXX_HAS_EHSC_FLAG) +check_cxx_compiler_flag(/EHs- LIBCXX_HAS_NO_EHS_FLAG) +check_cxx_compiler_flag(/EHa- LIBCXX_HAS_NO_EHA_FLAG) +check_cxx_compiler_flag(/GR- LIBCXX_HAS_NO_GR_FLAG) + + +# Check libraries +check_library_exists(pthread pthread_create "" LIBCXX_HAS_PTHREAD_LIB) +check_library_exists(c fopen "" LIBCXX_HAS_C_LIB) +check_library_exists(m ccos "" LIBCXX_HAS_M_LIB) +check_library_exists(rt clock_gettime "" LIBCXX_HAS_RT_LIB) +check_library_exists(gcc_s __gcc_personality_v0 "" LIBCXX_HAS_GCC_S_LIB) diff --git a/sdk/tlibcxx/docs/BuildingLibcxx.rst b/sdk/tlibcxx/docs/BuildingLibcxx.rst new file mode 100644 index 00000000..36866b13 --- /dev/null +++ b/sdk/tlibcxx/docs/BuildingLibcxx.rst @@ -0,0 +1,416 @@ +.. _BuildingLibcxx: + +=============== +Building libc++ +=============== + +.. contents:: + :local: + +.. _build instructions: + +Getting Started +=============== + +On Mac OS 10.7 (Lion) and later, the easiest way to get this library is to install +Xcode 4.2 or later. However if you want to install tip-of-trunk from here +(getting the bleeding edge), read on. + +The basic steps needed to build libc++ are: + +#. Checkout LLVM: + + * ``cd where-you-want-llvm-to-live`` + * ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm`` + +#. Checkout libc++: + + * ``cd where-you-want-llvm-to-live`` + * ``cd llvm/projects`` + * ``svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx`` + +#. Checkout libc++abi: + + * ``cd where-you-want-llvm-to-live`` + * ``cd llvm/projects`` + * ``svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi`` + +#. Configure and build libc++ with libc++abi: + + CMake is the only supported configuration system. + + Clang is the preferred compiler when building and using libc++. + + * ``cd where you want to build llvm`` + * ``mkdir build`` + * ``cd build`` + * ``cmake -G [options] `` + + For more information about configuring libc++ see :ref:`CMake Options`. + + * ``make cxx`` --- will build libc++ and libc++abi. + * ``make check-libcxx check-libcxxabi`` --- will run the test suites. + + Shared libraries for libc++ and libc++ abi should now be present in llvm/build/lib. + See :ref:`using an alternate libc++ installation ` + +#. **Optional**: Install libc++ and libc++abi + + If your system already provides a libc++ installation it is important to be + careful not to replace it. Remember Use the CMake option ``CMAKE_INSTALL_PREFIX`` to + select a safe place to install libc++. + + * ``make install-libcxx install-libcxxabi`` --- Will install the libraries and the headers + + .. warning:: + * Replacing your systems libc++ installation could render the system non-functional. + * Mac OS X will not boot without a valid copy of ``libc++.1.dylib`` in ``/usr/lib``. + + +The instructions are for building libc++ on +FreeBSD, Linux, or Mac using `libc++abi`_ as the C++ ABI library. +On Linux, it is also possible to use :ref:`libsupc++ ` or libcxxrt. + +It is sometimes beneficial to build outside of the LLVM tree. An out-of-tree +build would look like this: + +.. code-block:: bash + + $ cd where-you-want-libcxx-to-live + $ # Check out llvm, libc++ and libc++abi. + $ ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm`` + $ ``svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx`` + $ ``svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk libcxxabi`` + $ cd where-you-want-to-build + $ mkdir build && cd build + $ export CC=clang CXX=clang++ + $ cmake -DLLVM_PATH=path/to/llvm \ + -DLIBCXX_CXX_ABI=libcxxabi \ + -DLIBCXX_CXX_ABI_INCLUDE_PATHS=path/to/libcxxabi/include \ + path/to/libcxx + $ make + $ make check-libcxx # optional + + +.. _`libc++abi`: http://libcxxabi.llvm.org/ + + +.. _CMake Options: + +CMake Options +============= + +Here are some of the CMake variables that are used often, along with a +brief explanation and LLVM-specific notes. For full documentation, check the +CMake docs or execute ``cmake --help-variable VARIABLE_NAME``. + +**CMAKE_BUILD_TYPE**:STRING + Sets the build type for ``make`` based generators. Possible values are + Release, Debug, RelWithDebInfo and MinSizeRel. On systems like Visual Studio + the user sets the build type with the IDE settings. + +**CMAKE_INSTALL_PREFIX**:PATH + Path where LLVM will be installed if "make install" is invoked or the + "INSTALL" target is built. + +**CMAKE_CXX_COMPILER**:STRING + The C++ compiler to use when building and testing libc++. + + +.. _libcxx-specific options: + +libc++ specific options +----------------------- + +.. option:: LIBCXX_INSTALL_LIBRARY:BOOL + + **Default**: ``ON`` + + Toggle the installation of the library portion of libc++. + +.. option:: LIBCXX_INSTALL_HEADERS:BOOL + + **Default**: ``ON`` + + Toggle the installation of the libc++ headers. + +.. option:: LIBCXX_ENABLE_ASSERTIONS:BOOL + + **Default**: ``ON`` + + Build libc++ with assertions enabled. + +.. option:: LIBCXX_BUILD_32_BITS:BOOL + + **Default**: ``OFF`` + + Build libc++ as a 32 bit library. Also see :option:`LLVM_BUILD_32_BITS`. + +.. option:: LIBCXX_ENABLE_SHARED:BOOL + + **Default**: ``ON`` + + Build libc++ as a shared library. If ``OFF`` is specified then libc++ is + built as a static library. + +.. option:: LIBCXX_LIBDIR_SUFFIX:STRING + + Extra suffix to append to the directory where libraries are to be installed. + This option overrides :option:`LLVM_LIBDIR_SUFFIX`. + + +.. _libc++experimental options: + +libc++experimental Specific Options +------------------------------------ + +.. option:: LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY:BOOL + + **Default**: ``ON`` + + Build and test libc++experimental.a. + +.. option:: LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY:BOOL + + **Default**: ``OFF`` + + Install libc++experimental.a alongside libc++. + + +.. option:: LIBCXX_ENABLE_FILESYSTEM:BOOL + + **Default**: ``LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY`` + + Build filesystem as part of libc++experimental.a. This allows filesystem + to be disabled without turning off the entire experimental library. + + +.. _ABI Library Specific Options: + +ABI Library Specific Options +---------------------------- + +.. option:: LIBCXX_CXX_ABI:STRING + + **Values**: ``none``, ``libcxxabi``, ``libcxxrt``, ``libstdc++``, ``libsupc++``. + + Select the ABI library to build libc++ against. + +.. option:: LIBCXX_CXX_ABI_INCLUDE_PATHS:PATHS + + Provide additional search paths for the ABI library headers. + +.. option:: LIBCXX_CXX_ABI_LIBRARY_PATH:PATH + + Provide the path to the ABI library that libc++ should link against. + +.. option:: LIBCXX_ENABLE_STATIC_ABI_LIBRARY:BOOL + + **Default**: ``OFF`` + + If this option is enabled, libc++ will try and link the selected ABI library + statically. + +.. option:: LIBCXX_ENABLE_ABI_LINKER_SCRIPT:BOOL + + **Default**: ``ON`` by default on UNIX platforms other than Apple unless + 'LIBCXX_ENABLE_STATIC_ABI_LIBRARY' is ON. Otherwise the default value is ``OFF``. + + This option generate and installs a linker script as ``libc++.so`` which + links the correct ABI library. + +.. option:: LIBCXXABI_USE_LLVM_UNWINDER:BOOL + + **Default**: ``OFF`` + + Build and use the LLVM unwinder. Note: This option can only be used when + libc++abi is the C++ ABI library used. + + +libc++ Feature options +---------------------- + +.. option:: LIBCXX_ENABLE_EXCEPTIONS:BOOL + + **Default**: ``ON`` + + Build libc++ with exception support. + +.. option:: LIBCXX_ENABLE_RTTI:BOOL + + **Default**: ``ON`` + + Build libc++ with run time type information. + + +libc++ Feature options +---------------------- + +The following options allow building libc++ for a different ABI version. + +.. option:: LIBCXX_ABI_VERSION:STRING + + **Default**: ``1`` + + Defines the target ABI version of libc++. + +.. option:: LIBCXX_ABI_UNSTABLE:BOOL + + **Default**: ``OFF`` + + Build the "unstable" ABI version of libc++. Includes all ABI changing features + on top of the current stable version. + +.. _LLVM-specific variables: + +LLVM-specific options +--------------------- + +.. option:: LLVM_LIBDIR_SUFFIX:STRING + + Extra suffix to append to the directory where libraries are to be + installed. On a 64-bit architecture, one could use ``-DLLVM_LIBDIR_SUFFIX=64`` + to install libraries to ``/usr/lib64``. + +.. option:: LLVM_BUILD_32_BITS:BOOL + + Build 32-bits executables and libraries on 64-bits systems. This option is + available only on some 64-bits unix systems. Defaults to OFF. + +.. option:: LLVM_LIT_ARGS:STRING + + Arguments given to lit. ``make check`` and ``make clang-test`` are affected. + By default, ``'-sv --no-progress-bar'`` on Visual C++ and Xcode, ``'-sv'`` on + others. + + +Using Alternate ABI libraries +============================= + + +.. _libsupcxx: + +Using libsupc++ on Linux +------------------------ + +You will need libstdc++ in order to provide libsupc++. + +Figure out where the libsupc++ headers are on your system. On Ubuntu this +is ``/usr/include/c++/`` and ``/usr/include/c++//`` + +You can also figure this out by running + +.. code-block:: bash + + $ echo | g++ -Wp,-v -x c++ - -fsyntax-only + ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" + ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/include" + #include "..." search starts here: + #include <...> search starts here: + /usr/include/c++/4.7 + /usr/include/c++/4.7/x86_64-linux-gnu + /usr/include/c++/4.7/backward + /usr/lib/gcc/x86_64-linux-gnu/4.7/include + /usr/local/include + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed + /usr/include/x86_64-linux-gnu + /usr/include + End of search list. + +Note that the first two entries happen to be what we are looking for. This +may not be correct on other platforms. + +We can now run CMake: + +.. code-block:: bash + + $ CC=clang CXX=clang++ cmake -G "Unix Makefiles" \ + -DLIBCXX_CXX_ABI=libstdc++ \ + -DLIBCXX_CXX_ABI_INCLUDE_PATHS="/usr/include/c++/4.7/;/usr/include/c++/4.7/x86_64-linux-gnu/" \ + -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr \ + + + +You can also substitute ``-DLIBCXX_CXX_ABI=libsupc++`` +above, which will cause the library to be linked to libsupc++ instead +of libstdc++, but this is only recommended if you know that you will +never need to link against libstdc++ in the same executable as libc++. +GCC ships libsupc++ separately but only as a static library. If a +program also needs to link against libstdc++, it will provide its +own copy of libsupc++ and this can lead to subtle problems. + +.. code-block:: bash + + $ make cxx + $ make install + +You can now run clang with -stdlib=libc++. + + +.. _libcxxrt_ref: + +Using libcxxrt on Linux +------------------------ + +You will need to keep the source tree of `libcxxrt`_ available +on your build machine and your copy of the libcxxrt shared library must +be placed where your linker will find it. + +We can now run CMake like: + +.. code-block:: bash + + $ CC=clang CXX=clang++ cmake -G "Unix Makefiles" \ + -DLIBCXX_CXX_ABI=libcxxrt \ + -DLIBCXX_CXX_ABI_INCLUDE_PATHS=path/to/libcxxrt-sources/src \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=/usr \ + + $ make cxx + $ make install + +Unfortunately you can't simply run clang with "-stdlib=libc++" at this point, as +clang is set up to link for libc++ linked to libsupc++. To get around this +you'll have to set up your linker yourself (or patch clang). For example, + +.. code-block:: bash + + $ clang++ -stdlib=libc++ helloworld.cpp \ + -nodefaultlibs -lc++ -lcxxrt -lm -lc -lgcc_s -lgcc + +Alternately, you could just add libcxxrt to your libraries list, which in most +situations will give the same result: + +.. code-block:: bash + + $ clang++ -stdlib=libc++ helloworld.cpp -lcxxrt + +.. _`libcxxrt`: https://github.com/pathscale/libcxxrt/ + + +Using a local ABI library installation +--------------------------------------- + +.. warning:: + This is not recommended in almost all cases. + +These instructions should only be used when you can't install your ABI library. + +Normally you must link libc++ against a ABI shared library that the +linker can find. If you want to build and test libc++ against an ABI +library not in the linker's path you needq to set +``-DLIBCXX_CXX_ABI_LIBRARY_PATH=/path/to/abi/lib`` when configuring CMake. + +An example build using libc++abi would look like: + +.. code-block:: bash + + $ CC=clang CXX=clang++ cmake \ + -DLIBCXX_CXX_ABI=libc++abi \ + -DLIBCXX_CXX_ABI_INCLUDE_PATHS="/path/to/libcxxabi/include" \ + -DLIBCXX_CXX_ABI_LIBRARY_PATH="/path/to/libcxxabi-build/lib" \ + path/to/libcxx + $ make + +When testing libc++ LIT will automatically link against the proper ABI +library. diff --git a/sdk/tlibcxx/docs/CMakeLists.txt b/sdk/tlibcxx/docs/CMakeLists.txt new file mode 100644 index 00000000..f63ee00a --- /dev/null +++ b/sdk/tlibcxx/docs/CMakeLists.txt @@ -0,0 +1,9 @@ + +if (LLVM_ENABLE_SPHINX) + if (SPHINX_FOUND) + include(AddSphinxTarget) + if (${SPHINX_OUTPUT_HTML}) + add_sphinx_target(html libcxx) + endif() + endif() +endif() \ No newline at end of file diff --git a/sdk/tlibcxx/docs/DesignDocs/ABIVersioning.rst b/sdk/tlibcxx/docs/DesignDocs/ABIVersioning.rst new file mode 100644 index 00000000..5960dd18 --- /dev/null +++ b/sdk/tlibcxx/docs/DesignDocs/ABIVersioning.rst @@ -0,0 +1,17 @@ + +==================== +Libc++ ABI stability +==================== + +Libc++ aims to preserve stable ABI to avoid subtle bugs when code built to the old ABI +is linked with the code build to the new ABI. At the same time, libc++ allows ABI-breaking +improvements and bugfixes for the scenarios when ABI change is not a issue. + +To support both cases, libc++ allows specifying the ABI version at the +build time. The version is defined with a cmake option +LIBCXX_ABI_VERSION. Another option LIBCXX_ABI_UNSTABLE can be used to +include all present ABI breaking features. These options translate +into C++ macro definitions _LIBCPP_ABI_VERSION, _LIBCPP_ABI_UNSTABLE. + +Any ABI-changing feature is placed under it's own macro, _LIBCPP_ABI_XXX, which is enabled +based on the value of _LIBCPP_ABI_VERSION. _LIBCPP_ABI_UNSTABLE, if set, enables all features at once. diff --git a/sdk/tlibcxx/docs/DesignDocs/CapturingConfigInfo.rst b/sdk/tlibcxx/docs/DesignDocs/CapturingConfigInfo.rst new file mode 100644 index 00000000..73378a21 --- /dev/null +++ b/sdk/tlibcxx/docs/DesignDocs/CapturingConfigInfo.rst @@ -0,0 +1,88 @@ +======================================================= +Capturing configuration information during installation +======================================================= + +.. contents:: + :local: + +The Problem +=========== + +Currently the libc++ supports building the library with a number of different +configuration options. Unfortunately all of that configuration information is +lost when libc++ is installed. In order to support "persistent" +configurations libc++ needs a mechanism to capture the configuration options +in the INSTALLED headers. + + +Design Goals +============ + +* The solution should not INSTALL any additional headers. We don't want an extra + #include slowing everybody down. + +* The solution should not unduly affect libc++ developers. The problem is limited + to installed versions of libc++ and the solution should be as well. + +* The solution should not modify any existing headers EXCEPT during installation. + It makes developers lives harder if they have to regenerate the libc++ headers + every time they are modified. + +* The solution should not make any of the libc++ headers dependant on + files generated by the build system. The headers should be able to compile + out of the box without any modification. + +* The solution should not have ANY effect on users who don't need special + configuration options. The vast majority of users will never need this so it + shouldn't cost them. + + +The Solution +============ + +When you first configure libc++ using CMake we check to see if we need to +capture any options. If we haven't been given any "persistent" options then +we do NOTHING. + +Otherwise we create a custom installation rule that modifies the installed __config +header. The rule first generates a dummy "__config_site" header containing the required +#defines. The contents of the dummy header are then prependend to the installed +__config header. By manually prepending the files we avoid the cost of an +extra #include and we allow the __config header to be ignorant of the extra +configuration all together. An example "__config" header generated when +-DLIBCXX_ENABLE_THREADS=OFF is given to CMake would look something like: + +.. code-block:: cpp + + //===----------------------------------------------------------------------===// + // + // 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. + // + //===----------------------------------------------------------------------===// + + #ifndef _LIBCPP_CONFIG_SITE + #define _LIBCPP_CONFIG_SITE + + /* #undef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE */ + /* #undef _LIBCPP_HAS_NO_STDIN */ + /* #undef _LIBCPP_HAS_NO_STDOUT */ + #define _LIBCPP_HAS_NO_THREADS + /* #undef _LIBCPP_HAS_NO_MONOTONIC_CLOCK */ + /* #undef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS */ + + #endif + // -*- C++ -*- + //===--------------------------- __config ---------------------------------===// + // + // 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. + // + //===----------------------------------------------------------------------===// + + #ifndef _LIBCPP_CONFIG + #define _LIBCPP_CONFIG diff --git a/sdk/tlibcxx/docs/Makefile.sphinx b/sdk/tlibcxx/docs/Makefile.sphinx new file mode 100644 index 00000000..2ca1e4d3 --- /dev/null +++ b/sdk/tlibcxx/docs/Makefile.sphinx @@ -0,0 +1,37 @@ +# Makefile for Sphinx documentation +# +# FIXME: This hack is only in place to allow the libcxx.llvm.org/docs builder +# to work with libcxx. This should be removed when that builder supports +# out-of-tree builds. + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext default + +default: html + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @# FIXME: Remove this `cp` once HTML->Sphinx transition is completed. + @# Kind of a hack, but HTML-formatted docs are on the way out anyway. + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + diff --git a/sdk/tlibcxx/docs/README.txt b/sdk/tlibcxx/docs/README.txt new file mode 100644 index 00000000..06d94f5b --- /dev/null +++ b/sdk/tlibcxx/docs/README.txt @@ -0,0 +1,13 @@ +libc++ Documentation +==================== + +The libc++ documentation is written using the Sphinx documentation generator. It is +currently tested with Sphinx 1.1.3. + +To build the documents into html configure libc++ with the following cmake options: + + * -DLLVM_ENABLE_SPHINX=ON + * -DLIBCXX_INCLUDE_DOCS=ON + +After configuring libc++ with these options the make rule `docs-libcxx-html` +should be available. diff --git a/sdk/tlibcxx/docs/TestingLibcxx.rst b/sdk/tlibcxx/docs/TestingLibcxx.rst new file mode 100644 index 00000000..9226ae17 --- /dev/null +++ b/sdk/tlibcxx/docs/TestingLibcxx.rst @@ -0,0 +1,200 @@ +============== +Testing libc++ +============== + +.. contents:: + :local: + +Getting Started +=============== + +libc++ uses LIT to configure and run its tests. The primary way to run the +libc++ tests is by using make check-libcxx. However since libc++ can be used +in any number of possible configurations it is important to customize the way +LIT builds and runs the tests. This guide provides information on how to use +LIT directly to test libc++. + +Please see the `Lit Command Guide`_ for more information about LIT. + +.. _LIT Command Guide: http://llvm.org/docs/CommandGuide/lit.html + +Setting up the Environment +-------------------------- + +After building libc++ you must setup your environment to test libc++ using +LIT. + +#. Create a shortcut to the actual lit executable so that you can invoke it + easily from the command line. + + .. code-block:: bash + + $ alias lit='python path/to/llvm/utils/lit/lit.py' + +#. Tell LIT where to find your build configuration. + + .. code-block:: bash + + $ export LIBCXX_SITE_CONFIG=path/to/build-libcxx/test/lit.site.cfg + +Example Usage +------------- + +Once you have your environment set up and you have built libc++ you can run +parts of the libc++ test suite by simply running `lit` on a specified test or +directory. For example: + +.. code-block:: bash + + $ cd path/to/src/libcxx + $ lit -sv test/std/re # Run all of the std::regex tests + $ lit -sv test/std/depr/depr.c.headers/stdlib_h.pass.cpp # Run a single test + $ lit -sv test/std/atomics test/std/threads # Test std::thread and std::atomic + +Sometimes you'll want to change the way LIT is running the tests. Custom options +can be specified using the `--param==` flag. The most common option +you'll want to change is the standard dialect (ie -std=c++XX). By default the +test suite will select the newest C++ dialect supported by the compiler and use +that. However if you want to manually specify the option like so: + +.. code-block:: bash + + $ lit -sv test/std/containers # Run the tests with the newest -std + $ lit -sv --param=std=c++03 test/std/containers # Run the tests in C++03 + +Occasionally you'll want to add extra compile or link flags when testing. +You can do this as follows: + +.. code-block:: bash + + $ lit -sv --param=compile_flags='-Wcustom-warning' + $ lit -sv --param=link_flags='-L/custom/library/path' + +Some other common examples include: + +.. code-block:: bash + + # Specify a custom compiler. + $ lit -sv --param=cxx_under_test=/opt/bin/g++ test/std + + # Enable warnings in the test suite + $ lit -sv --param=enable_warnings=true test/std + + # Use UBSAN when running the tests. + $ lit -sv --param=use_sanitizer=Undefined + + +LIT Options +=========== + +:program:`lit` [*options*...] [*filenames*...] + +Command Line Options +-------------------- + +To use these options you pass them on the LIT command line as --param NAME or +--param NAME=VALUE. Some options have default values specified during CMake's +configuration. Passing the option on the command line will override the default. + +.. program:: lit + +.. option:: --cxx_under_test= + + Specify the compiler used to build the tests. + +.. option:: std= + + **Values**: c++98, c++03, c++11, c++14, c++1z + + Change the standard version used when building the tests. + +.. option:: --libcxx_site_config= + + Specify the site configuration to use when running the tests. This option + overrides the enviroment variable LIBCXX_SITE_CONFIG. + +.. option:: --libcxx_headers= + + Specify the libc++ headers that are tested. By default the headers in the + source tree are used. + +.. option:: --cxx_library_root= + + Specify the directory of the libc++ library to be tested. By default the + library folder of the build directory is used. This option cannot be used + when use_system_lib is provided. + + +.. option:: --cxx_runtime_root= + + Specify the directory of the libc++ library to use at runtime. This directory + is not added to the linkers search path. This can be used to compile tests + against one version of libc++ and run them using another. The default value + for this option is `cxx_library_root`. This option cannot be used + when use_system_lib is provided. + +.. option:: --use_system_lib= + + **Default**: False + + Enable or disable testing against the installed version of libc++ library. + Note: This does not use the installed headers. + +.. option:: --use_lit_shell= + + Enable or disable the use of LIT's internal shell in ShTests. If the + environment variable LIT_USE_INTERNAL_SHELL is present then that is used as + the default value. Otherwise the default value is True on Windows and False + on every other platform. + +.. option:: --no_default_flags= + + **Default**: False + + Disable all default compile and link flags from being added. When this + option is used only flags specified using the compile_flags and link_flags + will be used. + +.. option:: --compile_flags="" + + Specify additional compile flags as a space delimited string. + Note: This options should not be used to change the standard version used. + +.. option:: --link_flags="" + + Specify additional link flags as a space delimited string. + +.. option:: --debug_level= + + **Values**: 0, 1 + + Enable the use of debug mode. Level 0 enables assertions and level 1 enables + assertions and debugging of iterator misuse. + +.. option:: use_sanitizer= + + **Values**: Memory, MemoryWithOrigins, Address, Undefined + + Run the tests using the given sanitizer. If LLVM_USE_SANITIZER was given when + building libc++ then that sanitizer will be used by default. + +.. option:: color_diagnostics + + Enable the use of colorized compile diagnostics. If the color_diagnostics + option is specified or the environment variable LIBCXX_COLOR_DIAGNOSTICS is + present then color diagnostics will be enabled. + + +Environment Variables +--------------------- + +.. envvar:: LIBCXX_SITE_CONFIG= + + Specify the site configuration to use when running the tests. + Also see :option:`libcxx_site_config`. + +.. envvar:: LIBCXX_COLOR_DIAGNOSTICS + + If ``LIBCXX_COLOR_DIAGNOSTICS`` is defined then the test suite will attempt + to use color diagnostic outputs from the compiler. + Also see :option:`color_diagnostics`. diff --git a/sdk/tlibcxx/docs/UsingLibcxx.rst b/sdk/tlibcxx/docs/UsingLibcxx.rst new file mode 100644 index 00000000..514ed14b --- /dev/null +++ b/sdk/tlibcxx/docs/UsingLibcxx.rst @@ -0,0 +1,125 @@ +============ +Using libc++ +============ + +.. contents:: + :local: + +Getting Started +=============== + +If you already have libc++ installed you can use it with clang. + +.. code-block:: bash + + $ clang++ -stdlib=libc++ test.cpp + $ clang++ -std=c++11 -stdlib=libc++ test.cpp + +On OS X and FreeBSD libc++ is the default standard library +and the ``-stdlib=libc++`` is not required. + +.. _alternate libcxx: + +If you want to select an alternate installation of libc++ you +can use the following options. + +.. code-block:: bash + + $ clang++ -std=c++11 -stdlib=libc++ -nostdinc++ \ + -I/include/c++/v1 \ + -L/lib \ + -Wl,-rpath,/lib \ + test.cpp + +The option ``-Wl,-rpath,/lib`` adds a runtime library +search path. Meaning that the systems dynamic linker will look for libc++ in +``/lib`` whenever the program is run. Alternatively the +environment variable ``LD_LIBRARY_PATH`` (``DYLD_LIBRARY_PATH`` on OS X) can +be used to change the dynamic linkers search paths after a program is compiled. + +An example of using ``LD_LIBRARY_PATH``: + +.. code-block:: bash + + $ clang++ -stdlib=libc++ -nostdinc++ \ + -I/include/c++/v1 + -L/lib \ + test.cpp -o + $ ./a.out # Searches for libc++ in the systems library paths. + $ export LD_LIBRARY_PATH=/lib + $ ./a.out # Searches for libc++ along LD_LIBRARY_PATH + +Using libc++experimental and ```` +===================================================== + +Libc++ provides implementations of experimental technical specifications +in a separate library, ``libc++experimental.a``. Users of ```` +headers may be required to link ``-lc++experimental``. + +.. code-block:: bash + + $ clang++ -std=c++14 -stdlib=libc++ test.cpp -lc++experimental + +Libc++experimental.a may not always be available, even when libc++ is already +installed. For information on building libc++experimental from source see +:ref:`Building Libc++ ` and +:ref:`libc++experimental CMake Options `. + +Also see the `Experimental Library Implementation Status `__ +page. + +.. warning:: + Experimental libraries are Experimental. + * The contents of the ```` headers and ``libc++experimental.a`` + library will not remain compatible between versions. + * No guarantees of API or ABI stability are provided. + +Using libc++ on Linux +===================== + +On Linux libc++ can typically be used with only '-stdlib=libc++'. However +some libc++ installations require the user manually link libc++abi themselves. +If you are running into linker errors when using libc++ try adding '-lc++abi' +to the link line. For example: + +.. code-block:: bash + + $ clang++ -stdlib=libc++ test.cpp -lc++ -lc++abi -lm -lc -lgcc_s -lgcc + +Alternately, you could just add libc++abi to your libraries list, which in +most situations will give the same result: + +.. code-block:: bash + + $ clang++ -stdlib=libc++ test.cpp -lc++abi + + +Using libc++ with GCC +--------------------- + +GCC does not provide a way to switch from libstdc++ to libc++. You must manually +configure the compile and link commands. + +In particular you must tell GCC to remove the libstdc++ include directories +using ``-nostdinc++`` and to not link libstdc++.so using ``-nodefaultlibs``. + +Note that ``-nodefaultlibs`` removes all of the standard system libraries and +not just libstdc++ so they must be manually linked. For example: + +.. code-block:: bash + + $ g++ -nostdinc++ -I/include/c++/v1 \ + test.cpp -nodefaultlibs -lc++ -lc++abi -lm -lc -lgcc_s -lgcc + + +GDB Pretty printers for libc++ +------------------------------ + +GDB does not support pretty-printing of libc++ symbols by default. Unfortunately +libc++ does not provide pretty-printers itself. However there are 3rd +party implementations available and although they are not officially +supported by libc++ they may be useful to users. + +Known 3rd Party Implementations Include: + +* `Koutheir's libc++ pretty-printers `_. diff --git a/sdk/tlibcxx/docs/conf.py b/sdk/tlibcxx/docs/conf.py new file mode 100644 index 00000000..e385406b --- /dev/null +++ b/sdk/tlibcxx/docs/conf.py @@ -0,0 +1,251 @@ +# -*- coding: utf-8 -*- +# +# libc++ documentation build configuration file. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'libc++' +copyright = u'2011-2016, LLVM Project' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '3.9' +# The full version, including alpha/beta/rc tags. +release = '3.9' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +today_fmt = '%Y-%m-%d' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +show_authors = True + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'friendly' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'haiku' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'libcxxdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('contents', 'libcxx.tex', u'libcxx Documentation', + u'LLVM project', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('contents', 'libc++', u'libc++ Documentation', + [u'LLVM project'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('contents', 'libc++', u'libc++ Documentation', + u'LLVM project', 'libc++', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# FIXME: Define intersphinx configration. +intersphinx_mapping = {} + + +# -- Options for extensions ---------------------------------------------------- + +# Enable this if you want TODOs to show up in the generated documentation. +todo_include_todos = True diff --git a/sdk/tlibcxx/docs/index.rst b/sdk/tlibcxx/docs/index.rst new file mode 100644 index 00000000..b0c8b813 --- /dev/null +++ b/sdk/tlibcxx/docs/index.rst @@ -0,0 +1,185 @@ +.. _index: + +============================= +"libc++" C++ Standard Library +============================= + +Overview +======== + +libc++ is a new implementation of the C++ standard library, targeting C++11. + +* Features and Goals + + * Correctness as defined by the C++11 standard. + * Fast execution. + * Minimal memory use. + * Fast compile times. + * ABI compatibility with gcc's libstdc++ for some low-level features + such as exception objects, rtti and memory allocation. + * Extensive unit tests. + +* Design and Implementation: + + * Extensive unit tests + * Internal linker model can be dumped/read to textual format + * Additional linking features can be plugged in as "passes" + * OS specific and CPU specific code factored out + + +Getting Started with libc++ +--------------------------- + +.. toctree:: + :maxdepth: 2 + + UsingLibcxx + BuildingLibcxx + TestingLibcxx + + +Current Status +-------------- + +After its initial introduction, many people have asked "why start a new +library instead of contributing to an existing library?" (like Apache's +libstdcxx, GNU's libstdc++, STLport, etc). There are many contributing +reasons, but some of the major ones are: + +* From years of experience (including having implemented the standard + library before), we've learned many things about implementing + the standard containers which require ABI breakage and fundamental changes + to how they are implemented. For example, it is generally accepted that + building std::string using the "short string optimization" instead of + using Copy On Write (COW) is a superior approach for multicore + machines (particularly in C++11, which has rvalue references). Breaking + ABI compatibility with old versions of the library was + determined to be critical to achieving the performance goals of + libc++. + +* Mainline libstdc++ has switched to GPL3, a license which the developers + of libc++ cannot use. libstdc++ 4.2 (the last GPL2 version) could be + independently extended to support C++11, but this would be a fork of the + codebase (which is often seen as worse for a project than starting a new + independent one). Another problem with libstdc++ is that it is tightly + integrated with G++ development, tending to be tied fairly closely to the + matching version of G++. + +* STLport and the Apache libstdcxx library are two other popular + candidates, but both lack C++11 support. Our experience (and the + experience of libstdc++ developers) is that adding support for C++11 (in + particular rvalue references and move-only types) requires changes to + almost every class and function, essentially amounting to a rewrite. + Faced with a rewrite, we decided to start from scratch and evaluate every + design decision from first principles based on experience. + Further, both projects are apparently abandoned: STLport 5.2.1 was + released in Oct'08, and STDCXX 4.2.1 in May'08. + +Platform and Compiler Support +----------------------------- + +libc++ is known to work on the following platforms, using gcc-4.2 and +clang (lack of C++11 language support disables some functionality). +Note that functionality provided by ```` is only functional with clang +and GCC. + +============ ==================== ============ ======================== +OS Arch Compilers ABI Library +============ ==================== ============ ======================== +Mac OS X i386, x86_64 Clang, GCC libc++abi +FreeBSD 10+ i386, x86_64, ARM Clang, GCC libcxxrt, libc++abi +Linux i386, x86_64 Clang, GCC libc++abi +============ ==================== ============ ======================== + +The following minimum compiler versions are strongly recommended. + +* Clang 3.5 and above +* GCC 4.7 and above. + +Anything older *may* work. + +C++ Dialect Support +--------------------- + +* C++11 - Complete +* `C++14 - Complete `__ +* `C++1z - In Progress `__ +* `Post C++14 Technical Specifications - In Progress `__ + +Notes and Known Issues +---------------------- + +This list contains known issues with libc++ + +* Building libc++ with ``-fno-rtti`` is not supported. However + linking against it with ``-fno-rtti`` is supported. +* On OS X v10.8 and older the CMake option ``-DLIBCXX_LIBCPPABI_VERSION=""`` + must be used during configuration. + + +A full list of currently open libc++ bugs can be `found here`__. + +.. __: https://llvm.org/bugs/buglist.cgi?component=All%20Bugs&product=libc%2B%2B&query_format=advanced&resolution=---&order=changeddate%20DESC%2Cassigned_to%20DESC%2Cbug_status%2Cpriority%2Cbug_id&list_id=74184 + +Design Documents +---------------- + +.. toctree:: + :maxdepth: 1 + + DesignDocs/CapturingConfigInfo + DesignDocs/ABIVersioning + + +* ` design `_ +* ` design `_ +* `Status of debug mode `_ +* `Notes by Marshall Clow`__ + +.. __: https://cplusplusmusings.wordpress.com/2012/07/05/clang-and-standard-libraries-on-mac-os-x/ + +Build Bots and Test Coverage +---------------------------- + +* `LLVM Buildbot Builders `_ +* `Apple Jenkins Builders `_ +* `EricWF's Nightly Builders `_ +* `Code Coverage Results `_ + +Getting Involved +================ + +First please review our `Developer's Policy `__ +and `Getting started with LLVM `__. + +**Bug Reports** + +If you think you've found a bug in libc++, please report it using +the `LLVM Bugzilla`_. If you're not sure, you +can post a message to the `cfe-dev mailing list`_ or on IRC. +Please include "libc++" in your subject. + +**Patches** + +If you want to contribute a patch to libc++, the best place for that is +`Phabricator `_. Please include [libcxx] in the subject and +add `cfe-commits` as a subscriber. Also make sure you are subscribed to the +`cfe-commits mailing list `_. + +**Discussion and Questions** + +Send discussions and questions to the +`cfe-dev mailing list `_. +Please include [libcxx] in the subject. + + + +Quick Links +=========== +* `LLVM Homepage `_ +* `libc++abi Homepage `_ +* `LLVM Bugzilla `_ +* `cfe-commits Mailing List`_ +* `cfe-dev Mailing List`_ +* `Browse libc++ -- SVN `_ +* `Browse libc++ -- ViewVC `_ diff --git a/sdk/tlibcxx/include/CMakeLists.txt b/sdk/tlibcxx/include/CMakeLists.txt new file mode 100644 index 00000000..219d1b73 --- /dev/null +++ b/sdk/tlibcxx/include/CMakeLists.txt @@ -0,0 +1,63 @@ +if (NOT LIBCXX_INSTALL_SUPPORT_HEADERS) + set(LIBCXX_SUPPORT_HEADER_PATTERN PATTERN "support" EXCLUDE) +endif() + +set(LIBCXX_HEADER_PATTERN + PATTERN "*" + PATTERN "CMakeLists.txt" EXCLUDE + PATTERN ".svn" EXCLUDE + PATTERN "__config_site.in" EXCLUDE + ${LIBCXX_SUPPORT_HEADER_PATTERN} + ) + +file(COPY . + DESTINATION "${CMAKE_BINARY_DIR}/include/c++/v1" + FILES_MATCHING + ${LIBCXX_HEADER_PATTERN} + ) + +if (LIBCXX_INSTALL_HEADERS) + install(DIRECTORY . + DESTINATION include/c++/v1 + COMPONENT libcxx-headers + FILES_MATCHING + ${LIBCXX_HEADER_PATTERN} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + ) + + if (LIBCXX_NEEDS_SITE_CONFIG) + set(UNIX_CAT cat) + if (WIN32) + set(UNIX_CAT type) + endif() + # Generate and install a custom __config header. The new header is created + # by prepending __config_site to the current __config header. + add_custom_command(OUTPUT ${LIBCXX_BINARY_DIR}/__generated_config + COMMAND ${CMAKE_COMMAND} -E copy ${LIBCXX_BINARY_DIR}/__config_site ${LIBCXX_BINARY_DIR}/__generated_config + COMMAND ${UNIX_CAT} ${LIBCXX_SOURCE_DIR}/include/__config >> ${LIBCXX_BINARY_DIR}/__generated_config + DEPENDS ${LIBCXX_SOURCE_DIR}/include/__config + ${LIBCXX_BINARY_DIR}/__config_site + ) + # Add a target that executes the generation commands. + add_custom_target(generate_config_header ALL + DEPENDS ${LIBCXX_BINARY_DIR}/__generated_config) + set(generated_config_deps generate_config_header) + # Install the generated header as __config. + install(FILES ${LIBCXX_BINARY_DIR}/__generated_config + DESTINATION include/c++/v1 + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + RENAME __config + COMPONENT libcxx-headers) + endif() + + if (NOT CMAKE_CONFIGURATION_TYPES) + # this target is just needed as a placeholder for the distribution target + add_custom_target(libcxx-headers) + add_custom_target(install-libcxx-headers + DEPENDS libcxx-headers ${generated_config_deps} + COMMAND "${CMAKE_COMMAND}" + -DCMAKE_INSTALL_COMPONENT=libcxx-headers + -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") + endif() + +endif() diff --git a/sdk/tlibcxx/include/__bit_reference b/sdk/tlibcxx/include/__bit_reference new file mode 100644 index 00000000..1839a30a --- /dev/null +++ b/sdk/tlibcxx/include/__bit_reference @@ -0,0 +1,1296 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___BIT_REFERENCE +#define _LIBCPP___BIT_REFERENCE + +#include <__config> +#include + +#include <__undef_min_max> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// We had to remove the 3rd template param of __bit_iterator to fix a compilation error for VS compiler +#if !defined(_LIBCPP_SGX_CONFIG) +template class __bit_iterator; +#else +template class __bit_iterator; +#endif // !defined(_LIBCPP_SGX_CONFIG) +template class __bit_const_reference; + +template +struct __has_storage_type +{ + static const bool value = false; +}; + +template ::value> +class __bit_reference +{ + typedef typename _Cp::__storage_type __storage_type; + typedef typename _Cp::__storage_pointer __storage_pointer; + + __storage_pointer __seg_; + __storage_type __mask_; + +#if defined(__clang__) || defined(__IBMCPP__) || defined(_LIBCPP_MSVC) + friend typename _Cp::__self; +#else + friend class _Cp::__self; +#endif + friend class __bit_const_reference<_Cp>; + friend class __bit_iterator<_Cp, false>; +public: + _LIBCPP_INLINE_VISIBILITY operator bool() const _NOEXCEPT + {return static_cast(*__seg_ & __mask_);} + _LIBCPP_INLINE_VISIBILITY bool operator ~() const _NOEXCEPT + {return !static_cast(*this);} + + _LIBCPP_INLINE_VISIBILITY + __bit_reference& operator=(bool __x) _NOEXCEPT + { + if (__x) + *__seg_ |= __mask_; + else + *__seg_ &= ~__mask_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT + {return operator=(static_cast(__x));} + + _LIBCPP_INLINE_VISIBILITY void flip() _NOEXCEPT {*__seg_ ^= __mask_;} + _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, false> operator&() const _NOEXCEPT + {return __bit_iterator<_Cp, false>(__seg_, static_cast(__ctz(__mask_)));} +private: + _LIBCPP_INLINE_VISIBILITY + __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT + : __seg_(__s), __mask_(__m) {} +}; + +template +class __bit_reference<_Cp, false> +{ +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT +{ + bool __t = __x; + __x = __y; + __y = __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT +{ + bool __t = __x; + __x = __y; + __y = __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT +{ + bool __t = __x; + __x = __y; + __y = __t; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT +{ + bool __t = __x; + __x = __y; + __y = __t; +} + +template +class __bit_const_reference +{ + typedef typename _Cp::__storage_type __storage_type; + typedef typename _Cp::__const_storage_pointer __storage_pointer; + + __storage_pointer __seg_; + __storage_type __mask_; + +#if defined(__clang__) || defined(__IBMCPP__) || defined(_LIBCPP_MSVC) + friend typename _Cp::__self; +#else + friend class _Cp::__self; +#endif + friend class __bit_iterator<_Cp, true>; +public: + _LIBCPP_INLINE_VISIBILITY + __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT + : __seg_(__x.__seg_), __mask_(__x.__mask_) {} + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator bool() const _NOEXCEPT + {return static_cast(*__seg_ & __mask_);} + + _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, true> operator&() const _NOEXCEPT + {return __bit_iterator<_Cp, true>(__seg_, static_cast(__ctz(__mask_)));} +private: + _LIBCPP_INLINE_VISIBILITY + _LIBCPP_CONSTEXPR + __bit_const_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT + : __seg_(__s), __mask_(__m) {} + + __bit_const_reference& operator=(const __bit_const_reference& __x); +}; + +// find + +template +__bit_iterator<_Cp, _IsConst> +__find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, _IsConst> _It; + typedef typename _It::__storage_type __storage_type; + static const unsigned __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b = *__first.__seg_ & __m; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__ctz(__b))); + if (__n == __dn) + return __first + __n; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) + if (*__first.__seg_) + return _It(__first.__seg_, static_cast(_VSTD::__ctz(*__first.__seg_))); + // do last partial word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = *__first.__seg_ & __m; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__ctz(__b))); + } + return _It(__first.__seg_, static_cast(__n)); +} + +template +__bit_iterator<_Cp, _IsConst> +__find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, _IsConst> _It; + typedef typename _It::__storage_type __storage_type; + static const unsigned __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b = ~*__first.__seg_ & __m; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__ctz(__b))); + if (__n == __dn) + return __first + __n; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) + { + __storage_type __b = ~*__first.__seg_; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__ctz(__b))); + } + // do last partial word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = ~*__first.__seg_ & __m; + if (__b) + return _It(__first.__seg_, static_cast(_VSTD::__ctz(__b))); + } + return _It(__first.__seg_, static_cast(__n)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<_Cp, _IsConst> +find(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value_) +{ + if (static_cast(__value_)) + return __find_bool_true(__first, static_cast(__last - __first)); + return __find_bool_false(__first, static_cast(__last - __first)); +} + +// count + +template +typename __bit_iterator<_Cp, _IsConst>::difference_type +__count_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, _IsConst> _It; + typedef typename _It::__storage_type __storage_type; + typedef typename _It::difference_type difference_type; + static const unsigned __bits_per_word = _It::__bits_per_word; + difference_type __r = 0; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __r = _VSTD::__pop_count(*__first.__seg_ & __m); + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) + __r += _VSTD::__pop_count(*__first.__seg_); + // do last partial word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __r += _VSTD::__pop_count(*__first.__seg_ & __m); + } + return __r; +} + +template +typename __bit_iterator<_Cp, _IsConst>::difference_type +__count_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, _IsConst> _It; + typedef typename _It::__storage_type __storage_type; + typedef typename _It::difference_type difference_type; + static const unsigned __bits_per_word = _It::__bits_per_word; + difference_type __r = 0; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __r = _VSTD::__pop_count(~*__first.__seg_ & __m); + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) + __r += _VSTD::__pop_count(~*__first.__seg_); + // do last partial word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __r += _VSTD::__pop_count(~*__first.__seg_ & __m); + } + return __r; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __bit_iterator<_Cp, _IsConst>::difference_type +count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value_) +{ + if (static_cast(__value_)) + return __count_bool_true(__first, static_cast(__last - __first)); + return __count_bool_false(__first, static_cast(__last - __first)); +} + +// fill_n + +template +void +__fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, false> _It; + typedef typename _It::__storage_type __storage_type; + static const unsigned __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + *__first.__seg_ &= ~__m; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + __storage_type __nw = __n / __bits_per_word; + _VSTD::memset(_VSTD::__to_raw_pointer(__first.__seg_), 0, __nw * sizeof(__storage_type)); + __n -= __nw * __bits_per_word; + // do last partial word + if (__n > 0) + { + __first.__seg_ += __nw; + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + *__first.__seg_ &= ~__m; + } +} + +template +void +__fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n) +{ + typedef __bit_iterator<_Cp, false> _It; + typedef typename _It::__storage_type __storage_type; + static const unsigned __bits_per_word = _It::__bits_per_word; + // do first partial word + if (__first.__ctz_ != 0) + { + __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_); + __storage_type __dn = _VSTD::min(__clz_f, __n); + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + *__first.__seg_ |= __m; + __n -= __dn; + ++__first.__seg_; + } + // do middle whole words + __storage_type __nw = __n / __bits_per_word; + _VSTD::memset(_VSTD::__to_raw_pointer(__first.__seg_), -1, __nw * sizeof(__storage_type)); + __n -= __nw * __bits_per_word; + // do last partial word + if (__n > 0) + { + __first.__seg_ += __nw; + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + *__first.__seg_ |= __m; + } +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n, bool __value_) +{ + if (__n > 0) + { + if (__value_) + __fill_n_true(__first, __n); + else + __fill_n_false(__first, __n); + } +} + +// fill + +template +inline _LIBCPP_INLINE_VISIBILITY +void +fill(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __last, bool __value_) +{ + _VSTD::fill_n(__first, static_cast(__last - __first), __value_); +} + +// copy + +template +__bit_iterator<_Cp, false> +__copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) +{ + typedef __bit_iterator<_Cp, _IsConst> _In; + typedef typename _In::difference_type difference_type; + typedef typename _In::__storage_type __storage_type; + static const unsigned __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__first.__ctz_ != 0) + { + unsigned __clz = __bits_per_word - __first.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); + __storage_type __b = *__first.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + __storage_type __nw = __n / __bits_per_word; + _VSTD::memmove(_VSTD::__to_raw_pointer(__result.__seg_), + _VSTD::__to_raw_pointer(__first.__seg_), + __nw * sizeof(__storage_type)); + __n -= __nw * __bits_per_word; + __result.__seg_ += __nw; + // do last word + if (__n > 0) + { + __first.__seg_ += __nw; + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = *__first.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(__n); + } + } + return __result; +} + +template +__bit_iterator<_Cp, false> +__copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) +{ + typedef __bit_iterator<_Cp, _IsConst> _In; + typedef typename _In::difference_type difference_type; + typedef typename _In::__storage_type __storage_type; + static const unsigned __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__first.__ctz_ != 0) + { + unsigned __clz_f = __bits_per_word - __first.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b = *__first.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __first.__ctz_) + *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_); + else + *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_); + __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __dn); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn); + __result.__ctz_ = static_cast(__dn); + } + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __m = ~__storage_type(0) << __result.__ctz_; + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) + { + __storage_type __b = *__first.__seg_; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << __result.__ctz_; + ++__result.__seg_; + *__result.__seg_ &= __m; + *__result.__seg_ |= __b >> __clz_r; + } + // do last word + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = *__first.__seg_ & __m; + __storage_type __dn = _VSTD::min(__n, static_cast(__clz_r)); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << __result.__ctz_; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> __dn; + __result.__ctz_ = static_cast(__n); + } + } + } + return __result; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<_Cp, false> +copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) +{ + if (__first.__ctz_ == __result.__ctz_) + return __copy_aligned(__first, __last, __result); + return __copy_unaligned(__first, __last, __result); +} + +// copy_backward + +template +__bit_iterator<_Cp, false> +__copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) +{ + typedef __bit_iterator<_Cp, _IsConst> _In; + typedef typename _In::difference_type difference_type; + typedef typename _In::__storage_type __storage_type; + static const unsigned __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__last.__ctz_ != 0) + { + difference_type __dn = _VSTD::min(static_cast(__last.__ctz_), __n); + __n -= __dn; + unsigned __clz = __bits_per_word - __last.__ctz_; + __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz); + __storage_type __b = *__last.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) + + __result.__ctz_) % __bits_per_word); + // __last.__ctz_ = 0 + } + // __last.__ctz_ == 0 || __n == 0 + // __result.__ctz_ == 0 || __n == 0 + // do middle words + __storage_type __nw = __n / __bits_per_word; + __result.__seg_ -= __nw; + __last.__seg_ -= __nw; + _VSTD::memmove(_VSTD::__to_raw_pointer(__result.__seg_), + _VSTD::__to_raw_pointer(__last.__seg_), + __nw * sizeof(__storage_type)); + __n -= __nw * __bits_per_word; + // do last word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) << (__bits_per_word - __n); + __storage_type __b = *--__last.__seg_ & __m; + *--__result.__seg_ &= ~__m; + *__result.__seg_ |= __b; + __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1)); + } + } + return __result; +} + +template +__bit_iterator<_Cp, false> +__copy_backward_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, + __bit_iterator<_Cp, false> __result) +{ + typedef __bit_iterator<_Cp, _IsConst> _In; + typedef typename _In::difference_type difference_type; + typedef typename _In::__storage_type __storage_type; + static const unsigned __bits_per_word = _In::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__last.__ctz_ != 0) + { + difference_type __dn = _VSTD::min(static_cast(__last.__ctz_), __n); + __n -= __dn; + unsigned __clz_l = __bits_per_word - __last.__ctz_; + __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_l); + __storage_type __b = *__last.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = _VSTD::min(__dn, static_cast(__result.__ctz_)); + if (__ddn > 0) + { + __m = (~__storage_type(0) << (__result.__ctz_ - __ddn)) & (~__storage_type(0) >> __clz_r); + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __last.__ctz_) + *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); + else + *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_); + __result.__ctz_ = static_cast(((-__ddn & (__bits_per_word - 1)) + + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + } + if (__dn > 0) + { + // __result.__ctz_ == 0 + --__result.__seg_; + __result.__ctz_ = static_cast(-__dn & (__bits_per_word - 1)); + __m = ~__storage_type(0) << __result.__ctz_; + *__result.__seg_ &= ~__m; + __last.__ctz_ -= __dn + __ddn; + *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_); + } + // __last.__ctz_ = 0 + } + // __last.__ctz_ == 0 || __n == 0 + // __result.__ctz_ != 0 || __n == 0 + // do middle words + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __m = ~__storage_type(0) >> __clz_r; + for (; __n >= __bits_per_word; __n -= __bits_per_word) + { + __storage_type __b = *--__last.__seg_; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> __clz_r; + *--__result.__seg_ &= __m; + *__result.__seg_ |= __b << __result.__ctz_; + } + // do last word + if (__n > 0) + { + __m = ~__storage_type(0) << (__bits_per_word - __n); + __storage_type __b = *--__last.__seg_ & __m; + __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __dn = _VSTD::min(__n, static_cast(__result.__ctz_)); + __m = (~__storage_type(0) << (__result.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_r); + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_); + __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) + + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) + { + // __result.__ctz_ == 0 + --__result.__seg_; + __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1)); + __m = ~__storage_type(0) << __result.__ctz_; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn)); + } + } + } + return __result; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<_Cp, false> +copy_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) +{ + if (__last.__ctz_ == __result.__ctz_) + return __copy_backward_aligned(__first, __last, __result); + return __copy_backward_unaligned(__first, __last, __result); +} + +// move + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<_Cp, false> +move(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) +{ + return _VSTD::copy(__first, __last, __result); +} + +// move_backward + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<_Cp, false> +move_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) +{ + return _VSTD::copy_backward(__first, __last, __result); +} + +// swap_ranges + +template +__bit_iterator<__C2, false> +__swap_ranges_aligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last, + __bit_iterator<__C2, false> __result) +{ + typedef __bit_iterator<__C1, false> _I1; + typedef typename _I1::difference_type difference_type; + typedef typename _I1::__storage_type __storage_type; + static const unsigned __bits_per_word = _I1::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__first.__ctz_ != 0) + { + unsigned __clz = __bits_per_word - __first.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1; + *__first.__seg_ |= __b2; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_) + swap(*__first.__seg_, *__result.__seg_); + // do last word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1; + *__first.__seg_ |= __b2; + __result.__ctz_ = static_cast(__n); + } + } + return __result; +} + +template +__bit_iterator<__C2, false> +__swap_ranges_unaligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last, + __bit_iterator<__C2, false> __result) +{ + typedef __bit_iterator<__C1, false> _I1; + typedef typename _I1::difference_type difference_type; + typedef typename _I1::__storage_type __storage_type; + static const unsigned __bits_per_word = _I1::__bits_per_word; + difference_type __n = __last - __first; + if (__n > 0) + { + // do first word + if (__first.__ctz_ != 0) + { + unsigned __clz_f = __bits_per_word - __first.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + if (__result.__ctz_ > __first.__ctz_) + { + unsigned __s = __result.__ctz_ - __first.__ctz_; + *__result.__seg_ |= __b1 << __s; + *__first.__seg_ |= __b2 >> __s; + } + else + { + unsigned __s = __first.__ctz_ - __result.__ctz_; + *__result.__seg_ |= __b1 >> __s; + *__first.__seg_ |= __b2 << __s; + } + __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __dn); + __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + unsigned __s = __first.__ctz_ + __ddn; + *__result.__seg_ |= __b1 >> __s; + *__first.__seg_ |= __b2 << __s; + __result.__ctz_ = static_cast(__dn); + } + ++__first.__seg_; + // __first.__ctz_ = 0; + } + // __first.__ctz_ == 0; + // do middle words + __storage_type __m = ~__storage_type(0) << __result.__ctz_; + unsigned __clz_r = __bits_per_word - __result.__ctz_; + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) + { + __storage_type __b1 = *__first.__seg_; + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 << __result.__ctz_; + *__first.__seg_ = __b2 >> __result.__ctz_; + ++__result.__seg_; + __b2 = *__result.__seg_ & ~__m; + *__result.__seg_ &= __m; + *__result.__seg_ |= __b1 >> __clz_r; + *__first.__seg_ |= __b2 << __clz_r; + } + // do last word + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b1 = *__first.__seg_ & __m; + *__first.__seg_ &= ~__m; + __storage_type __dn = _VSTD::min<__storage_type>(__n, __clz_r); + __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); + __storage_type __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 << __result.__ctz_; + *__first.__seg_ |= __b2 >> __result.__ctz_; + __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word; + __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __b2 = *__result.__seg_ & __m; + *__result.__seg_ &= ~__m; + *__result.__seg_ |= __b1 >> __dn; + *__first.__seg_ |= __b2 << __dn; + __result.__ctz_ = static_cast(__n); + } + } + } + return __result; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +__bit_iterator<__C2, false> +swap_ranges(__bit_iterator<__C1, false> __first1, __bit_iterator<__C1, false> __last1, + __bit_iterator<__C2, false> __first2) +{ + if (__first1.__ctz_ == __first2.__ctz_) + return __swap_ranges_aligned(__first1, __last1, __first2); + return __swap_ranges_unaligned(__first1, __last1, __first2); +} + +// rotate + +template +struct __bit_array +{ + typedef typename _Cp::difference_type difference_type; + typedef typename _Cp::__storage_type __storage_type; + typedef typename _Cp::__storage_pointer __storage_pointer; + typedef typename _Cp::iterator iterator; + static const unsigned __bits_per_word = _Cp::__bits_per_word; + static const unsigned _Np = 4; + + difference_type __size_; + __storage_type __word_[_Np]; + + _LIBCPP_INLINE_VISIBILITY static difference_type capacity() + {return static_cast(_Np * __bits_per_word);} + _LIBCPP_INLINE_VISIBILITY explicit __bit_array(difference_type __s) : __size_(__s) {} + _LIBCPP_INLINE_VISIBILITY iterator begin() + { + return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]), 0); + } + _LIBCPP_INLINE_VISIBILITY iterator end() + { + return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]) + __size_ / __bits_per_word, + static_cast(__size_ % __bits_per_word)); + } +}; + +template +__bit_iterator<_Cp, false> +rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) +{ + typedef __bit_iterator<_Cp, false> _I1; + typedef typename _I1::difference_type difference_type; + difference_type __d1 = __middle - __first; + difference_type __d2 = __last - __middle; + _I1 __r = __first + __d2; + while (__d1 != 0 && __d2 != 0) + { + if (__d1 <= __d2) + { + if (__d1 <= __bit_array<_Cp>::capacity()) + { + __bit_array<_Cp> __b(__d1); + _VSTD::copy(__first, __middle, __b.begin()); + _VSTD::copy(__b.begin(), __b.end(), _VSTD::copy(__middle, __last, __first)); + break; + } + else + { + __bit_iterator<_Cp, false> __mp = _VSTD::swap_ranges(__first, __middle, __middle); + __first = __middle; + __middle = __mp; + __d2 -= __d1; + } + } + else + { + if (__d2 <= __bit_array<_Cp>::capacity()) + { + __bit_array<_Cp> __b(__d2); + _VSTD::copy(__middle, __last, __b.begin()); + _VSTD::copy_backward(__b.begin(), __b.end(), _VSTD::copy_backward(__first, __middle, __last)); + break; + } + else + { + __bit_iterator<_Cp, false> __mp = __first + __d2; + _VSTD::swap_ranges(__first, __mp, __middle); + __first = __mp; + __d1 -= __d2; + } + } + } + return __r; +} + +// equal + +template +bool +__equal_unaligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, + __bit_iterator<_Cp, _IC2> __first2) +{ + typedef __bit_iterator<_Cp, _IC1> _It; + typedef typename _It::difference_type difference_type; + typedef typename _It::__storage_type __storage_type; + static const unsigned __bits_per_word = _It::__bits_per_word; + difference_type __n = __last1 - __first1; + if (__n > 0) + { + // do first word + if (__first1.__ctz_ != 0) + { + unsigned __clz_f = __bits_per_word - __first1.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz_f), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn)); + __storage_type __b = *__first1.__seg_ & __m; + unsigned __clz_r = __bits_per_word - __first2.__ctz_; + __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r); + __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn)); + if (__first2.__ctz_ > __first1.__ctz_) + { + if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_))) + return false; + } + else + { + if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_))) + return false; + } + __first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word; + __first2.__ctz_ = static_cast((__ddn + __first2.__ctz_) % __bits_per_word); + __dn -= __ddn; + if (__dn > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __dn); + if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn))) + return false; + __first2.__ctz_ = static_cast(__dn); + } + ++__first1.__seg_; + // __first1.__ctz_ = 0; + } + // __first1.__ctz_ == 0; + // do middle words + unsigned __clz_r = __bits_per_word - __first2.__ctz_; + __storage_type __m = ~__storage_type(0) << __first2.__ctz_; + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) + { + __storage_type __b = *__first1.__seg_; + if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_)) + return false; + ++__first2.__seg_; + if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r)) + return false; + } + // do last word + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + __storage_type __b = *__first1.__seg_ & __m; + __storage_type __dn = _VSTD::min(__n, static_cast(__clz_r)); + __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn)); + if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_)) + return false; + __first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word; + __first2.__ctz_ = static_cast((__dn + __first2.__ctz_) % __bits_per_word); + __n -= __dn; + if (__n > 0) + { + __m = ~__storage_type(0) >> (__bits_per_word - __n); + if ((*__first2.__seg_ & __m) != (__b >> __dn)) + return false; + } + } + } + return true; +} + +template +bool +__equal_aligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, + __bit_iterator<_Cp, _IC2> __first2) +{ + typedef __bit_iterator<_Cp, _IC1> _It; + typedef typename _It::difference_type difference_type; + typedef typename _It::__storage_type __storage_type; + static const unsigned __bits_per_word = _It::__bits_per_word; + difference_type __n = __last1 - __first1; + if (__n > 0) + { + // do first word + if (__first1.__ctz_ != 0) + { + unsigned __clz = __bits_per_word - __first1.__ctz_; + difference_type __dn = _VSTD::min(static_cast(__clz), __n); + __n -= __dn; + __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz - __dn)); + if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) + return false; + ++__first2.__seg_; + ++__first1.__seg_; + // __first1.__ctz_ = 0; + // __first2.__ctz_ = 0; + } + // __first1.__ctz_ == 0; + // __first2.__ctz_ == 0; + // do middle words + for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_) + if (*__first2.__seg_ != *__first1.__seg_) + return false; + // do last word + if (__n > 0) + { + __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n); + if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m)) + return false; + } + } + return true; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +equal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) +{ + if (__first1.__ctz_ == __first2.__ctz_) + return __equal_aligned(__first1, __last1, __first2); + return __equal_unaligned(__first1, __last1, __first2); +} + +// We had to remove the 3rd template param of __bit_iterator to fix a compilation error for VS compiler +#if !defined(_LIBCPP_SGX_CONFIG) +template +#else +template +#endif // !defined(_LIBCPP_SGX_CONFIG) +class __bit_iterator +{ +public: + typedef typename _Cp::difference_type difference_type; + typedef bool value_type; + typedef __bit_iterator pointer; + typedef typename conditional<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >::type reference; + typedef random_access_iterator_tag iterator_category; + +private: + typedef typename _Cp::__storage_type __storage_type; + typedef typename conditional<_IsConst, typename _Cp::__const_storage_pointer, + typename _Cp::__storage_pointer>::type __storage_pointer; + static const unsigned __bits_per_word = _Cp::__bits_per_word; + + __storage_pointer __seg_; + unsigned __ctz_; + +public: + _LIBCPP_INLINE_VISIBILITY __bit_iterator() _NOEXCEPT +#if _LIBCPP_STD_VER > 11 + : __seg_(nullptr), __ctz_(0) +#endif + {} + + _LIBCPP_INLINE_VISIBILITY + __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT + : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {} + + _LIBCPP_INLINE_VISIBILITY reference operator*() const _NOEXCEPT + {return reference(__seg_, __storage_type(1) << __ctz_);} + + _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator++() + { + if (__ctz_ != __bits_per_word-1) + ++__ctz_; + else + { + __ctz_ = 0; + ++__seg_; + } + return *this; + } + + _LIBCPP_INLINE_VISIBILITY __bit_iterator operator++(int) + { + __bit_iterator __tmp = *this; + ++(*this); + return __tmp; + } + + _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator--() + { + if (__ctz_ != 0) + --__ctz_; + else + { + __ctz_ = __bits_per_word - 1; + --__seg_; + } + return *this; + } + + _LIBCPP_INLINE_VISIBILITY __bit_iterator operator--(int) + { + __bit_iterator __tmp = *this; + --(*this); + return __tmp; + } + + _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator+=(difference_type __n) + { + if (__n >= 0) + __seg_ += (__n + __ctz_) / __bits_per_word; + else + __seg_ += static_cast(__n - __bits_per_word + __ctz_ + 1) + / static_cast(__bits_per_word); + __n &= (__bits_per_word - 1); + __ctz_ = static_cast((__n + __ctz_) % __bits_per_word); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator-=(difference_type __n) + { + return *this += -__n; + } + + _LIBCPP_INLINE_VISIBILITY __bit_iterator operator+(difference_type __n) const + { + __bit_iterator __t(*this); + __t += __n; + return __t; + } + + _LIBCPP_INLINE_VISIBILITY __bit_iterator operator-(difference_type __n) const + { + __bit_iterator __t(*this); + __t -= __n; + return __t; + } + + _LIBCPP_INLINE_VISIBILITY + friend __bit_iterator operator+(difference_type __n, const __bit_iterator& __it) {return __it + __n;} + + _LIBCPP_INLINE_VISIBILITY + friend difference_type operator-(const __bit_iterator& __x, const __bit_iterator& __y) + {return (__x.__seg_ - __y.__seg_) * __bits_per_word + __x.__ctz_ - __y.__ctz_;} + + _LIBCPP_INLINE_VISIBILITY reference operator[](difference_type __n) const {return *(*this + __n);} + + _LIBCPP_INLINE_VISIBILITY friend bool operator==(const __bit_iterator& __x, const __bit_iterator& __y) + {return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;} + + _LIBCPP_INLINE_VISIBILITY friend bool operator!=(const __bit_iterator& __x, const __bit_iterator& __y) + {return !(__x == __y);} + + _LIBCPP_INLINE_VISIBILITY friend bool operator<(const __bit_iterator& __x, const __bit_iterator& __y) + {return __x.__seg_ < __y.__seg_ || (__x.__seg_ == __y.__seg_ && __x.__ctz_ < __y.__ctz_);} + + _LIBCPP_INLINE_VISIBILITY friend bool operator>(const __bit_iterator& __x, const __bit_iterator& __y) + {return __y < __x;} + + _LIBCPP_INLINE_VISIBILITY friend bool operator<=(const __bit_iterator& __x, const __bit_iterator& __y) + {return !(__y < __x);} + + _LIBCPP_INLINE_VISIBILITY friend bool operator>=(const __bit_iterator& __x, const __bit_iterator& __y) + {return !(__x < __y);} + +private: + _LIBCPP_INLINE_VISIBILITY + __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT + : __seg_(__s), __ctz_(__ctz) {} + +#if defined(__clang__) || defined(__IBMCPP__) || defined(_LIBCPP_MSVC) + friend typename _Cp::__self; +#else + friend class _Cp::__self; +#endif + friend class __bit_reference<_Cp>; + friend class __bit_const_reference<_Cp>; + friend class __bit_iterator<_Cp, true>; + template friend struct __bit_array; + template friend void __fill_n_false(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + template friend void __fill_n_true(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n); + template friend __bit_iterator<_Dp, false> __copy_aligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template friend __bit_iterator<_Dp, false> __copy_unaligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template friend __bit_iterator<_Dp, false> copy(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template friend __bit_iterator<_Dp, false> __copy_backward_aligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template friend __bit_iterator<_Dp, false> __copy_backward_unaligned(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first, + __bit_iterator<_Dp, _IC> __last, + __bit_iterator<_Dp, false> __result); + template friend __bit_iterator<__C2, false> __swap_ranges_aligned(__bit_iterator<__C1, false>, + __bit_iterator<__C1, false>, + __bit_iterator<__C2, false>); + template friend __bit_iterator<__C2, false> __swap_ranges_unaligned(__bit_iterator<__C1, false>, + __bit_iterator<__C1, false>, + __bit_iterator<__C2, false>); + template friend __bit_iterator<__C2, false> swap_ranges(__bit_iterator<__C1, false>, + __bit_iterator<__C1, false>, + __bit_iterator<__C2, false>); + template friend __bit_iterator<_Dp, false> rotate(__bit_iterator<_Dp, false>, + __bit_iterator<_Dp, false>, + __bit_iterator<_Dp, false>); + template friend bool __equal_aligned(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template friend bool __equal_unaligned(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template friend bool equal(__bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC1>, + __bit_iterator<_Dp, _IC2>); + template friend __bit_iterator<_Dp, _IC> __find_bool_true(__bit_iterator<_Dp, _IC>, + typename _Dp::size_type); + template friend __bit_iterator<_Dp, _IC> __find_bool_false(__bit_iterator<_Dp, _IC>, + typename _Dp::size_type); + template friend typename __bit_iterator<_Dp, _IC>::difference_type + __count_bool_true(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); + template friend typename __bit_iterator<_Dp, _IC>::difference_type + __count_bool_false(__bit_iterator<_Dp, _IC>, typename _Dp::size_type); +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___BIT_REFERENCE diff --git a/sdk/tlibcxx/include/__bsd_locale_defaults.h b/sdk/tlibcxx/include/__bsd_locale_defaults.h new file mode 100644 index 00000000..f315ca29 --- /dev/null +++ b/sdk/tlibcxx/include/__bsd_locale_defaults.h @@ -0,0 +1,33 @@ +// -*- C++ -*- +//===---------------------- __bsd_locale_defaults.h -----------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// The BSDs have lots of *_l functions. We don't want to define those symbols +// on other platforms though, for fear of conflicts with user code. So here, +// we will define the mapping from an internal macro to the real BSD symbol. +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_BSD_LOCALE_DEFAULTS_H +#define _LIBCPP_BSD_LOCALE_DEFAULTS_H + +#define __libcpp_mb_cur_max_l(loc) MB_CUR_MAX_L(loc) +#define __libcpp_btowc_l(ch, loc) btowc_l(ch, loc) +#define __libcpp_wctob_l(wch, loc) wctob_l(wch, loc) +#define __libcpp_wcsnrtombs_l(dst, src, nwc, len, ps, loc) wcsnrtombs_l(dst, src, nwc, len, ps, loc) +#define __libcpp_wcrtomb_l(src, wc, ps, loc) wcrtomb_l(src, wc, ps, loc) +#define __libcpp_mbsnrtowcs_l(dst, src, nms, len, ps, loc) mbsnrtowcs_l(dst, src, nms, len, ps, loc) +#define __libcpp_mbrtowc_l(pwc, s, n, ps, l) mbrtowc_l(pwc, s, n, ps, l) +#define __libcpp_mbtowc_l(pwc, pmb, max, l) mbtowc_l(pwc, pmb, max, l) +#define __libcpp_mbrlen_l(s, n, ps, l) mbrlen_l(s, n, ps, l) +#define __libcpp_localeconv_l(l) localeconv_l(l) +#define __libcpp_mbsrtowcs_l(dest, src, len, ps, l) mbsrtowcs_l(dest, src, len, ps, l) +#define __libcpp_snprintf_l(...) snprintf_l(__VA_ARGS__) +#define __libcpp_asprintf_l(...) asprintf_l(__VA_ARGS__) +#define __libcpp_sscanf_l(...) sscanf_l(__VA_ARGS__) + +#endif // _LIBCPP_BSD_LOCALE_DEFAULTS_H diff --git a/sdk/tlibcxx/include/__bsd_locale_fallbacks.h b/sdk/tlibcxx/include/__bsd_locale_fallbacks.h new file mode 100644 index 00000000..cbc8ad22 --- /dev/null +++ b/sdk/tlibcxx/include/__bsd_locale_fallbacks.h @@ -0,0 +1,138 @@ +// -*- C++ -*- +//===---------------------- __bsd_locale_fallbacks.h ----------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// The BSDs have lots of *_l functions. This file provides reimplementations +// of those functions for non-BSD platforms. +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H +#define _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H + +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +typedef _VSTD::remove_pointer::type __use_locale_struct; +typedef _VSTD::unique_ptr<__use_locale_struct, decltype(&uselocale)> __locale_raii; + +inline _LIBCPP_ALWAYS_INLINE +decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return MB_CUR_MAX; +} + +inline _LIBCPP_ALWAYS_INLINE +wint_t __libcpp_btowc_l(int __c, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return btowc(__c); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_wctob_l(wint_t __c, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return wctob(__c); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, + size_t __len, mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return wcsnrtombs(__dest, __src, __nwc, __len, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return wcrtomb(__s, __wc, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, + size_t __len, mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbsnrtowcs(__dest, __src, __nms, __len, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, + mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbrtowc(__pwc, __s, __n, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbtowc(__pwc, __pmb, __max); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbrlen(__s, __n, __ps); +} + +inline _LIBCPP_ALWAYS_INLINE +lconv *__libcpp_localeconv_l(locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return localeconv(); +} + +inline _LIBCPP_ALWAYS_INLINE +size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, + mbstate_t *__ps, locale_t __l) +{ + __locale_raii __current( uselocale(__l), uselocale ); + return mbsrtowcs(__dest, __src, __len, __ps); +} + +inline +int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __locale_raii __current( uselocale(__l), uselocale ); + int __res = vsnprintf(__s, __n, __format, __va); + va_end(__va); + return __res; +} + +inline +int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __locale_raii __current( uselocale(__l), uselocale ); + int __res = vasprintf(__s, __format, __va); + va_end(__va); + return __res; +} + +inline +int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + __locale_raii __current( uselocale(__l), uselocale ); + int __res = vsscanf(__s, __format, __va); + va_end(__va); + return __res; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H diff --git a/sdk/tlibcxx/include/__config b/sdk/tlibcxx/include/__config new file mode 100644 index 00000000..32ec9965 --- /dev/null +++ b/sdk/tlibcxx/include/__config @@ -0,0 +1,1025 @@ +// -*- C++ -*- +//===--------------------------- __config ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_CONFIG +#define _LIBCPP_CONFIG + +//#pragma message ("Parsing __config file.") + +#define CPP_MESSAGE(x) _Pragma (#x) +#define GCC_MESSAGE(x) CPP_MESSAGE(GCC warning #x) + +#if defined(_MSC_VER) && !defined(__clang__) +#define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#endif + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +GCC_MESSAGE("_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER is not defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER is defined") +#endif + +#ifdef __cplusplus + +#ifdef __GNUC__ +#define _GNUC_VER (__GNUC__ * 100 + __GNUC_MINOR__) +#else +#define _GNUC_VER 0 +#endif + +#define _LIBCPP_VERSION 3900 + +#ifndef _LIBCPP_ABI_VERSION +#define _LIBCPP_ABI_VERSION 1 +#endif + +#if defined(_LIBCPP_ABI_UNSTABLE) || _LIBCPP_ABI_VERSION >= 2 +// Change short string represention so that string data starts at offset 0, +// improving its alignment in some cases. +#define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +// Fix deque iterator type in order to support incomplete types. +#define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE +// Fix undefined behavior in how std::list stores it's linked nodes. +#define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB +// Fix undefined behavior in how __tree stores its end and parent nodes. +#define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB +#define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB +#define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE +#define _LIBCPP_ABI_VARIADIC_LOCK_GUARD +#elif _LIBCPP_ABI_VERSION == 1 +// Feature macros for disabling pre ABI v1 features. All of these options +// are deprecated. +#if defined(__FreeBSD__) +#define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR +#endif +#endif + +#ifdef _LIBCPP_TRIVIAL_PAIR_COPY_CTOR +#error "_LIBCPP_TRIVIAL_PAIR_COPY_CTOR" is no longer supported. \ + use _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR instead +#endif + +#define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y +#define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) + +#define _LIBCPP_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION) +GCC_MESSAGE("_LIBCPP_NAMESPACE") + +#ifndef __has_attribute +#define __has_attribute(__x) 0 +#endif +#ifndef __has_builtin +#define __has_builtin(__x) 0 +#endif +#ifndef __has_extension +#define __has_extension(__x) 0 +#endif +#ifndef __has_feature +#define __has_feature(__x) 0 +#endif +// '__is_identifier' returns '0' if '__x' is a reserved identifier provided by +// the compiler and '1' otherwise. +#ifndef __is_identifier +#define __is_identifier(__x) 1 +#endif + + +#ifdef __LITTLE_ENDIAN__ +#if __LITTLE_ENDIAN__ +#define _LIBCPP_LITTLE_ENDIAN 1 +#define _LIBCPP_BIG_ENDIAN 0 +#endif // __LITTLE_ENDIAN__ +#endif // __LITTLE_ENDIAN__ + +#ifdef __BIG_ENDIAN__ +#if __BIG_ENDIAN__ +#define _LIBCPP_LITTLE_ENDIAN 0 +#define _LIBCPP_BIG_ENDIAN 1 +#endif // __BIG_ENDIAN__ +#endif // __BIG_ENDIAN__ + +#ifdef __BYTE_ORDER__ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define _LIBCPP_LITTLE_ENDIAN 1 +#define _LIBCPP_BIG_ENDIAN 0 +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define _LIBCPP_LITTLE_ENDIAN 0 +#define _LIBCPP_BIG_ENDIAN 1 +#endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#endif // __BYTE_ORDER__ + +#ifdef __FreeBSD__ +# include +# if _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 1 +# define _LIBCPP_BIG_ENDIAN 0 +# else // _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 0 +# define _LIBCPP_BIG_ENDIAN 1 +# endif // _BYTE_ORDER == _LITTLE_ENDIAN +# ifndef __LONG_LONG_SUPPORTED +# define _LIBCPP_HAS_NO_LONG_LONG +# endif // __LONG_LONG_SUPPORTED +#endif // __FreeBSD__ + +#ifdef __NetBSD__ +# include +# if _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 1 +# define _LIBCPP_BIG_ENDIAN 0 +# else // _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 0 +# define _LIBCPP_BIG_ENDIAN 1 +# endif // _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_HAS_QUICK_EXIT +#endif // __NetBSD__ + +#ifdef _WIN32 +# define _LIBCPP_LITTLE_ENDIAN 1 +# define _LIBCPP_BIG_ENDIAN 0 +// Compiler intrinsics (MSVC) +#if defined(_MSC_VER) && _MSC_VER >= 1400 +# define _LIBCPP_HAS_IS_BASE_OF +# endif +# if defined(_MSC_VER) && !defined(__clang__) +# define _LIBCPP_MSVC // Using Microsoft Visual C++ compiler +# define _LIBCPP_TOSTRING2(x) #x +# define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x) +# define _LIBCPP_WARNING(x) __pragma(message(__FILE__ "(" _LIBCPP_TOSTRING(__LINE__) ") : warning note: " x)) +# endif +# // If mingw not explicitly detected, assume using MS C runtime only. +# ifndef __MINGW32__ +# define _LIBCPP_MSVCRT // Using Microsoft's C Runtime library +# endif +#endif // _WIN32 + +#ifdef __sun__ +# include +# ifdef _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 1 +# define _LIBCPP_BIG_ENDIAN 0 +# else +# define _LIBCPP_LITTLE_ENDIAN 0 +# define _LIBCPP_BIG_ENDIAN 1 +# endif +#endif // __sun__ + +#if defined(__CloudABI__) + // Certain architectures provide arc4random(). Prefer using + // arc4random() over /dev/{u,}random to make it possible to obtain + // random data even when using sandboxing mechanisms such as chroots, + // Capsicum, etc. +# define _LIBCPP_USING_ARC4_RANDOM +#elif defined(__native_client__) + // NaCl's sandbox (which PNaCl also runs in) doesn't allow filesystem access, + // including accesses to the special files under /dev. C++11's + // std::random_device is instead exposed through a NaCl syscall. +# define _LIBCPP_USING_NACL_RANDOM +#elif defined(_WIN32) +# define _LIBCPP_USING_WIN32_RANDOM +#else +# define _LIBCPP_USING_DEV_RANDOM +#endif + +#if !defined(_LIBCPP_LITTLE_ENDIAN) || !defined(_LIBCPP_BIG_ENDIAN) +# include +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 1 +# define _LIBCPP_BIG_ENDIAN 0 +# elif __BYTE_ORDER == __BIG_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 0 +# define _LIBCPP_BIG_ENDIAN 1 +# else // __BYTE_ORDER == __BIG_ENDIAN +# error unable to determine endian +# endif +#endif // !defined(_LIBCPP_LITTLE_ENDIAN) || !defined(_LIBCPP_BIG_ENDIAN) + +#if __has_attribute(__no_sanitize__) +#define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi"))) +#else +#define _LIBCPP_NO_CFI +#endif + +#ifdef _WIN32 + +#ifdef _LIBCPP_MSVC +# include <__sgx> +#endif + +// only really useful for a DLL +#ifdef _LIBCPP_DLL // this should be a compiler builtin define ideally... +# ifdef cxx_EXPORTS +# define _LIBCPP_HIDDEN +# define _LIBCPP_FUNC_VIS __declspec(dllexport) +# define _LIBCPP_TYPE_VIS __declspec(dllexport) +# else +# define _LIBCPP_HIDDEN +# define _LIBCPP_FUNC_VIS __declspec(dllimport) +# define _LIBCPP_TYPE_VIS __declspec(dllimport) +# endif +#else +# define _LIBCPP_HIDDEN +# define _LIBCPP_FUNC_VIS +# define _LIBCPP_TYPE_VIS +#endif + +#define _LIBCPP_TYPE_VIS_ONLY +#define _LIBCPP_FUNC_VIS_ONLY + +#ifndef _LIBCPP_INLINE_VISIBILITY +# ifdef _LIBCPP_MSVC +# ifdef _LIBCPP_SGX_CONFIG +# define _LIBCPP_INLINE_VISIBILITY +# else +# define _LIBCPP_INLINE_VISIBILITY __forceinline +# endif //_LIBCPP_SGX_CONFIG +# else // MinGW GCC and Clang +# define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__always_inline__)) +# endif +#endif + +#ifndef _LIBCPP_EXCEPTION_ABI +#define _LIBCPP_EXCEPTION_ABI _LIBCPP_TYPE_VIS +#endif + +#ifndef _LIBCPP_ALWAYS_INLINE +# ifdef _LIBCPP_MSVC +# define _LIBCPP_ALWAYS_INLINE __forceinline +# endif +#endif + +#endif // _WIN32 + +#ifndef _LIBCPP_HIDDEN +#define _LIBCPP_HIDDEN __attribute__ ((__visibility__("hidden"))) +#endif + +#ifndef _LIBCPP_FUNC_VIS +#define _LIBCPP_FUNC_VIS __attribute__ ((__visibility__("default"))) +#endif + +#ifndef _LIBCPP_TYPE_VIS +# if __has_attribute(__type_visibility__) +# define _LIBCPP_TYPE_VIS __attribute__ ((__type_visibility__("default"))) +# else +# define _LIBCPP_TYPE_VIS __attribute__ ((__visibility__("default"))) +# endif +#endif + +#ifndef _LIBCPP_PREFERRED_OVERLOAD +# if __has_attribute(__enable_if__) +# define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, ""))) +# endif +#endif + +#ifndef _LIBCPP_TYPE_VIS_ONLY +# define _LIBCPP_TYPE_VIS_ONLY _LIBCPP_TYPE_VIS +#endif + +#ifndef _LIBCPP_FUNC_VIS_ONLY +# define _LIBCPP_FUNC_VIS_ONLY _LIBCPP_FUNC_VIS +#endif + +#ifndef _LIBCPP_INLINE_VISIBILITY +#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__)) +#endif + +#ifndef _LIBCPP_EXCEPTION_ABI +#define _LIBCPP_EXCEPTION_ABI __attribute__ ((__visibility__("default"))) +#endif + +#ifndef _LIBCPP_ALWAYS_INLINE +#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__)) +#endif + +#if defined(__clang__) + +// _LIBCPP_ALTERNATE_STRING_LAYOUT is an old name for +// _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT left here for backward compatibility. +#if (defined(__APPLE__) && !defined(__i386__) && !defined(__x86_64__) && \ + !defined(__arm__)) || \ + defined(_LIBCPP_ALTERNATE_STRING_LAYOUT) +#define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT +#endif + +#if __has_feature(cxx_alignas) +# define _ALIGNAS_TYPE(x) alignas(x) +# define _ALIGNAS(x) alignas(x) +#else +# define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) +# define _ALIGNAS(x) __attribute__((__aligned__(x))) +#endif + +#if !__has_feature(cxx_alias_templates) +#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#endif + +#if __cplusplus < 201103L +typedef __char16_t char16_t; +typedef __char32_t char32_t; +#endif + +#if !(__has_feature(cxx_exceptions)) && !defined(_LIBCPP_NO_EXCEPTIONS) +#define _LIBCPP_NO_EXCEPTIONS +#endif + +#if !(__has_feature(cxx_rtti)) +#define _LIBCPP_NO_RTTI +#endif + +#if !(__has_feature(cxx_strong_enums)) +#define _LIBCPP_HAS_NO_STRONG_ENUMS +#endif + +#if !(__has_feature(cxx_decltype)) +#define _LIBCPP_HAS_NO_DECLTYPE +#endif + +#if __has_feature(cxx_attributes) +# define _LIBCPP_NORETURN [[noreturn]] +#else +# define _LIBCPP_NORETURN __attribute__ ((noreturn)) +#endif + +#if !(__has_feature(cxx_default_function_template_args)) +#define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS +#endif + +#if !(__has_feature(cxx_defaulted_functions)) +#define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif // !(__has_feature(cxx_defaulted_functions)) + +#if !(__has_feature(cxx_deleted_functions)) +#define _LIBCPP_HAS_NO_DELETED_FUNCTIONS +#endif // !(__has_feature(cxx_deleted_functions)) + +#if !(__has_feature(cxx_lambdas)) +#define _LIBCPP_HAS_NO_LAMBDAS +#endif + +#if !(__has_feature(cxx_nullptr)) +#define _LIBCPP_HAS_NO_NULLPTR +#endif + +#if !(__has_feature(cxx_rvalue_references)) +#define _LIBCPP_HAS_NO_RVALUE_REFERENCES +#endif + +#if !(__has_feature(cxx_static_assert)) +#define _LIBCPP_HAS_NO_STATIC_ASSERT +#endif + +#if !(__has_feature(cxx_auto_type)) +#define _LIBCPP_HAS_NO_AUTO_TYPE +#endif + +#if !(__has_feature(cxx_access_control_sfinae)) || !__has_feature(cxx_trailing_return) +#define _LIBCPP_HAS_NO_ADVANCED_SFINAE +#endif + +#if !(__has_feature(cxx_variadic_templates)) +#define _LIBCPP_HAS_NO_VARIADICS +#endif + +#if !(__has_feature(cxx_trailing_return)) +#define _LIBCPP_HAS_NO_TRAILING_RETURN +#endif + +#if !(__has_feature(cxx_generalized_initializers)) +#define _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS +#endif + +#if __has_feature(is_base_of) +# define _LIBCPP_HAS_IS_BASE_OF +#endif + +#if __has_feature(is_final) +# define _LIBCPP_HAS_IS_FINAL +#endif + +// Objective-C++ features (opt-in) +#if __has_feature(objc_arc) +#define _LIBCPP_HAS_OBJC_ARC +#endif + +#if __has_feature(objc_arc_weak) +#define _LIBCPP_HAS_OBJC_ARC_WEAK +#define _LIBCPP_HAS_NO_STRONG_ENUMS +#endif + +#if !(__has_feature(cxx_constexpr)) +#define _LIBCPP_HAS_NO_CONSTEXPR +#endif + +#if !(__has_feature(cxx_relaxed_constexpr)) +#define _LIBCPP_HAS_NO_CXX14_CONSTEXPR +#endif + +#if !(__has_feature(cxx_variable_templates)) +#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES +#endif + +#if __ISO_C_VISIBLE >= 2011 || __cplusplus >= 201103L +#if defined(__FreeBSD__) +#define _LIBCPP_HAS_QUICK_EXIT +#define _LIBCPP_HAS_C11_FEATURES +#elif defined(__ANDROID__) +#define _LIBCPP_HAS_QUICK_EXIT +#elif defined(__linux__) +#if !defined(_LIBCPP_HAS_MUSL_LIBC) +# include +#if __GLIBC_PREREQ(2, 15) +#define _LIBCPP_HAS_QUICK_EXIT +#endif +#if __GLIBC_PREREQ(2, 17) +#define _LIBCPP_HAS_C11_FEATURES +#endif +#else // defined(_LIBCPP_HAS_MUSL_LIBC) +#define _LIBCPP_HAS_QUICK_EXIT +#define _LIBCPP_HAS_C11_FEATURES +#endif +#endif // __linux__ +#endif + +#if !(__has_feature(cxx_noexcept)) +#define _LIBCPP_HAS_NO_NOEXCEPT +#endif + +#if __has_feature(underlying_type) +# define _LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T) +#endif + +#if __has_feature(is_literal) +# define _LIBCPP_IS_LITERAL(T) __is_literal(T) +#endif + +// Inline namespaces are available in Clang regardless of C++ dialect. +#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE { +#define _LIBCPP_END_NAMESPACE_STD } } +#define _VSTD std::_LIBCPP_NAMESPACE + +namespace std { + inline namespace _LIBCPP_NAMESPACE { + } +} + +#if !defined(_LIBCPP_HAS_NO_ASAN) && !__has_feature(address_sanitizer) +#define _LIBCPP_HAS_NO_ASAN +#endif + +// Allow for build-time disabling of unsigned integer sanitization +#if !defined(_LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK) && __has_attribute(no_sanitize) +#define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK __attribute__((__no_sanitize__("unsigned-integer-overflow"))) +#endif + +#elif defined(__GNUC__) + +#include <__sgx> + +#define _ALIGNAS(x) __attribute__((__aligned__(x))) +#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) + +#define _LIBCPP_NORETURN __attribute__((noreturn)) + +#if _GNUC_VER >= 407 +#define _LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T) +#define _LIBCPP_IS_LITERAL(T) __is_literal_type(T) +#define _LIBCPP_HAS_IS_FINAL +#endif + +#if defined(__GNUC__) && _GNUC_VER >= 403 +# define _LIBCPP_HAS_IS_BASE_OF +#endif + +#if !__EXCEPTIONS +#define _LIBCPP_NO_EXCEPTIONS +GCC_MESSAGE("_LIBCPP_NO_EXCEPTIONS is defined") +#else +GCC_MESSAGE("_LIBCPP_NO_EXCEPTIONS is not defined") +#endif + +// constexpr was added to GCC in 4.6. +#if _GNUC_VER < 406 +#define _LIBCPP_HAS_NO_CONSTEXPR +// Can only use constexpr in c++11 mode. +#elif !defined(__GXX_EXPERIMENTAL_CXX0X__) && __cplusplus < 201103L +#define _LIBCPP_HAS_NO_CONSTEXPR +#endif + +#if defined(_LIBCPP_HAS_NO_CONSTEXPR) +GCC_MESSAGE("_LIBCPP_HAS_NO_CONSTEXPR is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_CONSTEXPR is not defined") +#endif + +// Determine if GCC supports relaxed constexpr +#if !defined(__cpp_constexpr) || __cpp_constexpr < 201304L +#define _LIBCPP_HAS_NO_CXX14_CONSTEXPR +#endif + +#if defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) +GCC_MESSAGE("_LIBCPP_HAS_NO_CXX14_CONSTEXPR is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_CXX14_CONSTEXPR is not defined") +#endif + +// GCC 5 will support variable templates +#if !defined(__cpp_variable_templates) || __cpp_variable_templates < 201304L +#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES +#endif + +#if defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) +GCC_MESSAGE("_LIBCPP_HAS_NO_VARIABLE_TEMPLATES is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_VARIABLE_TEMPLATES is not defined") +#endif + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ + +GCC_MESSAGE("__GXX_EXPERIMENTAL_CXX0X__ is not defined") +#define _LIBCPP_HAS_NO_ADVANCED_SFINAE +#define _LIBCPP_HAS_NO_DECLTYPE +#define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS +#define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#define _LIBCPP_HAS_NO_DELETED_FUNCTIONS +#define _LIBCPP_HAS_NO_NULLPTR +#define _LIBCPP_HAS_NO_STATIC_ASSERT +#define _LIBCPP_HAS_NO_UNICODE_CHARS +#define _LIBCPP_HAS_NO_VARIADICS +#define _LIBCPP_HAS_NO_RVALUE_REFERENCES +#define _LIBCPP_HAS_NO_STRONG_ENUMS +#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#define _LIBCPP_HAS_NO_NOEXCEPT + +#else // __GXX_EXPERIMENTAL_CXX0X__ + +GCC_MESSAGE("__GXX_EXPERIMENTAL_CXX0X__ is defined") + +#if _GNUC_VER < 403 +GCC_MESSAGE("_GNUC_VER < 403") +#define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS +#define _LIBCPP_HAS_NO_RVALUE_REFERENCES +#define _LIBCPP_HAS_NO_STATIC_ASSERT +#endif + + +#if _GNUC_VER < 404 +GCC_MESSAGE("_GNUC_VER < 404") +#define _LIBCPP_HAS_NO_DECLTYPE +#define _LIBCPP_HAS_NO_DELETED_FUNCTIONS +#define _LIBCPP_HAS_NO_TRAILING_RETURN +#define _LIBCPP_HAS_NO_UNICODE_CHARS +#define _LIBCPP_HAS_NO_VARIADICS +#define _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS +#endif // _GNUC_VER < 404 + +#if _GNUC_VER < 406 +GCC_MESSAGE("_GNUC_VER < 406") +#define _LIBCPP_HAS_NO_NOEXCEPT +#define _LIBCPP_HAS_NO_NULLPTR +#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#endif + +#if _GNUC_VER < 407 +GCC_MESSAGE("_GNUC_VER < 407") +#define _LIBCPP_HAS_NO_ADVANCED_SFINAE +#define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#endif + +#if _GNUC_VER == 408 +GCC_MESSAGE("_GNUC_VER == 408") +#endif + +#endif // __GXX_EXPERIMENTAL_CXX0X__ + +#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { namespace _LIBCPP_NAMESPACE { +#define _LIBCPP_END_NAMESPACE_STD } } +#define _VSTD std::_LIBCPP_NAMESPACE + +namespace std { +namespace _LIBCPP_NAMESPACE { +} +using namespace _LIBCPP_NAMESPACE __attribute__((__strong__)); +} + +#if !defined(_LIBCPP_HAS_NO_ASAN) && !defined(__SANITIZE_ADDRESS__) +#define _LIBCPP_HAS_NO_ASAN +GCC_MESSAGE("_LIBCPP_HAS_NO_ASAN is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_ASAN is not defined") +#endif + +#elif defined(_LIBCPP_MSVC) + +// If _LIBCPP_SGX_CONFIG is not defined run with MS VS default configuration +#if !defined(_LIBCPP_SGX_CONFIG) +GCC_MESSAGE("_LIBCPP_SGX_CONFIG" was not been defined. Applying general settings") +#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#define _LIBCPP_HAS_NO_CONSTEXPR +#define _LIBCPP_HAS_NO_CXX14_CONSTEXPR +#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES +#define _LIBCPP_HAS_NO_UNICODE_CHARS +#define _LIBCPP_HAS_NO_DELETED_FUNCTIONS +#define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#define _LIBCPP_HAS_NO_NOEXCEPT +#define __alignof__ __alignof +#define _LIBCPP_NORETURN __declspec(noreturn) +#define _ALIGNAS(x) __declspec(align(x)) +#define _LIBCPP_HAS_NO_VARIADICS + + + +#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { +#define _LIBCPP_END_NAMESPACE_STD } +#define _VSTD std + +# define _LIBCPP_WEAK +namespace std { +} + +#define _LIBCPP_HAS_NO_ASAN +#endif // !defined(_LIBCPP_SGX_CONFIG) + +#elif defined(__IBMCPP__) + +#define _ALIGNAS(x) __attribute__((__aligned__(x))) +#define _ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x)))) +#define _ATTRIBUTE(x) __attribute__((x)) +#define _LIBCPP_NORETURN __attribute__((noreturn)) + +#define _LIBCPP_HAS_NO_DEFAULT_FUNCTION_TEMPLATE_ARGS +#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#define _LIBCPP_HAS_NO_ADVANCED_SFINAE +#define _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS +#define _LIBCPP_HAS_NO_NOEXCEPT +#define _LIBCPP_HAS_NO_NULLPTR +#define _LIBCPP_HAS_NO_UNICODE_CHARS +#define _LIBCPP_HAS_IS_BASE_OF +#define _LIBCPP_HAS_IS_FINAL +#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES + +#if defined(_AIX) +#define __MULTILOCALE_API +#endif + +#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {inline namespace _LIBCPP_NAMESPACE { +#define _LIBCPP_END_NAMESPACE_STD } } +#define _VSTD std::_LIBCPP_NAMESPACE + +namespace std { + inline namespace _LIBCPP_NAMESPACE { + } +} + +#define _LIBCPP_HAS_NO_ASAN + +#endif // __clang__ || __GNUC__ || _MSC_VER || __IBMCPP__ + +#ifndef _LIBCPP_HAS_NO_NOEXCEPT +# define _NOEXCEPT noexcept +# define _NOEXCEPT_(x) noexcept(x) +GCC_MESSAGE("_LIBCPP_HAS_NO_NOEXCEPT is not defined") +#else +# define _NOEXCEPT throw() +# define _NOEXCEPT_(x) +GCC_MESSAGE("_LIBCPP_HAS_NO_NOEXCEPT is defined") +#endif + +#ifdef _LIBCPP_HAS_NO_UNICODE_CHARS +typedef unsigned short char16_t; +typedef unsigned int char32_t; +GCC_MESSAGE("_LIBCPP_HAS_NO_UNICODE_CHARS is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_UNICODE_CHARS is not defined") +#endif // _LIBCPP_HAS_NO_UNICODE_CHARS + +#ifndef __SIZEOF_INT128__ +#define _LIBCPP_HAS_NO_INT128 +GCC_MESSAGE("_LIBCPP_HAS_NO_INT128 is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_INT128 is not defined") +#endif + +#ifdef _LIBCPP_HAS_NO_STATIC_ASSERT + +extern "C++" { +template struct __static_assert_test; +template <> struct __static_assert_test {}; +template struct __static_assert_check {}; +} +#define static_assert(__b, __m) \ + typedef __static_assert_check)> \ + _LIBCPP_CONCAT(__t, __LINE__) + +GCC_MESSAGE("_LIBCPP_HAS_NO_STATIC_ASSERT is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_STATIC_ASSERT is not defined") +#endif // _LIBCPP_HAS_NO_STATIC_ASSERT + +#ifdef _LIBCPP_HAS_NO_DECLTYPE +// GCC 4.6 provides __decltype in all standard modes. +#if !__is_identifier(__decltype) || _GNUC_VER >= 406 +# define decltype(__x) __decltype(__x) +#else +# define decltype(__x) __typeof__(__x) +#endif +#endif + +#if defined(_LIBCPP_HAS_NO_DECLTYPE) +GCC_MESSAGE("_LIBCPP_HAS_NO_DECLTYPE is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_DECLTYPE is not defined") +#endif + +#ifdef _LIBCPP_HAS_NO_CONSTEXPR +#define _LIBCPP_CONSTEXPR +#else +#define _LIBCPP_CONSTEXPR constexpr +#endif + +#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#define _LIBCPP_DEFAULT {} +#else +#define _LIBCPP_DEFAULT = default; +#endif + +#if defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) +GCC_MESSAGE("_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS is not defined") +#endif + +#ifdef _LIBCPP_HAS_NO_DELETED_FUNCTIONS +#define _LIBCPP_EQUAL_DELETE +#else +#define _LIBCPP_EQUAL_DELETE = delete +#endif + +#if defined(_LIBCPP_HAS_NO_DELETED_FUNCTIONS) +GCC_MESSAGE("_LIBCPP_HAS_NO_DELETED_FUNCTIONS is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_DELETED_FUNCTIONS is not defined") +#endif + +#ifdef __GNUC__ +#define _NOALIAS __attribute__((__malloc__)) +#else +#define _NOALIAS +#endif + +#if __has_feature(cxx_explicit_conversions) || defined(__IBMCPP__) +# define _LIBCPP_EXPLICIT explicit +GCC_MESSAGE("_LIBCPP_EXPLICIT is really defined") +#else +# define _LIBCPP_EXPLICIT +GCC_MESSAGE("_LIBCPP_EXPLICIT is empty defined") +#endif + +#if !__has_builtin(__builtin_operator_new) || !__has_builtin(__builtin_operator_delete) +# define _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE +GCC_MESSAGE("_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE is not defined") +#endif + +#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS +GCC_MESSAGE("_LIBCPP_HAS_NO_STRONG_ENUMS is defined") +#define _LIBCPP_DECLARE_STRONG_ENUM(x) struct _LIBCPP_TYPE_VIS x { enum __lx +#define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ + __lx __v_; \ + _LIBCPP_ALWAYS_INLINE x(__lx __v) : __v_(__v) {} \ + _LIBCPP_ALWAYS_INLINE explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ + _LIBCPP_ALWAYS_INLINE operator int() const {return __v_;} \ + }; +#else // _LIBCPP_HAS_NO_STRONG_ENUMS +GCC_MESSAGE("_LIBCPP_HAS_NO_STRONG_ENUMS is not defined") +#define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_TYPE_VIS x +#define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) +#endif // _LIBCPP_HAS_NO_STRONG_ENUMS + +#ifdef _LIBCPP_DEBUG +GCC_MESSAGE("_LIBCPP_DEBUG is defined") +# if _LIBCPP_DEBUG == 0 +GCC_MESSAGE("_LIBCPP_DEBUG == 0. _LIBCPP_DEBUG_LEVEL 1") +# define _LIBCPP_DEBUG_LEVEL 1 +# elif _LIBCPP_DEBUG == 1 +GCC_MESSAGE("_LIBCPP_DEBUG == 1. _LIBCPP_DEBUG_LEVEL 2") +# define _LIBCPP_DEBUG_LEVEL 2 +# else +# error Supported values for _LIBCPP_DEBUG are 0 and 1 +# endif +# define _LIBCPP_EXTERN_TEMPLATE(...) +#else +GCC_MESSAGE("_LIBCPP_DEBUG is not defined") +#endif + +#ifndef _LIBCPP_EXTERN_TEMPLATE +#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__; +GCC_MESSAGE("_LIBCPP_EXTERN_TEMPLATE was not defined") +#endif + +#ifndef _LIBCPP_EXTERN_TEMPLATE2 +#define _LIBCPP_EXTERN_TEMPLATE2(...) extern template __VA_ARGS__; +GCC_MESSAGE("_LIBCPP_EXTERN_TEMPLATE2 was not defined") +#endif + +#if defined(__APPLE__) && defined(__LP64__) && !defined(__x86_64__) +#define _LIBCPP_NONUNIQUE_RTTI_BIT (1ULL << 63) +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) || \ + defined(__sun__) || defined(__NetBSD__) || defined(__CloudABI__) +#define _LIBCPP_LOCALE__L_EXTENSIONS 1 +#endif + +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +// Most unix variants have catopen. These are the specific ones that don't. +#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(_NEWLIB_VERSION) && !defined(__LIBCPP_SGX) +#define _LIBCPP_HAS_CATOPEN 1 +#endif +#endif + +#ifdef __FreeBSD__ +#define _DECLARE_C99_LDBL_MATH 1 +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) +#define _LIBCPP_HAS_DEFAULTRUNELOCALE +#endif + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun__) +#define _LIBCPP_WCTYPE_IS_MASK +#endif + +#ifndef _LIBCPP_STD_VER +# if __cplusplus <= 201103L +# define _LIBCPP_STD_VER 11 +# elif __cplusplus <= 201402L +# define _LIBCPP_STD_VER 14 +# else +# define _LIBCPP_STD_VER 16 // current year, or date of c++17 ratification +# endif +#endif // _LIBCPP_STD_VER + +#if _LIBCPP_STD_VER > 11 +#define _LIBCPP_DEPRECATED [[deprecated]] +#else +#define _LIBCPP_DEPRECATED +#endif + +#if _LIBCPP_STD_VER <= 11 +#define _LIBCPP_EXPLICIT_AFTER_CXX11 +#define _LIBCPP_DEPRECATED_AFTER_CXX11 +#else +#define _LIBCPP_EXPLICIT_AFTER_CXX11 explicit +#define _LIBCPP_DEPRECATED_AFTER_CXX11 [[deprecated]] +#endif + +#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) +#define _LIBCPP_CONSTEXPR_AFTER_CXX11 constexpr +#else +#define _LIBCPP_CONSTEXPR_AFTER_CXX11 +#endif + +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) +#define _LIBCPP_CONSTEXPR_AFTER_CXX14 constexpr +#else +#define _LIBCPP_CONSTEXPR_AFTER_CXX14 +#endif + +#ifdef _LIBCPP_HAS_NO_RVALUE_REFERENCES +# define _LIBCPP_EXPLICIT_MOVE(x) _VSTD::move(x) +#else +# define _LIBCPP_EXPLICIT_MOVE(x) (x) +#endif + +#if defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) +GCC_MESSAGE("_LIBCPP_HAS_NO_RVALUE_REFERENCES is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_RVALUE_REFERENCES is not defined") +#endif + +#ifndef _LIBCPP_HAS_NO_ASAN +extern "C" void __sanitizer_annotate_contiguous_container( + const void *, const void *, const void *, const void *); +#endif + +// Try to find out if RTTI is disabled. +// g++ and cl.exe have RTTI on by default and define a macro when it is. +// g++ only defines the macro in 4.3.2 and onwards. +#if !defined(_LIBCPP_NO_RTTI) +# if defined(__GNUC__) && ((__GNUC__ >= 5) || (__GNUC__ == 4 && \ + (__GNUC_MINOR__ >= 3 || __GNUC_PATCHLEVEL__ >= 2))) && !defined(__GXX_RTTI) +# define _LIBCPP_NO_RTTI +# elif (defined(_MSC_VER) && !defined(__clang__)) && !defined(_CPPRTTI) +# define _LIBCPP_NO_RTTI +# endif +#endif + +#if defined(_LIBCPP_NO_RTTI) +GCC_MESSAGE("_LIBCPP_NO_RTTI is defined") +#else +GCC_MESSAGE("_LIBCPP_NO_RTTI is not defined") +#endif + +#ifndef _LIBCPP_WEAK +# define _LIBCPP_WEAK __attribute__((__weak__)) +#endif + +#if defined(_LIBCPP_WEAK) +GCC_MESSAGE("_LIBCPP_WEAK is defined") +#else +GCC_MESSAGE("_LIBCPP_WEAK is not defined") +#endif + +// Thread API +#if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +# if defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__linux__) || \ + defined(__APPLE__) || \ + defined(__CloudABI__) || \ + defined(__sun__) +# define _LIBCPP_HAS_THREAD_API_PTHREAD +# else +# error "No thread API" +# endif // _LIBCPP_HAS_THREAD_API +#endif // _LIBCPP_HAS_NO_THREADS + +#if defined(_LIBCPP_HAS_NO_THREADS) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +# error _LIBCPP_HAS_THREAD_API_PTHREAD may only be defined when \ + _LIBCPP_HAS_NO_THREADS is not defined. +#endif + +#if defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(_LIBCPP_HAS_NO_THREADS) +# error _LIBCPP_HAS_NO_MONOTONIC_CLOCK may only be defined when \ + _LIBCPP_HAS_NO_THREADS is defined. +#endif + +// Systems that use capability-based security (FreeBSD with Capsicum, +// Nuxi CloudABI) may only provide local filesystem access (using *at()). +// Functions like open(), rename(), unlink() and stat() should not be +// used, as they attempt to access the global filesystem namespace. +#ifdef __CloudABI__ +#define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE +#endif + +// CloudABI is intended for running networked services. Processes do not +// have standard input and output channels. +#ifdef __CloudABI__ +#define _LIBCPP_HAS_NO_STDIN +#define _LIBCPP_HAS_NO_STDOUT +#endif + +#if defined(__ANDROID__) || defined(__CloudABI__) || defined(_LIBCPP_HAS_MUSL_LIBC) +#define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE +#endif + +// Thread-unsafe functions such as strtok(), mbtowc() and localtime() +// are not available. +#ifdef __CloudABI__ +#define _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS +#endif + +#if __has_feature(cxx_atomic) || __has_extension(c_atomic) +#define _LIBCPP_HAS_C_ATOMIC_IMP +#elif _GNUC_VER > 407 +#define _LIBCPP_HAS_GCC_ATOMIC_IMP +#endif + +#if (!defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_GCC_ATOMIC_IMP)) \ + || defined(_LIBCPP_HAS_NO_THREADS) +#define _LIBCPP_HAS_NO_ATOMIC_HEADER +GCC_MESSAGE("_LIBCPP_HAS_NO_ATOMIC_HEADER is defined") +#else +GCC_MESSAGE("_LIBCPP_HAS_NO_ATOMIC_HEADER is not defined") +#endif + +#ifndef _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK +#define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK +#endif + +#if __cplusplus < 201103L +#define _LIBCPP_CXX03_LANG +#else +#if defined(_LIBCPP_HAS_NO_VARIADIC_TEMPLATES) || defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) +#error Libc++ requires a feature complete C++11 compiler in C++11 or greater. +#endif +#endif + +#if (defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) && defined(__clang__) \ + && __has_attribute(acquire_capability)) +#define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS +#endif + +#endif // __cplusplus + +#endif // _LIBCPP_CONFIG diff --git a/sdk/tlibcxx/include/__config_site.in b/sdk/tlibcxx/include/__config_site.in new file mode 100644 index 00000000..6c2b7bb4 --- /dev/null +++ b/sdk/tlibcxx/include/__config_site.in @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_CONFIG_SITE +#define _LIBCPP_CONFIG_SITE + +#cmakedefine _LIBCPP_ABI_VERSION @_LIBCPP_ABI_VERSION@ +#cmakedefine _LIBCPP_ABI_UNSTABLE +#cmakedefine _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE +#cmakedefine _LIBCPP_HAS_NO_STDIN +#cmakedefine _LIBCPP_HAS_NO_STDOUT +#cmakedefine _LIBCPP_HAS_NO_THREADS +#cmakedefine _LIBCPP_HAS_NO_MONOTONIC_CLOCK +#cmakedefine _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS +#cmakedefine _LIBCPP_HAS_MUSL_LIBC +#cmakedefine _LIBCPP_HAS_THREAD_API_PTHREAD + +#endif // _LIBCPP_CONFIG_SITE diff --git a/sdk/tlibcxx/include/__debug b/sdk/tlibcxx/include/__debug new file mode 100644 index 00000000..80395974 --- /dev/null +++ b/sdk/tlibcxx/include/__debug @@ -0,0 +1,226 @@ +// -*- C++ -*- +//===--------------------------- __debug ----------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_DEBUG_H +#define _LIBCPP_DEBUG_H + +// Not supported. +#include <__config> +#if !defined(_LIBCPP_SGX_CONFIG) + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#if _LIBCPP_DEBUG_LEVEL >= 1 +# include +# include +# include +# ifndef _LIBCPP_ASSERT +# define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : (_VSTD::fprintf(stderr, "%s\n", m), _VSTD::abort())) +# endif +#endif + +#ifndef _LIBCPP_ASSERT +# define _LIBCPP_ASSERT(x, m) ((void)0) +#endif + +#if _LIBCPP_DEBUG_LEVEL >= 2 + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_TYPE_VIS __c_node; + +struct _LIBCPP_TYPE_VIS __i_node +{ + void* __i_; + __i_node* __next_; + __c_node* __c_; + +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS + __i_node(const __i_node&) = delete; + __i_node& operator=(const __i_node&) = delete; +#else +private: + __i_node(const __i_node&); + __i_node& operator=(const __i_node&); +public: +#endif + _LIBCPP_INLINE_VISIBILITY + __i_node(void* __i, __i_node* __next, __c_node* __c) + : __i_(__i), __next_(__next), __c_(__c) {} + ~__i_node(); +}; + +struct _LIBCPP_TYPE_VIS __c_node +{ + void* __c_; + __c_node* __next_; + __i_node** beg_; + __i_node** end_; + __i_node** cap_; + +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS + __c_node(const __c_node&) = delete; + __c_node& operator=(const __c_node&) = delete; +#else +private: + __c_node(const __c_node&); + __c_node& operator=(const __c_node&); +public: +#endif + _LIBCPP_INLINE_VISIBILITY + __c_node(void* __c, __c_node* __next) + : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {} + virtual ~__c_node(); + + virtual bool __dereferenceable(const void*) const = 0; + virtual bool __decrementable(const void*) const = 0; + virtual bool __addable(const void*, ptrdiff_t) const = 0; + virtual bool __subscriptable(const void*, ptrdiff_t) const = 0; + + void __add(__i_node* __i); + _LIBCPP_HIDDEN void __remove(__i_node* __i); +}; + +template +struct _C_node + : public __c_node +{ + _C_node(void* __c, __c_node* __n) + : __c_node(__c, __n) {} + + virtual bool __dereferenceable(const void*) const; + virtual bool __decrementable(const void*) const; + virtual bool __addable(const void*, ptrdiff_t) const; + virtual bool __subscriptable(const void*, ptrdiff_t) const; +}; + +template +bool +_C_node<_Cont>::__dereferenceable(const void* __i) const +{ + typedef typename _Cont::const_iterator iterator; + const iterator* __j = static_cast(__i); + _Cont* _Cp = static_cast<_Cont*>(__c_); + return _Cp->__dereferenceable(__j); +} + +template +bool +_C_node<_Cont>::__decrementable(const void* __i) const +{ + typedef typename _Cont::const_iterator iterator; + const iterator* __j = static_cast(__i); + _Cont* _Cp = static_cast<_Cont*>(__c_); + return _Cp->__decrementable(__j); +} + +template +bool +_C_node<_Cont>::__addable(const void* __i, ptrdiff_t __n) const +{ + typedef typename _Cont::const_iterator iterator; + const iterator* __j = static_cast(__i); + _Cont* _Cp = static_cast<_Cont*>(__c_); + return _Cp->__addable(__j, __n); +} + +template +bool +_C_node<_Cont>::__subscriptable(const void* __i, ptrdiff_t __n) const +{ + typedef typename _Cont::const_iterator iterator; + const iterator* __j = static_cast(__i); + _Cont* _Cp = static_cast<_Cont*>(__c_); + return _Cp->__subscriptable(__j, __n); +} + +class _LIBCPP_TYPE_VIS __libcpp_db +{ + __c_node** __cbeg_; + __c_node** __cend_; + size_t __csz_; + __i_node** __ibeg_; + __i_node** __iend_; + size_t __isz_; + + __libcpp_db(); +public: +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS + __libcpp_db(const __libcpp_db&) = delete; + __libcpp_db& operator=(const __libcpp_db&) = delete; +#else +private: + __libcpp_db(const __libcpp_db&); + __libcpp_db& operator=(const __libcpp_db&); +public: +#endif + ~__libcpp_db(); + + class __db_c_iterator; + class __db_c_const_iterator; + class __db_i_iterator; + class __db_i_const_iterator; + + __db_c_const_iterator __c_end() const; + __db_i_const_iterator __i_end() const; + + template + _LIBCPP_INLINE_VISIBILITY + void __insert_c(_Cont* __c) + { + __c_node* __n = __insert_c(static_cast(__c)); + ::new(__n) _C_node<_Cont>(__n->__c_, __n->__next_); + } + + void __insert_i(void* __i); + __c_node* __insert_c(void* __c); + void __erase_c(void* __c); + + void __insert_ic(void* __i, const void* __c); + void __iterator_copy(void* __i, const void* __i0); + void __erase_i(void* __i); + + void* __find_c_from_i(void* __i) const; + void __invalidate_all(void* __c); + __c_node* __find_c_and_lock(void* __c) const; + __c_node* __find_c(void* __c) const; + void unlock() const; + + void swap(void* __c1, void* __c2); + + + bool __dereferenceable(const void* __i) const; + bool __decrementable(const void* __i) const; + bool __addable(const void* __i, ptrdiff_t __n) const; + bool __subscriptable(const void* __i, ptrdiff_t __n) const; + bool __less_than_comparable(const void* __i, const void* __j) const; +private: + _LIBCPP_HIDDEN + __i_node* __insert_iterator(void* __i); + _LIBCPP_HIDDEN + __i_node* __find_iterator(const void* __i) const; + + friend _LIBCPP_FUNC_VIS __libcpp_db* __get_db(); +}; + +_LIBCPP_FUNC_VIS __libcpp_db* __get_db(); +_LIBCPP_FUNC_VIS const __libcpp_db* __get_const_db(); + + +_LIBCPP_END_NAMESPACE_STD + +#endif + +#endif // !defined(_LIBCPP_SGX_CONFIG) + +#endif // _LIBCPP_DEBUG_H + diff --git a/sdk/tlibcxx/include/__functional_03 b/sdk/tlibcxx/include/__functional_03 new file mode 100644 index 00000000..4edbb099 --- /dev/null +++ b/sdk/tlibcxx/include/__functional_03 @@ -0,0 +1,1576 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_FUNCTIONAL_03 +#define _LIBCPP_FUNCTIONAL_03 + +// manual variadic expansion for + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +namespace __function { + +template class __base; + +template +class __base<_Rp()> +{ + __base(const __base&); + __base& operator=(const __base&); +public: + __base() {} + virtual ~__base() {} + virtual __base* __clone() const = 0; + virtual void __clone(__base*) const = 0; + virtual void destroy() = 0; + virtual void destroy_deallocate() = 0; + virtual _Rp operator()() = 0; +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const = 0; + virtual const std::type_info& target_type() const = 0; +#endif // _LIBCPP_NO_RTTI +}; + +template +class __base<_Rp(_A0)> +{ + __base(const __base&); + __base& operator=(const __base&); +public: + __base() {} + virtual ~__base() {} + virtual __base* __clone() const = 0; + virtual void __clone(__base*) const = 0; + virtual void destroy() = 0; + virtual void destroy_deallocate() = 0; + virtual _Rp operator()(_A0) = 0; +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const = 0; + virtual const std::type_info& target_type() const = 0; +#endif // _LIBCPP_NO_RTTI +}; + +template +class __base<_Rp(_A0, _A1)> +{ + __base(const __base&); + __base& operator=(const __base&); +public: + __base() {} + virtual ~__base() {} + virtual __base* __clone() const = 0; + virtual void __clone(__base*) const = 0; + virtual void destroy() = 0; + virtual void destroy_deallocate() = 0; + virtual _Rp operator()(_A0, _A1) = 0; +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const = 0; + virtual const std::type_info& target_type() const = 0; +#endif // _LIBCPP_NO_RTTI +}; + +template +class __base<_Rp(_A0, _A1, _A2)> +{ + __base(const __base&); + __base& operator=(const __base&); +public: + __base() {} + virtual ~__base() {} + virtual __base* __clone() const = 0; + virtual void __clone(__base*) const = 0; + virtual void destroy() = 0; + virtual void destroy_deallocate() = 0; + virtual _Rp operator()(_A0, _A1, _A2) = 0; +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const = 0; + virtual const std::type_info& target_type() const = 0; +#endif // _LIBCPP_NO_RTTI +}; + +template class __func; + +template +class __func<_Fp, _Alloc, _Rp()> + : public __base<_Rp()> +{ + __compressed_pair<_Fp, _Alloc> __f_; +public: + explicit __func(_Fp __f) : __f_(_VSTD::move(__f)) {} + explicit __func(_Fp __f, _Alloc __a) : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} + virtual __base<_Rp()>* __clone() const; + virtual void __clone(__base<_Rp()>*) const; + virtual void destroy(); + virtual void destroy_deallocate(); + virtual _Rp operator()(); +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const; + virtual const std::type_info& target_type() const; +#endif // _LIBCPP_NO_RTTI +}; + +template +__base<_Rp()>* +__func<_Fp, _Alloc, _Rp()>::__clone() const +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; + _Ap __a(__f_.second()); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) __func(__f_.first(), _Alloc(__a)); + return __hold.release(); +} + +template +void +__func<_Fp, _Alloc, _Rp()>::__clone(__base<_Rp()>* __p) const +{ + ::new (__p) __func(__f_.first(), __f_.second()); +} + +template +void +__func<_Fp, _Alloc, _Rp()>::destroy() +{ + __f_.~__compressed_pair<_Fp, _Alloc>(); +} + +template +void +__func<_Fp, _Alloc, _Rp()>::destroy_deallocate() +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; + _Ap __a(__f_.second()); + __f_.~__compressed_pair<_Fp, _Alloc>(); + __a.deallocate(this, 1); +} + +template +_Rp +__func<_Fp, _Alloc, _Rp()>::operator()() +{ + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first()); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const void* +__func<_Fp, _Alloc, _Rp()>::target(const type_info& __ti) const +{ + if (__ti == typeid(_Fp)) + return &__f_.first(); + return (const void*)0; +} + +template +const std::type_info& +__func<_Fp, _Alloc, _Rp()>::target_type() const +{ + return typeid(_Fp); +} + +#endif // _LIBCPP_NO_RTTI + +template +class __func<_Fp, _Alloc, _Rp(_A0)> + : public __base<_Rp(_A0)> +{ + __compressed_pair<_Fp, _Alloc> __f_; +public: + _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f)) {} + _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) + : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} + virtual __base<_Rp(_A0)>* __clone() const; + virtual void __clone(__base<_Rp(_A0)>*) const; + virtual void destroy(); + virtual void destroy_deallocate(); + virtual _Rp operator()(_A0); +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const; + virtual const std::type_info& target_type() const; +#endif // _LIBCPP_NO_RTTI +}; + +template +__base<_Rp(_A0)>* +__func<_Fp, _Alloc, _Rp(_A0)>::__clone() const +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; + _Ap __a(__f_.second()); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) __func(__f_.first(), _Alloc(__a)); + return __hold.release(); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0)>::__clone(__base<_Rp(_A0)>* __p) const +{ + ::new (__p) __func(__f_.first(), __f_.second()); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0)>::destroy() +{ + __f_.~__compressed_pair<_Fp, _Alloc>(); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0)>::destroy_deallocate() +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; + _Ap __a(__f_.second()); + __f_.~__compressed_pair<_Fp, _Alloc>(); + __a.deallocate(this, 1); +} + +template +_Rp +__func<_Fp, _Alloc, _Rp(_A0)>::operator()(_A0 __a0) +{ + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), __a0); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const void* +__func<_Fp, _Alloc, _Rp(_A0)>::target(const type_info& __ti) const +{ + if (__ti == typeid(_Fp)) + return &__f_.first(); + return (const void*)0; +} + +template +const std::type_info& +__func<_Fp, _Alloc, _Rp(_A0)>::target_type() const +{ + return typeid(_Fp); +} + +#endif // _LIBCPP_NO_RTTI + +template +class __func<_Fp, _Alloc, _Rp(_A0, _A1)> + : public __base<_Rp(_A0, _A1)> +{ + __compressed_pair<_Fp, _Alloc> __f_; +public: + _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f)) {} + _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) + : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} + virtual __base<_Rp(_A0, _A1)>* __clone() const; + virtual void __clone(__base<_Rp(_A0, _A1)>*) const; + virtual void destroy(); + virtual void destroy_deallocate(); + virtual _Rp operator()(_A0, _A1); +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const; + virtual const std::type_info& target_type() const; +#endif // _LIBCPP_NO_RTTI +}; + +template +__base<_Rp(_A0, _A1)>* +__func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone() const +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; + _Ap __a(__f_.second()); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) __func(__f_.first(), _Alloc(__a)); + return __hold.release(); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone(__base<_Rp(_A0, _A1)>* __p) const +{ + ::new (__p) __func(__f_.first(), __f_.second()); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy() +{ + __f_.~__compressed_pair<_Fp, _Alloc>(); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy_deallocate() +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; + _Ap __a(__f_.second()); + __f_.~__compressed_pair<_Fp, _Alloc>(); + __a.deallocate(this, 1); +} + +template +_Rp +__func<_Fp, _Alloc, _Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) +{ + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), __a0, __a1); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const void* +__func<_Fp, _Alloc, _Rp(_A0, _A1)>::target(const type_info& __ti) const +{ + if (__ti == typeid(_Fp)) + return &__f_.first(); + return (const void*)0; +} + +template +const std::type_info& +__func<_Fp, _Alloc, _Rp(_A0, _A1)>::target_type() const +{ + return typeid(_Fp); +} + +#endif // _LIBCPP_NO_RTTI + +template +class __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> + : public __base<_Rp(_A0, _A1, _A2)> +{ + __compressed_pair<_Fp, _Alloc> __f_; +public: + _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f) : __f_(_VSTD::move(__f)) {} + _LIBCPP_INLINE_VISIBILITY explicit __func(_Fp __f, _Alloc __a) + : __f_(_VSTD::move(__f), _VSTD::move(__a)) {} + virtual __base<_Rp(_A0, _A1, _A2)>* __clone() const; + virtual void __clone(__base<_Rp(_A0, _A1, _A2)>*) const; + virtual void destroy(); + virtual void destroy_deallocate(); + virtual _Rp operator()(_A0, _A1, _A2); +#ifndef _LIBCPP_NO_RTTI + virtual const void* target(const type_info&) const; + virtual const std::type_info& target_type() const; +#endif // _LIBCPP_NO_RTTI +}; + +template +__base<_Rp(_A0, _A1, _A2)>* +__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone() const +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; + _Ap __a(__f_.second()); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) __func(__f_.first(), _Alloc(__a)); + return __hold.release(); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone(__base<_Rp(_A0, _A1, _A2)>* __p) const +{ + ::new (__p) __func(__f_.first(), __f_.second()); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy() +{ + __f_.~__compressed_pair<_Fp, _Alloc>(); +} + +template +void +__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy_deallocate() +{ + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; + _Ap __a(__f_.second()); + __f_.~__compressed_pair<_Fp, _Alloc>(); + __a.deallocate(this, 1); +} + +template +_Rp +__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) +{ + typedef __invoke_void_return_wrapper<_Rp> _Invoker; + return _Invoker::__call(__f_.first(), __a0, __a1, __a2); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const void* +__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target(const type_info& __ti) const +{ + if (__ti == typeid(_Fp)) + return &__f_.first(); + return (const void*)0; +} + +template +const std::type_info& +__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::target_type() const +{ + return typeid(_Fp); +} + +#endif // _LIBCPP_NO_RTTI + +} // __function + +template +class _LIBCPP_TYPE_VIS_ONLY function<_Rp()> +{ + typedef __function::__base<_Rp()> __base; + aligned_storage<3*sizeof(void*)>::type __buf_; + __base* __f_; + +public: + typedef _Rp result_type; + + // 20.7.16.2.1, construct/copy/destroy: + _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} + _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} + function(const function&); + template + function(_Fp, + typename enable_if::value>::type* = 0); + + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc& __a, _Fp __f, + typename enable_if::value>::type* = 0); + + function& operator=(const function&); + function& operator=(nullptr_t); + template + typename enable_if + < + !is_integral<_Fp>::value, + function& + >::type + operator=(_Fp); + + ~function(); + + // 20.7.16.2.2, function modifiers: + void swap(function&); + template + _LIBCPP_INLINE_VISIBILITY + void assign(_Fp __f, const _Alloc& __a) + {function(allocator_arg, __a, __f).swap(*this);} + + // 20.7.16.2.3, function capacity: + _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;} + +private: + // deleted overloads close possible hole in the type system + template + bool operator==(const function<_R2()>&) const;// = delete; + template + bool operator!=(const function<_R2()>&) const;// = delete; +public: + // 20.7.16.2.4, function invocation: + _Rp operator()() const; + +#ifndef _LIBCPP_NO_RTTI + // 20.7.16.2.5, function target access: + const std::type_info& target_type() const; + template _Tp* target(); + template const _Tp* target() const; +#endif // _LIBCPP_NO_RTTI +}; + +template +function<_Rp()>::function(const function& __f) +{ + if (__f.__f_ == 0) + __f_ = 0; + else if (__f.__f_ == (const __base*)&__f.__buf_) + { + __f_ = (__base*)&__buf_; + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); +} + +template +template +function<_Rp()>::function(allocator_arg_t, const _Alloc&, const function& __f) +{ + if (__f.__f_ == 0) + __f_ = 0; + else if (__f.__f_ == (const __base*)&__f.__buf_) + { + __f_ = (__base*)&__buf_; + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); +} + +template +template +function<_Rp()>::function(_Fp __f, + typename enable_if::value>::type*) + : __f_(0) +{ + if (__function::__not_null(__f)) + { + typedef __function::__func<_Fp, allocator<_Fp>, _Rp()> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new (__f_) _FF(__f); + } + else + { + typedef allocator<_FF> _Ap; + _Ap __a; + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) _FF(__f, allocator<_Fp>(__a)); + __f_ = __hold.release(); + } + } +} + +template +template +function<_Rp()>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, + typename enable_if::value>::type*) + : __f_(0) +{ + typedef allocator_traits<_Alloc> __alloc_traits; + if (__function::__not_null(__f)) + { + typedef __function::__func<_Fp, _Alloc, _Rp()> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new (__f_) _FF(__f, __a0); + } + else + { + typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; + _Ap __a(__a0); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) _FF(__f, _Alloc(__a)); + __f_ = __hold.release(); + } + } +} + +template +function<_Rp()>& +function<_Rp()>::operator=(const function& __f) +{ + function(__f).swap(*this); + return *this; +} + +template +function<_Rp()>& +function<_Rp()>::operator=(nullptr_t) +{ + if (__f_ == (__base*)&__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); + __f_ = 0; + return *this; +} + +template +template +typename enable_if +< + !is_integral<_Fp>::value, + function<_Rp()>& +>::type +function<_Rp()>::operator=(_Fp __f) +{ + function(_VSTD::move(__f)).swap(*this); + return *this; +} + +template +function<_Rp()>::~function() +{ + if (__f_ == (__base*)&__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); +} + +template +void +function<_Rp()>::swap(function& __f) +{ + if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) + { + typename aligned_storage::type __tempbuf; + __base* __t = (__base*)&__tempbuf; + __f_->__clone(__t); + __f_->destroy(); + __f_ = 0; + __f.__f_->__clone((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = 0; + __f_ = (__base*)&__buf_; + __t->__clone((__base*)&__f.__buf_); + __t->destroy(); + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f_ == (__base*)&__buf_) + { + __f_->__clone((__base*)&__f.__buf_); + __f_->destroy(); + __f_ = __f.__f_; + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f.__f_ == (__base*)&__f.__buf_) + { + __f.__f_->__clone((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = __f_; + __f_ = (__base*)&__buf_; + } + else + _VSTD::swap(__f_, __f.__f_); +} + +template +_Rp +function<_Rp()>::operator()() const +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__f_ == 0) + throw bad_function_call(); +#endif // _LIBCPP_NO_EXCEPTIONS + return (*__f_)(); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const std::type_info& +function<_Rp()>::target_type() const +{ + if (__f_ == 0) + return typeid(void); + return __f_->target_type(); +} + +template +template +_Tp* +function<_Rp()>::target() +{ + if (__f_ == 0) + return (_Tp*)0; + return (_Tp*)__f_->target(typeid(_Tp)); +} + +template +template +const _Tp* +function<_Rp()>::target() const +{ + if (__f_ == 0) + return (const _Tp*)0; + return (const _Tp*)__f_->target(typeid(_Tp)); +} + +#endif // _LIBCPP_NO_RTTI + +template +class _LIBCPP_TYPE_VIS_ONLY function<_Rp(_A0)> + : public unary_function<_A0, _Rp> +{ + typedef __function::__base<_Rp(_A0)> __base; + aligned_storage<3*sizeof(void*)>::type __buf_; + __base* __f_; + +public: + typedef _Rp result_type; + + // 20.7.16.2.1, construct/copy/destroy: + _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} + _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} + function(const function&); + template + function(_Fp, + typename enable_if::value>::type* = 0); + + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc& __a, _Fp __f, + typename enable_if::value>::type* = 0); + + function& operator=(const function&); + function& operator=(nullptr_t); + template + typename enable_if + < + !is_integral<_Fp>::value, + function& + >::type + operator=(_Fp); + + ~function(); + + // 20.7.16.2.2, function modifiers: + void swap(function&); + template + _LIBCPP_INLINE_VISIBILITY + void assign(_Fp __f, const _Alloc& __a) + {function(allocator_arg, __a, __f).swap(*this);} + + // 20.7.16.2.3, function capacity: + _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;} + +private: + // deleted overloads close possible hole in the type system + template + bool operator==(const function<_R2(_B0)>&) const;// = delete; + template + bool operator!=(const function<_R2(_B0)>&) const;// = delete; +public: + // 20.7.16.2.4, function invocation: + _Rp operator()(_A0) const; + +#ifndef _LIBCPP_NO_RTTI + // 20.7.16.2.5, function target access: + const std::type_info& target_type() const; + template _Tp* target(); + template const _Tp* target() const; +#endif // _LIBCPP_NO_RTTI +}; + +template +function<_Rp(_A0)>::function(const function& __f) +{ + if (__f.__f_ == 0) + __f_ = 0; + else if (__f.__f_ == (const __base*)&__f.__buf_) + { + __f_ = (__base*)&__buf_; + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); +} + +template +template +function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc&, const function& __f) +{ + if (__f.__f_ == 0) + __f_ = 0; + else if (__f.__f_ == (const __base*)&__f.__buf_) + { + __f_ = (__base*)&__buf_; + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); +} + +template +template +function<_Rp(_A0)>::function(_Fp __f, + typename enable_if::value>::type*) + : __f_(0) +{ + if (__function::__not_null(__f)) + { + typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0)> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new (__f_) _FF(__f); + } + else + { + typedef allocator<_FF> _Ap; + _Ap __a; + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) _FF(__f, allocator<_Fp>(__a)); + __f_ = __hold.release(); + } + } +} + +template +template +function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, + typename enable_if::value>::type*) + : __f_(0) +{ + typedef allocator_traits<_Alloc> __alloc_traits; + if (__function::__not_null(__f)) + { + typedef __function::__func<_Fp, _Alloc, _Rp(_A0)> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new (__f_) _FF(__f, __a0); + } + else + { + typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; + _Ap __a(__a0); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) _FF(__f, _Alloc(__a)); + __f_ = __hold.release(); + } + } +} + +template +function<_Rp(_A0)>& +function<_Rp(_A0)>::operator=(const function& __f) +{ + function(__f).swap(*this); + return *this; +} + +template +function<_Rp(_A0)>& +function<_Rp(_A0)>::operator=(nullptr_t) +{ + if (__f_ == (__base*)&__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); + __f_ = 0; + return *this; +} + +template +template +typename enable_if +< + !is_integral<_Fp>::value, + function<_Rp(_A0)>& +>::type +function<_Rp(_A0)>::operator=(_Fp __f) +{ + function(_VSTD::move(__f)).swap(*this); + return *this; +} + +template +function<_Rp(_A0)>::~function() +{ + if (__f_ == (__base*)&__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); +} + +template +void +function<_Rp(_A0)>::swap(function& __f) +{ + if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) + { + typename aligned_storage::type __tempbuf; + __base* __t = (__base*)&__tempbuf; + __f_->__clone(__t); + __f_->destroy(); + __f_ = 0; + __f.__f_->__clone((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = 0; + __f_ = (__base*)&__buf_; + __t->__clone((__base*)&__f.__buf_); + __t->destroy(); + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f_ == (__base*)&__buf_) + { + __f_->__clone((__base*)&__f.__buf_); + __f_->destroy(); + __f_ = __f.__f_; + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f.__f_ == (__base*)&__f.__buf_) + { + __f.__f_->__clone((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = __f_; + __f_ = (__base*)&__buf_; + } + else + _VSTD::swap(__f_, __f.__f_); +} + +template +_Rp +function<_Rp(_A0)>::operator()(_A0 __a0) const +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__f_ == 0) + throw bad_function_call(); +#endif // _LIBCPP_NO_EXCEPTIONS + return (*__f_)(__a0); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const std::type_info& +function<_Rp(_A0)>::target_type() const +{ + if (__f_ == 0) + return typeid(void); + return __f_->target_type(); +} + +template +template +_Tp* +function<_Rp(_A0)>::target() +{ + if (__f_ == 0) + return (_Tp*)0; + return (_Tp*)__f_->target(typeid(_Tp)); +} + +template +template +const _Tp* +function<_Rp(_A0)>::target() const +{ + if (__f_ == 0) + return (const _Tp*)0; + return (const _Tp*)__f_->target(typeid(_Tp)); +} + +#endif // _LIBCPP_NO_RTTI + +template +class _LIBCPP_TYPE_VIS_ONLY function<_Rp(_A0, _A1)> + : public binary_function<_A0, _A1, _Rp> +{ + typedef __function::__base<_Rp(_A0, _A1)> __base; + aligned_storage<3*sizeof(void*)>::type __buf_; + __base* __f_; + +public: + typedef _Rp result_type; + + // 20.7.16.2.1, construct/copy/destroy: + _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} + _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} + function(const function&); + template + function(_Fp, + typename enable_if::value>::type* = 0); + + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc& __a, _Fp __f, + typename enable_if::value>::type* = 0); + + function& operator=(const function&); + function& operator=(nullptr_t); + template + typename enable_if + < + !is_integral<_Fp>::value, + function& + >::type + operator=(_Fp); + + ~function(); + + // 20.7.16.2.2, function modifiers: + void swap(function&); + template + _LIBCPP_INLINE_VISIBILITY + void assign(_Fp __f, const _Alloc& __a) + {function(allocator_arg, __a, __f).swap(*this);} + + // 20.7.16.2.3, function capacity: + operator bool() const {return __f_;} + +private: + // deleted overloads close possible hole in the type system + template + bool operator==(const function<_R2(_B0, _B1)>&) const;// = delete; + template + bool operator!=(const function<_R2(_B0, _B1)>&) const;// = delete; +public: + // 20.7.16.2.4, function invocation: + _Rp operator()(_A0, _A1) const; + +#ifndef _LIBCPP_NO_RTTI + // 20.7.16.2.5, function target access: + const std::type_info& target_type() const; + template _Tp* target(); + template const _Tp* target() const; +#endif // _LIBCPP_NO_RTTI +}; + +template +function<_Rp(_A0, _A1)>::function(const function& __f) +{ + if (__f.__f_ == 0) + __f_ = 0; + else if (__f.__f_ == (const __base*)&__f.__buf_) + { + __f_ = (__base*)&__buf_; + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); +} + +template +template +function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc&, const function& __f) +{ + if (__f.__f_ == 0) + __f_ = 0; + else if (__f.__f_ == (const __base*)&__f.__buf_) + { + __f_ = (__base*)&__buf_; + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); +} + +template +template +function<_Rp(_A0, _A1)>::function(_Fp __f, + typename enable_if::value>::type*) + : __f_(0) +{ + if (__function::__not_null(__f)) + { + typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1)> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new (__f_) _FF(__f); + } + else + { + typedef allocator<_FF> _Ap; + _Ap __a; + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) _FF(__f, allocator<_Fp>(__a)); + __f_ = __hold.release(); + } + } +} + +template +template +function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, + typename enable_if::value>::type*) + : __f_(0) +{ + typedef allocator_traits<_Alloc> __alloc_traits; + if (__function::__not_null(__f)) + { + typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1)> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new (__f_) _FF(__f, __a0); + } + else + { + typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; + _Ap __a(__a0); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) _FF(__f, _Alloc(__a)); + __f_ = __hold.release(); + } + } +} + +template +function<_Rp(_A0, _A1)>& +function<_Rp(_A0, _A1)>::operator=(const function& __f) +{ + function(__f).swap(*this); + return *this; +} + +template +function<_Rp(_A0, _A1)>& +function<_Rp(_A0, _A1)>::operator=(nullptr_t) +{ + if (__f_ == (__base*)&__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); + __f_ = 0; + return *this; +} + +template +template +typename enable_if +< + !is_integral<_Fp>::value, + function<_Rp(_A0, _A1)>& +>::type +function<_Rp(_A0, _A1)>::operator=(_Fp __f) +{ + function(_VSTD::move(__f)).swap(*this); + return *this; +} + +template +function<_Rp(_A0, _A1)>::~function() +{ + if (__f_ == (__base*)&__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); +} + +template +void +function<_Rp(_A0, _A1)>::swap(function& __f) +{ + if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) + { + typename aligned_storage::type __tempbuf; + __base* __t = (__base*)&__tempbuf; + __f_->__clone(__t); + __f_->destroy(); + __f_ = 0; + __f.__f_->__clone((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = 0; + __f_ = (__base*)&__buf_; + __t->__clone((__base*)&__f.__buf_); + __t->destroy(); + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f_ == (__base*)&__buf_) + { + __f_->__clone((__base*)&__f.__buf_); + __f_->destroy(); + __f_ = __f.__f_; + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f.__f_ == (__base*)&__f.__buf_) + { + __f.__f_->__clone((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = __f_; + __f_ = (__base*)&__buf_; + } + else + _VSTD::swap(__f_, __f.__f_); +} + +template +_Rp +function<_Rp(_A0, _A1)>::operator()(_A0 __a0, _A1 __a1) const +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__f_ == 0) + throw bad_function_call(); +#endif // _LIBCPP_NO_EXCEPTIONS + return (*__f_)(__a0, __a1); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const std::type_info& +function<_Rp(_A0, _A1)>::target_type() const +{ + if (__f_ == 0) + return typeid(void); + return __f_->target_type(); +} + +template +template +_Tp* +function<_Rp(_A0, _A1)>::target() +{ + if (__f_ == 0) + return (_Tp*)0; + return (_Tp*)__f_->target(typeid(_Tp)); +} + +template +template +const _Tp* +function<_Rp(_A0, _A1)>::target() const +{ + if (__f_ == 0) + return (const _Tp*)0; + return (const _Tp*)__f_->target(typeid(_Tp)); +} + +#endif // _LIBCPP_NO_RTTI + +template +class _LIBCPP_TYPE_VIS_ONLY function<_Rp(_A0, _A1, _A2)> +{ + typedef __function::__base<_Rp(_A0, _A1, _A2)> __base; + aligned_storage<3*sizeof(void*)>::type __buf_; + __base* __f_; + +public: + typedef _Rp result_type; + + // 20.7.16.2.1, construct/copy/destroy: + _LIBCPP_INLINE_VISIBILITY explicit function() : __f_(0) {} + _LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {} + function(const function&); + template + function(_Fp, + typename enable_if::value>::type* = 0); + + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&) : __f_(0) {} + template + _LIBCPP_INLINE_VISIBILITY + function(allocator_arg_t, const _Alloc&, nullptr_t) : __f_(0) {} + template + function(allocator_arg_t, const _Alloc&, const function&); + template + function(allocator_arg_t, const _Alloc& __a, _Fp __f, + typename enable_if::value>::type* = 0); + + function& operator=(const function&); + function& operator=(nullptr_t); + template + typename enable_if + < + !is_integral<_Fp>::value, + function& + >::type + operator=(_Fp); + + ~function(); + + // 20.7.16.2.2, function modifiers: + void swap(function&); + template + _LIBCPP_INLINE_VISIBILITY + void assign(_Fp __f, const _Alloc& __a) + {function(allocator_arg, __a, __f).swap(*this);} + + // 20.7.16.2.3, function capacity: + _LIBCPP_INLINE_VISIBILITY operator bool() const {return __f_;} + +private: + // deleted overloads close possible hole in the type system + template + bool operator==(const function<_R2(_B0, _B1, _B2)>&) const;// = delete; + template + bool operator!=(const function<_R2(_B0, _B1, _B2)>&) const;// = delete; +public: + // 20.7.16.2.4, function invocation: + _Rp operator()(_A0, _A1, _A2) const; + +#ifndef _LIBCPP_NO_RTTI + // 20.7.16.2.5, function target access: + const std::type_info& target_type() const; + template _Tp* target(); + template const _Tp* target() const; +#endif // _LIBCPP_NO_RTTI +}; + +template +function<_Rp(_A0, _A1, _A2)>::function(const function& __f) +{ + if (__f.__f_ == 0) + __f_ = 0; + else if (__f.__f_ == (const __base*)&__f.__buf_) + { + __f_ = (__base*)&__buf_; + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); +} + +template +template +function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc&, + const function& __f) +{ + if (__f.__f_ == 0) + __f_ = 0; + else if (__f.__f_ == (const __base*)&__f.__buf_) + { + __f_ = (__base*)&__buf_; + __f.__f_->__clone(__f_); + } + else + __f_ = __f.__f_->__clone(); +} + +template +template +function<_Rp(_A0, _A1, _A2)>::function(_Fp __f, + typename enable_if::value>::type*) + : __f_(0) +{ + if (__function::__not_null(__f)) + { + typedef __function::__func<_Fp, allocator<_Fp>, _Rp(_A0, _A1, _A2)> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new (__f_) _FF(__f); + } + else + { + typedef allocator<_FF> _Ap; + _Ap __a; + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) _FF(__f, allocator<_Fp>(__a)); + __f_ = __hold.release(); + } + } +} + +template +template +function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, + typename enable_if::value>::type*) + : __f_(0) +{ + typedef allocator_traits<_Alloc> __alloc_traits; + if (__function::__not_null(__f)) + { + typedef __function::__func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)> _FF; + if (sizeof(_FF) <= sizeof(__buf_)) + { + __f_ = (__base*)&__buf_; + ::new (__f_) _FF(__f, __a0); + } + else + { + typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap; + _Ap __a(__a0); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new (__hold.get()) _FF(__f, _Alloc(__a)); + __f_ = __hold.release(); + } + } +} + +template +function<_Rp(_A0, _A1, _A2)>& +function<_Rp(_A0, _A1, _A2)>::operator=(const function& __f) +{ + function(__f).swap(*this); + return *this; +} + +template +function<_Rp(_A0, _A1, _A2)>& +function<_Rp(_A0, _A1, _A2)>::operator=(nullptr_t) +{ + if (__f_ == (__base*)&__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); + __f_ = 0; + return *this; +} + +template +template +typename enable_if +< + !is_integral<_Fp>::value, + function<_Rp(_A0, _A1, _A2)>& +>::type +function<_Rp(_A0, _A1, _A2)>::operator=(_Fp __f) +{ + function(_VSTD::move(__f)).swap(*this); + return *this; +} + +template +function<_Rp(_A0, _A1, _A2)>::~function() +{ + if (__f_ == (__base*)&__buf_) + __f_->destroy(); + else if (__f_) + __f_->destroy_deallocate(); +} + +template +void +function<_Rp(_A0, _A1, _A2)>::swap(function& __f) +{ + if (__f_ == (__base*)&__buf_ && __f.__f_ == (__base*)&__f.__buf_) + { + typename aligned_storage::type __tempbuf; + __base* __t = (__base*)&__tempbuf; + __f_->__clone(__t); + __f_->destroy(); + __f_ = 0; + __f.__f_->__clone((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = 0; + __f_ = (__base*)&__buf_; + __t->__clone((__base*)&__f.__buf_); + __t->destroy(); + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f_ == (__base*)&__buf_) + { + __f_->__clone((__base*)&__f.__buf_); + __f_->destroy(); + __f_ = __f.__f_; + __f.__f_ = (__base*)&__f.__buf_; + } + else if (__f.__f_ == (__base*)&__f.__buf_) + { + __f.__f_->__clone((__base*)&__buf_); + __f.__f_->destroy(); + __f.__f_ = __f_; + __f_ = (__base*)&__buf_; + } + else + _VSTD::swap(__f_, __f.__f_); +} + +template +_Rp +function<_Rp(_A0, _A1, _A2)>::operator()(_A0 __a0, _A1 __a1, _A2 __a2) const +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__f_ == 0) + throw bad_function_call(); +#endif // _LIBCPP_NO_EXCEPTIONS + return (*__f_)(__a0, __a1, __a2); +} + +#ifndef _LIBCPP_NO_RTTI + +template +const std::type_info& +function<_Rp(_A0, _A1, _A2)>::target_type() const +{ + if (__f_ == 0) + return typeid(void); + return __f_->target_type(); +} + +template +template +_Tp* +function<_Rp(_A0, _A1, _A2)>::target() +{ + if (__f_ == 0) + return (_Tp*)0; + return (_Tp*)__f_->target(typeid(_Tp)); +} + +template +template +const _Tp* +function<_Rp(_A0, _A1, _A2)>::target() const +{ + if (__f_ == 0) + return (const _Tp*)0; + return (const _Tp*)__f_->target(typeid(_Tp)); +} + +#endif // _LIBCPP_NO_RTTI + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const function<_Fp>& __f, nullptr_t) {return !__f;} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(nullptr_t, const function<_Fp>& __f) {return !__f;} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const function<_Fp>& __f, nullptr_t) {return (bool)__f;} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(nullptr_t, const function<_Fp>& __f) {return (bool)__f;} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(function<_Fp>& __x, function<_Fp>& __y) +{return __x.swap(__y);} + +#endif // _LIBCPP_FUNCTIONAL_03 diff --git a/sdk/tlibcxx/include/__functional_base b/sdk/tlibcxx/include/__functional_base new file mode 100644 index 00000000..1a08ea29 --- /dev/null +++ b/sdk/tlibcxx/include/__functional_base @@ -0,0 +1,680 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_FUNCTIONAL_BASE +#define _LIBCPP_FUNCTIONAL_BASE + +#include <__config> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _LIBCPP_TYPE_VIS_ONLY unary_function +{ + typedef _Arg argument_type; + typedef _Result result_type; +}; + +template +struct _LIBCPP_TYPE_VIS_ONLY binary_function +{ + typedef _Arg1 first_argument_type; + typedef _Arg2 second_argument_type; + typedef _Result result_type; +}; + +template +struct __has_result_type +{ +private: + struct __two {char __lx; char __lxx;}; + template static __two __test(...); + template static char __test(typename _Up::result_type* = 0); +public: + static const bool value = sizeof(__test<_Tp>(0)) == 1; +}; + +#if _LIBCPP_STD_VER > 11 +template +#else +template +#endif +struct _LIBCPP_TYPE_VIS_ONLY less : binary_function<_Tp, _Tp, bool> +{ + _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY + bool operator()(const _Tp& __x, const _Tp& __y) const + {return __x < __y;} +}; + +#if _LIBCPP_STD_VER > 11 +template <> +struct _LIBCPP_TYPE_VIS_ONLY less +{ + template + _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY + auto operator()(_T1&& __t, _T2&& __u) const + _NOEXCEPT_(noexcept(_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u))) + -> decltype (_VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u)) + { return _VSTD::forward<_T1>(__t) < _VSTD::forward<_T2>(__u); } + typedef void is_transparent; +}; +#endif + +// __weak_result_type + +template +struct __derives_from_unary_function +{ +private: + struct __two {char __lx; char __lxx;}; + static __two __test(...); + template + static unary_function<_Ap, _Rp> + __test(const volatile unary_function<_Ap, _Rp>*); +public: + static const bool value = !is_same::value; + typedef decltype(__test((_Tp*)0)) type; +}; + +template +struct __derives_from_binary_function +{ +private: + struct __two {char __lx; char __lxx;}; + static __two __test(...); + template + static binary_function<_A1, _A2, _Rp> + __test(const volatile binary_function<_A1, _A2, _Rp>*); +public: + static const bool value = !is_same::value; + typedef decltype(__test((_Tp*)0)) type; +}; + +template ::value> +struct __maybe_derive_from_unary_function // bool is true + : public __derives_from_unary_function<_Tp>::type +{ +}; + +template +struct __maybe_derive_from_unary_function<_Tp, false> +{ +}; + +template ::value> +struct __maybe_derive_from_binary_function // bool is true + : public __derives_from_binary_function<_Tp>::type +{ +}; + +template +struct __maybe_derive_from_binary_function<_Tp, false> +{ +}; + +template ::value> +struct __weak_result_type_imp // bool is true + : public __maybe_derive_from_unary_function<_Tp>, + public __maybe_derive_from_binary_function<_Tp> +{ + typedef typename _Tp::result_type result_type; +}; + +template +struct __weak_result_type_imp<_Tp, false> + : public __maybe_derive_from_unary_function<_Tp>, + public __maybe_derive_from_binary_function<_Tp> +{ +}; + +template +struct __weak_result_type + : public __weak_result_type_imp<_Tp> +{ +}; + +// 0 argument case + +template +struct __weak_result_type<_Rp ()> +{ + typedef _Rp result_type; +}; + +template +struct __weak_result_type<_Rp (&)()> +{ + typedef _Rp result_type; +}; + +template +struct __weak_result_type<_Rp (*)()> +{ + typedef _Rp result_type; +}; + +// 1 argument case + +template +struct __weak_result_type<_Rp (_A1)> + : public unary_function<_A1, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (&)(_A1)> + : public unary_function<_A1, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (*)(_A1)> + : public unary_function<_A1, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)()> + : public unary_function<_Cp*, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)() const> + : public unary_function +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)() volatile> + : public unary_function +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)() const volatile> + : public unary_function +{ +}; + +// 2 argument case + +template +struct __weak_result_type<_Rp (_A1, _A2)> + : public binary_function<_A1, _A2, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (*)(_A1, _A2)> + : public binary_function<_A1, _A2, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (&)(_A1, _A2)> + : public binary_function<_A1, _A2, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1)> + : public binary_function<_Cp*, _A1, _Rp> +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1) const> + : public binary_function +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1) volatile> + : public binary_function +{ +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1) const volatile> + : public binary_function +{ +}; + + +#ifndef _LIBCPP_HAS_NO_VARIADICS +// 3 or more arguments + +template +struct __weak_result_type<_Rp (_A1, _A2, _A3, _A4...)> +{ + typedef _Rp result_type; +}; + +template +struct __weak_result_type<_Rp (&)(_A1, _A2, _A3, _A4...)> +{ + typedef _Rp result_type; +}; + +template +struct __weak_result_type<_Rp (*)(_A1, _A2, _A3, _A4...)> +{ + typedef _Rp result_type; +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...)> +{ + typedef _Rp result_type; +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const> +{ + typedef _Rp result_type; +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) volatile> +{ + typedef _Rp result_type; +}; + +template +struct __weak_result_type<_Rp (_Cp::*)(_A1, _A2, _A3...) const volatile> +{ + typedef _Rp result_type; +}; + +#endif // _LIBCPP_HAS_NO_VARIADICS + +#ifndef _LIBCPP_CXX03_LANG + +template +struct __invoke_return +{ + typedef decltype(__invoke(_VSTD::declval<_Tp>(), _VSTD::declval<_Args>()...)) type; +}; + +#else // defined(_LIBCPP_CXX03_LANG) + +#include <__functional_base_03> + +#endif // !defined(_LIBCPP_CXX03_LANG) + + +template +struct __invoke_void_return_wrapper +{ +#ifndef _LIBCPP_HAS_NO_VARIADICS + template + static _Ret __call(_Args&&... __args) { + return __invoke(_VSTD::forward<_Args>(__args)...); + } +#else + template + static _Ret __call(_Fn __f) { + return __invoke(__f); + } + + template + static _Ret __call(_Fn __f, _A0& __a0) { + return __invoke(__f, __a0); + } + + template + static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1) { + return __invoke(__f, __a0, __a1); + } + + template + static _Ret __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2){ + return __invoke(__f, __a0, __a1, __a2); + } +#endif +}; + +template <> +struct __invoke_void_return_wrapper +{ +#ifndef _LIBCPP_HAS_NO_VARIADICS + template + static void __call(_Args&&... __args) { + __invoke(_VSTD::forward<_Args>(__args)...); + } +#else + template + static void __call(_Fn __f) { + __invoke(__f); + } + + template + static void __call(_Fn __f, _A0& __a0) { + __invoke(__f, __a0); + } + + template + static void __call(_Fn __f, _A0& __a0, _A1& __a1) { + __invoke(__f, __a0, __a1); + } + + template + static void __call(_Fn __f, _A0& __a0, _A1& __a1, _A2& __a2) { + __invoke(__f, __a0, __a1, __a2); + } +#endif +}; + +template +class _LIBCPP_TYPE_VIS_ONLY reference_wrapper + : public __weak_result_type<_Tp> +{ +public: + // types + typedef _Tp type; +private: + type* __f_; + +public: + // construct/copy/destroy + _LIBCPP_INLINE_VISIBILITY reference_wrapper(type& __f) _NOEXCEPT + : __f_(_VSTD::addressof(__f)) {} +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + private: reference_wrapper(type&&); public: // = delete; // do not bind to temps +#endif + + // access + _LIBCPP_INLINE_VISIBILITY operator type& () const _NOEXCEPT {return *__f_;} + _LIBCPP_INLINE_VISIBILITY type& get() const _NOEXCEPT {return *__f_;} + +#ifndef _LIBCPP_HAS_NO_VARIADICS + // invoke + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_of::type + operator() (_ArgTypes&&... __args) const { + return __invoke(get(), _VSTD::forward<_ArgTypes>(__args)...); + } +#else + + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return::type + operator() () const { + return __invoke(get()); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return0::type + operator() (_A0& __a0) const { + return __invoke(get(), __a0); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return0::type + operator() (_A0 const& __a0) const { + return __invoke(get(), __a0); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return1::type + operator() (_A0& __a0, _A1& __a1) const { + return __invoke(get(), __a0, __a1); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return1::type + operator() (_A0 const& __a0, _A1& __a1) const { + return __invoke(get(), __a0, __a1); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return1::type + operator() (_A0& __a0, _A1 const& __a1) const { + return __invoke(get(), __a0, __a1); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return1::type + operator() (_A0 const& __a0, _A1 const& __a1) const { + return __invoke(get(), __a0, __a1); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return2::type + operator() (_A0& __a0, _A1& __a1, _A2& __a2) const { + return __invoke(get(), __a0, __a1, __a2); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return2::type + operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const { + return __invoke(get(), __a0, __a1, __a2); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return2::type + operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const { + return __invoke(get(), __a0, __a1, __a2); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return2::type + operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const { + return __invoke(get(), __a0, __a1, __a2); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return2::type + operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const { + return __invoke(get(), __a0, __a1, __a2); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return2::type + operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const { + return __invoke(get(), __a0, __a1, __a2); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return2::type + operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const { + return __invoke(get(), __a0, __a1, __a2); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename __invoke_return2::type + operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const { + return __invoke(get(), __a0, __a1, __a2); + } +#endif // _LIBCPP_HAS_NO_VARIADICS +}; + + +template +inline _LIBCPP_INLINE_VISIBILITY +reference_wrapper<_Tp> +ref(_Tp& __t) _NOEXCEPT +{ + return reference_wrapper<_Tp>(__t); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +reference_wrapper<_Tp> +ref(reference_wrapper<_Tp> __t) _NOEXCEPT +{ + return ref(__t.get()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +reference_wrapper +cref(const _Tp& __t) _NOEXCEPT +{ + return reference_wrapper(__t); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +reference_wrapper +cref(reference_wrapper<_Tp> __t) _NOEXCEPT +{ + return cref(__t.get()); +} + +#ifndef _LIBCPP_HAS_NO_VARIADICS +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS + +template void ref(const _Tp&&) = delete; +template void cref(const _Tp&&) = delete; + +#else // _LIBCPP_HAS_NO_DELETED_FUNCTIONS + +template void ref(const _Tp&&);// = delete; +template void cref(const _Tp&&);// = delete; + +#endif // _LIBCPP_HAS_NO_DELETED_FUNCTIONS + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + +#endif // _LIBCPP_HAS_NO_VARIADICS + +#if _LIBCPP_STD_VER > 11 +template +struct __is_transparent +{ +private: + struct __two {char __lx; char __lxx;}; + template static __two __test(...); + template static char __test(typename _Up::is_transparent* = 0); +public: + static const bool value = sizeof(__test<_Tp1>(0)) == 1; +}; +#endif + +// allocator_arg_t + +struct _LIBCPP_TYPE_VIS_ONLY allocator_arg_t { }; + +#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MEMORY) +extern const allocator_arg_t allocator_arg; +#else +constexpr allocator_arg_t allocator_arg = allocator_arg_t(); +#endif + +// uses_allocator + +template +struct __has_allocator_type +{ +private: + struct __two {char __lx; char __lxx;}; + template static __two __test(...); + template static char __test(typename _Up::allocator_type* = 0); +public: + static const bool value = sizeof(__test<_Tp>(0)) == 1; +}; + +template ::value> +struct __uses_allocator + : public integral_constant::value> +{ +}; + +template +struct __uses_allocator<_Tp, _Alloc, false> + : public false_type +{ +}; + +template +struct _LIBCPP_TYPE_VIS_ONLY uses_allocator + : public __uses_allocator<_Tp, _Alloc> +{ +}; + +#ifndef _LIBCPP_HAS_NO_VARIADICS + +// allocator construction + +template +struct __uses_alloc_ctor_imp +{ + static const bool __ua = uses_allocator<_Tp, _Alloc>::value; + static const bool __ic = + is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value; + static const int value = __ua ? 2 - __ic : 0; +}; + +template +struct __uses_alloc_ctor + : integral_constant::value> + {}; + +template +inline _LIBCPP_INLINE_VISIBILITY +void __user_alloc_construct_impl (integral_constant, _Tp *__storage, const _Allocator &, _Args &&... __args ) +{ + new (__storage) _Tp (_VSTD::forward<_Args>(__args)...); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void __user_alloc_construct_impl (integral_constant, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) +{ + new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void __user_alloc_construct_impl (integral_constant, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) +{ + new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void __user_alloc_construct (_Tp *__storage, const _Allocator &__a, _Args &&... __args) +{ + __user_alloc_construct_impl( + __uses_alloc_ctor<_Tp, _Allocator>(), + __storage, __a, _VSTD::forward<_Args>(__args)... + ); +} +#endif // _LIBCPP_HAS_NO_VARIADICS + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_FUNCTIONAL_BASE diff --git a/sdk/tlibcxx/include/__functional_base_03 b/sdk/tlibcxx/include/__functional_base_03 new file mode 100644 index 00000000..8407dcfa --- /dev/null +++ b/sdk/tlibcxx/include/__functional_base_03 @@ -0,0 +1,224 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_FUNCTIONAL_BASE_03 +#define _LIBCPP_FUNCTIONAL_BASE_03 + +// manual variadic expansion for + +// __invoke + +template +struct __enable_invoke_imp; + +template +struct __enable_invoke_imp<_Ret, _T1, true, true> { + typedef _Ret _Bullet1; + typedef _Bullet1 type; +}; + +template +struct __enable_invoke_imp<_Ret, _T1, true, false> { + typedef _Ret _Bullet2; + typedef _Bullet2 type; +}; + +template +struct __enable_invoke_imp<_Ret, _T1, false, true> { + typedef typename add_lvalue_reference< + typename __apply_cv<_T1, _Ret>::type + >::type _Bullet3; + typedef _Bullet3 type; +}; + +template +struct __enable_invoke_imp<_Ret, _T1, false, false> { + typedef typename add_lvalue_reference< + typename __apply_cv()), _Ret>::type + >::type _Bullet4; + typedef _Bullet4 type; +}; + +template +struct __enable_invoke_imp<_Ret, _T1*, false, false> { + typedef typename add_lvalue_reference< + typename __apply_cv<_T1, _Ret>::type + >::type _Bullet4; + typedef _Bullet4 type; +}; + +template , + class _Ret = typename _Traits::_ReturnType, + class _Class = typename _Traits::_ClassType> +struct __enable_invoke : __enable_invoke_imp< + _Ret, _T1, + is_member_function_pointer<_Fn>::value, + is_base_of<_Class, typename remove_reference<_T1>::type>::value> +{ +}; + +__nat __invoke(__any, ...); + +// first bullet + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet1 +__invoke(_Fn __f, _T1& __t1) { + return (__t1.*__f)(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet1 +__invoke(_Fn __f, _T1& __t1, _A0& __a0) { + return (__t1.*__f)(__a0); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet1 +__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) { + return (__t1.*__f)(__a0, __a1); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet1 +__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) { + return (__t1.*__f)(__a0, __a1, __a2); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet2 +__invoke(_Fn __f, _T1& __t1) { + return ((*__t1).*__f)(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet2 +__invoke(_Fn __f, _T1& __t1, _A0& __a0) { + return ((*__t1).*__f)(__a0); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet2 +__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1) { + return ((*__t1).*__f)(__a0, __a1); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet2 +__invoke(_Fn __f, _T1& __t1, _A0& __a0, _A1& __a1, _A2& __a2) { + return ((*__t1).*__f)(__a0, __a1, __a2); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet3 +__invoke(_Fn __f, _T1& __t1) { + return __t1.*__f; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +typename __enable_invoke<_Fn, _T1>::_Bullet4 +__invoke(_Fn __f, _T1& __t1) { + return (*__t1).*__f; +} + +// fifth bullet + +template +inline _LIBCPP_INLINE_VISIBILITY +decltype(_VSTD::declval<_Fp&>()()) +__invoke(_Fp& __f) +{ + return __f(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>())) +__invoke(_Fp& __f, _A0& __a0) +{ + return __f(__a0); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>())) +__invoke(_Fp& __f, _A0& __a0, _A1& __a1) +{ + return __f(__a0, __a1); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +decltype(_VSTD::declval<_Fp&>()(_VSTD::declval<_A0&>(), _VSTD::declval<_A1&>(), _VSTD::declval<_A2&>())) +__invoke(_Fp& __f, _A0& __a0, _A1& __a1, _A2& __a2) +{ + return __f(__a0, __a1, __a2); +} + +template >::value> +struct __invoke_return +{ + typedef typename __weak_result_type<_Fp>::result_type type; +}; + +template +struct __invoke_return<_Fp, false> +{ + typedef decltype(__invoke(_VSTD::declval<_Fp&>())) type; +}; + +template +struct __invoke_return0 +{ + typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>())) type; +}; + +template +struct __invoke_return0<_Rp _Tp::*, _A0> +{ + typedef typename __enable_invoke<_Rp _Tp::*, _A0>::type type; +}; + +template +struct __invoke_return1 +{ + typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(), + _VSTD::declval<_A1&>())) type; +}; + +template +struct __invoke_return1<_Rp _Class::*, _A0, _A1> { + typedef typename __enable_invoke<_Rp _Class::*, _A0>::type type; +}; + +template +struct __invoke_return2 +{ + typedef decltype(__invoke(_VSTD::declval<_Tp&>(), _VSTD::declval<_A0&>(), + _VSTD::declval<_A1&>(), + _VSTD::declval<_A2&>())) type; +}; + +template +struct __invoke_return2<_Ret _Class::*, _A0, _A1, _A2> { + typedef typename __enable_invoke<_Ret _Class::*, _A0>::type type; +}; +#endif // _LIBCPP_FUNCTIONAL_BASE_03 diff --git a/sdk/tlibcxx/include/__hash_table b/sdk/tlibcxx/include/__hash_table new file mode 100644 index 00000000..318619cf --- /dev/null +++ b/sdk/tlibcxx/include/__hash_table @@ -0,0 +1,2648 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP__HASH_TABLE +#define _LIBCPP__HASH_TABLE + +#include <__config> +#include +#include +#include +#include +#include +#include + +#include <__undef_min_max> +#include <__undef___deallocate> + +#include <__debug> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + + +#ifndef _LIBCPP_CXX03_LANG +template +union __hash_value_type; +#else +template +struct __hash_value_type; +#endif + +#ifndef _LIBCPP_CXX03_LANG +template +struct __is_hash_value_type_imp : false_type {}; + +template +struct __is_hash_value_type_imp<__hash_value_type<_Key, _Value>> : true_type {}; + +template +struct __is_hash_value_type : false_type {}; + +template +struct __is_hash_value_type<_One> : __is_hash_value_type_imp::type> {}; +#endif + +_LIBCPP_FUNC_VIS +size_t __next_prime(size_t __n); + +template +struct __hash_node_base +{ + typedef __hash_node_base __first_node; + + _NodePtr __next_; + + _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {} +}; + +template +struct __hash_node + : public __hash_node_base + < + typename __rebind_pointer<_VoidPtr, __hash_node<_Tp, _VoidPtr> >::type + > +{ + typedef _Tp __node_value_type; + + size_t __hash_; + __node_value_type __value_; +}; + +inline _LIBCPP_INLINE_VISIBILITY +bool +__is_hash_power2(size_t __bc) +{ + return __bc > 2 && !(__bc & (__bc - 1)); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t +__constrain_hash(size_t __h, size_t __bc) +{ + return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : + (__h < __bc ? __h : __h % __bc); +} + +inline _LIBCPP_INLINE_VISIBILITY +size_t +__next_hash_pow2(size_t __n) +{ + return size_t(1) << (std::numeric_limits::digits - __clz(__n-1)); +} + + +template class __hash_table; + +template class _LIBCPP_TYPE_VIS_ONLY __hash_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; + +template +struct __hash_key_value_types { + static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, ""); + typedef _Tp key_type; + typedef _Tp __node_value_type; + typedef _Tp __container_value_type; + static const bool __is_map = false; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& __get_key(_Tp const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type const& __get_value(__node_value_type const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n); + } +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + static __container_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v); + } +#endif +}; + +template +struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > { + typedef _Key key_type; + typedef _Tp mapped_type; + typedef __hash_value_type<_Key, _Tp> __node_value_type; + typedef pair __container_value_type; + typedef pair<_Key, _Tp> __nc_value_type; + typedef __container_value_type __map_value_type; + static const bool __is_map = true; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& __get_key(__container_value_type const& __v) { + return __v.first; + } + + template + _LIBCPP_INLINE_VISIBILITY + static typename enable_if<__is_same_uncvref<_Up, __node_value_type>::value, + __container_value_type const&>::type + __get_value(_Up& __t) { + return __t.__cc; + } + + template + _LIBCPP_INLINE_VISIBILITY + static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value, + __container_value_type const&>::type + __get_value(_Up& __t) { + return __t; + } + + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n.__cc); + } +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + static __nc_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v.__nc); + } +#endif + +}; + +template , + bool = _KVTypes::__is_map> +struct __hash_map_pointer_types {}; + +template +struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> { + typedef typename _KVTypes::__map_value_type _Mv; + typedef typename __rebind_pointer<_AllocPtr, _Mv>::type + __map_value_type_pointer; + typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type + __const_map_value_type_pointer; +}; + +template ::element_type> +struct __hash_node_types; + +template +struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> > + : public __hash_key_value_types<_Tp>, __hash_map_pointer_types<_Tp, _VoidPtr> + +{ + typedef __hash_key_value_types<_Tp> __base; + +public: + typedef ptrdiff_t difference_type; + typedef size_t size_type; + + typedef typename __rebind_pointer<_NodePtr, void>::type __void_pointer; + + typedef typename pointer_traits<_NodePtr>::element_type __node_type; + typedef _NodePtr __node_pointer; + + typedef __hash_node_base<__node_pointer> __node_base_type; + typedef typename __rebind_pointer<_NodePtr, __node_base_type>::type + __node_base_pointer; + + typedef _Tp __node_value_type; + typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type + __node_value_type_pointer; + typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type + __const_node_value_type_pointer; +private: + static_assert(!is_const<__node_type>::value, + "_NodePtr should never be a pointer to const"); + static_assert((is_same::element_type, void>::value), + "_VoidPtr does not point to unqualified void type"); + static_assert((is_same::type, + _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr."); +}; + + + +template +struct __hash_node_types_from_iterator; +template +struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; +template +struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {}; + + +template +struct __make_hash_node_types { + typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp; + typedef typename __rebind_pointer<_VoidPtr, _NodeTp>::type _NodePtr; + typedef __hash_node_types<_NodePtr> type; +}; + +template +class _LIBCPP_TYPE_VIS_ONLY __hash_iterator +{ + typedef __hash_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; + + __node_pointer __node_; + +public: + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef value_type& reference; + typedef typename _NodeTypes::__node_value_type_pointer pointer; + + _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT +#if _LIBCPP_STD_VER > 11 + : __node_(nullptr) +#endif + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_i(this); +#endif + } + +#if _LIBCPP_DEBUG_LEVEL >= 2 + + _LIBCPP_INLINE_VISIBILITY + __hash_iterator(const __hash_iterator& __i) + : __node_(__i.__node_) + { + __get_db()->__iterator_copy(this, &__i); + } + + _LIBCPP_INLINE_VISIBILITY + ~__hash_iterator() + { + __get_db()->__erase_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_iterator& operator=(const __hash_iterator& __i) + { + if (this != &__i) + { + __get_db()->__iterator_copy(this, &__i); + __node_ = __i.__node_; + } + return *this; + } + +#endif // _LIBCPP_DEBUG_LEVEL >= 2 + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container iterator"); +#endif + return __node_->__value_; + } + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container iterator"); +#endif + return pointer_traits::pointer_to(__node_->__value_); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_iterator& operator++() + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment non-incrementable unordered container iterator"); +#endif + __node_ = __node_->__next_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __hash_iterator operator++(int) + { + __hash_iterator __t(*this); + ++(*this); + return __t; + } + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __hash_iterator& __x, const __hash_iterator& __y) + { + return __x.__node_ == __y.__node_; + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y) + {return !(__x == __y);} + +private: +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_INLINE_VISIBILITY + __hash_iterator(__node_pointer __node, const void* __c) _NOEXCEPT + : __node_(__node) + { + __get_db()->__insert_ic(this, __c); + } +#else + _LIBCPP_INLINE_VISIBILITY + __hash_iterator(__node_pointer __node) _NOEXCEPT + : __node_(__node) + {} +#endif + + template friend class __hash_table; + template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; + template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; + template friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; + template friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; +}; + +template +class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator +{ + static_assert(!is_const::element_type>::value, ""); + typedef __hash_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; + + __node_pointer __node_; + +public: + typedef __hash_iterator<_NodePtr> __non_const_iterator; + + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef const value_type& reference; + typedef typename _NodeTypes::__const_node_value_type_pointer pointer; + + + _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT +#if _LIBCPP_STD_VER > 11 + : __node_(nullptr) +#endif + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_i(this); +#endif + } + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT + : __node_(__x.__node_) + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__iterator_copy(this, &__x); +#endif + } + +#if _LIBCPP_DEBUG_LEVEL >= 2 + + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator(const __hash_const_iterator& __i) + : __node_(__i.__node_) + { + __get_db()->__iterator_copy(this, &__i); + } + + _LIBCPP_INLINE_VISIBILITY + ~__hash_const_iterator() + { + __get_db()->__erase_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator& operator=(const __hash_const_iterator& __i) + { + if (this != &__i) + { + __get_db()->__iterator_copy(this, &__i); + __node_ = __i.__node_; + } + return *this; + } + +#endif // _LIBCPP_DEBUG_LEVEL >= 2 + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container const_iterator"); +#endif + return __node_->__value_; + } + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container const_iterator"); +#endif + return pointer_traits::pointer_to(__node_->__value_); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator& operator++() + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment non-incrementable unordered container const_iterator"); +#endif + __node_ = __node_->__next_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator operator++(int) + { + __hash_const_iterator __t(*this); + ++(*this); + return __t; + } + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y) + { + return __x.__node_ == __y.__node_; + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y) + {return !(__x == __y);} + +private: +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator(__node_pointer __node, const void* __c) _NOEXCEPT + : __node_(__node) + { + __get_db()->__insert_ic(this, __c); + } +#else + _LIBCPP_INLINE_VISIBILITY + __hash_const_iterator(__node_pointer __node) _NOEXCEPT + : __node_(__node) + {} +#endif + + template friend class __hash_table; + template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; + template friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; + template friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; +}; + +template +class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator +{ + typedef __hash_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; + + __node_pointer __node_; + size_t __bucket_; + size_t __bucket_count_; + +public: + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef value_type& reference; + typedef typename _NodeTypes::__node_value_type_pointer pointer; + + _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_i(this); +#endif + } + +#if _LIBCPP_DEBUG_LEVEL >= 2 + + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator(const __hash_local_iterator& __i) + : __node_(__i.__node_), + __bucket_(__i.__bucket_), + __bucket_count_(__i.__bucket_count_) + { + __get_db()->__iterator_copy(this, &__i); + } + + _LIBCPP_INLINE_VISIBILITY + ~__hash_local_iterator() + { + __get_db()->__erase_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator& operator=(const __hash_local_iterator& __i) + { + if (this != &__i) + { + __get_db()->__iterator_copy(this, &__i); + __node_ = __i.__node_; + __bucket_ = __i.__bucket_; + __bucket_count_ = __i.__bucket_count_; + } + return *this; + } + +#endif // _LIBCPP_DEBUG_LEVEL >= 2 + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container local_iterator"); +#endif + return __node_->__value_; + } + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container local_iterator"); +#endif + return pointer_traits::pointer_to(__node_->__value_); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator& operator++() + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment non-incrementable unordered container local_iterator"); +#endif + __node_ = __node_->__next_; + if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_) + __node_ = nullptr; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator operator++(int) + { + __hash_local_iterator __t(*this); + ++(*this); + return __t; + } + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y) + { + return __x.__node_ == __y.__node_; + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y) + {return !(__x == __y);} + +private: +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator(__node_pointer __node, size_t __bucket, + size_t __bucket_count, const void* __c) _NOEXCEPT + : __node_(__node), + __bucket_(__bucket), + __bucket_count_(__bucket_count) + { + __get_db()->__insert_ic(this, __c); + if (__node_ != nullptr) + __node_ = __node_->__next_; + } +#else + _LIBCPP_INLINE_VISIBILITY + __hash_local_iterator(__node_pointer __node, size_t __bucket, + size_t __bucket_count) _NOEXCEPT + : __node_(__node), + __bucket_(__bucket), + __bucket_count_(__bucket_count) + { + if (__node_ != nullptr) + __node_ = __node_->__next_; + } +#endif + template friend class __hash_table; + template friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; + template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; +}; + +template +class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator +{ + typedef __hash_node_types<_ConstNodePtr> _NodeTypes; + typedef _ConstNodePtr __node_pointer; + + __node_pointer __node_; + size_t __bucket_; + size_t __bucket_count_; + + typedef pointer_traits<__node_pointer> __pointer_traits; + typedef typename __pointer_traits::element_type __node; + typedef typename remove_const<__node>::type __non_const_node; + typedef typename __rebind_pointer<__node_pointer, __non_const_node>::type + __non_const_node_pointer; +public: + typedef __hash_local_iterator<__non_const_node_pointer> + __non_const_iterator; + + typedef forward_iterator_tag iterator_category; + typedef typename _NodeTypes::__node_value_type value_type; + typedef typename _NodeTypes::difference_type difference_type; + typedef const value_type& reference; + typedef typename _NodeTypes::__const_node_value_type_pointer pointer; + + + _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_i(this); +#endif + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT + : __node_(__x.__node_), + __bucket_(__x.__bucket_), + __bucket_count_(__x.__bucket_count_) + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__iterator_copy(this, &__x); +#endif + } + +#if _LIBCPP_DEBUG_LEVEL >= 2 + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator(const __hash_const_local_iterator& __i) + : __node_(__i.__node_), + __bucket_(__i.__bucket_), + __bucket_count_(__i.__bucket_count_) + { + __get_db()->__iterator_copy(this, &__i); + } + + _LIBCPP_INLINE_VISIBILITY + ~__hash_const_local_iterator() + { + __get_db()->__erase_i(this); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i) + { + if (this != &__i) + { + __get_db()->__iterator_copy(this, &__i); + __node_ = __i.__node_; + __bucket_ = __i.__bucket_; + __bucket_count_ = __i.__bucket_count_; + } + return *this; + } + +#endif // _LIBCPP_DEBUG_LEVEL >= 2 + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); +#endif + return __node_->__value_; + } + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); +#endif + return pointer_traits::pointer_to(__node_->__value_); + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator& operator++() + { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), + "Attempted to increment non-incrementable unordered container const_local_iterator"); +#endif + __node_ = __node_->__next_; + if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_) + __node_ = nullptr; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator operator++(int) + { + __hash_const_local_iterator __t(*this); + ++(*this); + return __t; + } + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) + { + return __x.__node_ == __y.__node_; + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) + {return !(__x == __y);} + +private: +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator(__node_pointer __node, size_t __bucket, + size_t __bucket_count, const void* __c) _NOEXCEPT + : __node_(__node), + __bucket_(__bucket), + __bucket_count_(__bucket_count) + { + __get_db()->__insert_ic(this, __c); + if (__node_ != nullptr) + __node_ = __node_->__next_; + } +#else + _LIBCPP_INLINE_VISIBILITY + __hash_const_local_iterator(__node_pointer __node, size_t __bucket, + size_t __bucket_count) _NOEXCEPT + : __node_(__node), + __bucket_(__bucket), + __bucket_count_(__bucket_count) + { + if (__node_ != nullptr) + __node_ = __node_->__next_; + } +#endif + template friend class __hash_table; + template friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; +}; + +template +class __bucket_list_deallocator +{ + typedef _Alloc allocator_type; + typedef allocator_traits __alloc_traits; + typedef typename __alloc_traits::size_type size_type; + + __compressed_pair __data_; +public: + typedef typename __alloc_traits::pointer pointer; + + _LIBCPP_INLINE_VISIBILITY + __bucket_list_deallocator() + _NOEXCEPT_(is_nothrow_default_constructible::value) + : __data_(0) {} + + _LIBCPP_INLINE_VISIBILITY + __bucket_list_deallocator(const allocator_type& __a, size_type __size) + _NOEXCEPT_(is_nothrow_copy_constructible::value) + : __data_(__size, __a) {} + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + + _LIBCPP_INLINE_VISIBILITY + __bucket_list_deallocator(__bucket_list_deallocator&& __x) + _NOEXCEPT_(is_nothrow_move_constructible::value) + : __data_(_VSTD::move(__x.__data_)) + { + __x.size() = 0; + } + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + + _LIBCPP_INLINE_VISIBILITY + size_type& size() _NOEXCEPT {return __data_.first();} + _LIBCPP_INLINE_VISIBILITY + size_type size() const _NOEXCEPT {return __data_.first();} + + _LIBCPP_INLINE_VISIBILITY + allocator_type& __alloc() _NOEXCEPT {return __data_.second();} + _LIBCPP_INLINE_VISIBILITY + const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();} + + _LIBCPP_INLINE_VISIBILITY + void operator()(pointer __p) _NOEXCEPT + { + __alloc_traits::deallocate(__alloc(), __p, size()); + } +}; + +template class __hash_map_node_destructor; + +template +class __hash_node_destructor +{ + typedef _Alloc allocator_type; + typedef allocator_traits __alloc_traits; + +public: + typedef typename __alloc_traits::pointer pointer; +private: + typedef __hash_node_types _NodeTypes; + + allocator_type& __na_; + + __hash_node_destructor& operator=(const __hash_node_destructor&); + +public: + bool __value_constructed; + + _LIBCPP_INLINE_VISIBILITY + explicit __hash_node_destructor(allocator_type& __na, + bool __constructed = false) _NOEXCEPT + : __na_(__na), + __value_constructed(__constructed) + {} + + _LIBCPP_INLINE_VISIBILITY + void operator()(pointer __p) _NOEXCEPT + { + if (__value_constructed) + __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_)); + if (__p) + __alloc_traits::deallocate(__na_, __p, 1); + } + + template friend class __hash_map_node_destructor; +}; + +template +class __hash_table +{ +public: + typedef _Tp value_type; + typedef _Hash hasher; + typedef _Equal key_equal; + typedef _Alloc allocator_type; + +private: + typedef allocator_traits __alloc_traits; + typedef typename + __make_hash_node_types::type + _NodeTypes; +public: + + typedef typename _NodeTypes::__node_value_type __node_value_type; + typedef typename _NodeTypes::__container_value_type __container_value_type; + typedef typename _NodeTypes::key_type key_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef typename __alloc_traits::pointer pointer; + typedef typename __alloc_traits::const_pointer const_pointer; +#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE + typedef typename __alloc_traits::size_type size_type; +#else + typedef typename _NodeTypes::size_type size_type; +#endif + typedef typename _NodeTypes::difference_type difference_type; +public: + // Create __node + + typedef typename _NodeTypes::__node_type __node; + typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator; + typedef allocator_traits<__node_allocator> __node_traits; + typedef typename _NodeTypes::__void_pointer __void_pointer; + typedef typename _NodeTypes::__node_pointer __node_pointer; + typedef typename _NodeTypes::__node_pointer __node_const_pointer; + typedef typename _NodeTypes::__node_base_type __first_node; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; + +private: + // check for sane allocator pointer rebinding semantics. Rebinding the + // allocator for a new pointer type should be exactly the same as rebinding + // the pointer using 'pointer_traits'. + static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); + typedef typename __rebind_alloc_helper<__node_traits, __first_node>::type + __node_base_allocator; + typedef allocator_traits<__node_base_allocator> __node_base_traits; + static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); + +private: + + typedef typename __rebind_alloc_helper<__node_traits, __node_pointer>::type __pointer_allocator; + typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter; + typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list; + typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits; + typedef typename __bucket_list_deleter::pointer __node_pointer_pointer; + + // --- Member data begin --- + __bucket_list __bucket_list_; + __compressed_pair<__first_node, __node_allocator> __p1_; + __compressed_pair __p2_; + __compressed_pair __p3_; + // --- Member data end --- + + _LIBCPP_INLINE_VISIBILITY + size_type& size() _NOEXCEPT {return __p2_.first();} +public: + _LIBCPP_INLINE_VISIBILITY + size_type size() const _NOEXCEPT {return __p2_.first();} + + _LIBCPP_INLINE_VISIBILITY + hasher& hash_function() _NOEXCEPT {return __p2_.second();} + _LIBCPP_INLINE_VISIBILITY + const hasher& hash_function() const _NOEXCEPT {return __p2_.second();} + + _LIBCPP_INLINE_VISIBILITY + float& max_load_factor() _NOEXCEPT {return __p3_.first();} + _LIBCPP_INLINE_VISIBILITY + float max_load_factor() const _NOEXCEPT {return __p3_.first();} + + _LIBCPP_INLINE_VISIBILITY + key_equal& key_eq() _NOEXCEPT {return __p3_.second();} + _LIBCPP_INLINE_VISIBILITY + const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();} + + _LIBCPP_INLINE_VISIBILITY + __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();} + _LIBCPP_INLINE_VISIBILITY + const __node_allocator& __node_alloc() const _NOEXCEPT + {return __p1_.second();} + +public: + typedef __hash_iterator<__node_pointer> iterator; + typedef __hash_const_iterator<__node_pointer> const_iterator; + typedef __hash_local_iterator<__node_pointer> local_iterator; + typedef __hash_const_local_iterator<__node_pointer> const_local_iterator; + + _LIBCPP_INLINE_VISIBILITY + __hash_table() + _NOEXCEPT_( + is_nothrow_default_constructible<__bucket_list>::value && + is_nothrow_default_constructible<__first_node>::value && + is_nothrow_default_constructible<__node_allocator>::value && + is_nothrow_default_constructible::value && + is_nothrow_default_constructible::value); + _LIBCPP_INLINE_VISIBILITY + __hash_table(const hasher& __hf, const key_equal& __eql); + __hash_table(const hasher& __hf, const key_equal& __eql, + const allocator_type& __a); + explicit __hash_table(const allocator_type& __a); + __hash_table(const __hash_table& __u); + __hash_table(const __hash_table& __u, const allocator_type& __a); +#ifndef _LIBCPP_CXX03_LANG + __hash_table(__hash_table&& __u) + _NOEXCEPT_( + is_nothrow_move_constructible<__bucket_list>::value && + is_nothrow_move_constructible<__first_node>::value && + is_nothrow_move_constructible<__node_allocator>::value && + is_nothrow_move_constructible::value && + is_nothrow_move_constructible::value); + __hash_table(__hash_table&& __u, const allocator_type& __a); +#endif // _LIBCPP_CXX03_LANG + ~__hash_table(); + + __hash_table& operator=(const __hash_table& __u); +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + __hash_table& operator=(__hash_table&& __u) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<__node_allocator>::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable::value); +#endif + template + void __assign_unique(_InputIterator __first, _InputIterator __last); + template + void __assign_multi(_InputIterator __first, _InputIterator __last); + + _LIBCPP_INLINE_VISIBILITY + size_type max_size() const _NOEXCEPT + { + return allocator_traits<__pointer_allocator>::max_size( + __bucket_list_.get_deleter().__alloc()); + } + + pair __node_insert_unique(__node_pointer __nd); + iterator __node_insert_multi(__node_pointer __nd); + iterator __node_insert_multi(const_iterator __p, + __node_pointer __nd); + +#ifndef _LIBCPP_CXX03_LANG + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique_key_args(_Key const& __k, _Args&&... __args); + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique_impl(_Args&&... __args); + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Pp&& __x) { + return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x), + __can_extract_key<_Pp, key_type>()); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if< + __can_extract_map_key<_First, key_type, __container_value_type>::value, + pair + >::type __emplace_unique(_First&& __f, _Second&& __s) { + return __emplace_unique_key_args(__f, _VSTD::forward<_First>(__f), + _VSTD::forward<_Second>(__s)); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Args&&... __args) { + return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { + return __emplace_unique_impl(_VSTD::forward<_Pp>(__x)); + } + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { + return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x)); + } + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { + return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_multi(_Args&&... __args); + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); + + + _LIBCPP_INLINE_VISIBILITY + pair + __insert_unique(__container_value_type&& __x) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__x), _VSTD::move(__x)); + } + + template ::value + >::type> + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(_Pp&& __x) { + return __emplace_unique(_VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(_Pp&& __x) { + return __emplace_multi(_VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, _Pp&& __x) { + return __emplace_hint_multi(__p, _VSTD::forward<_Pp>(__x)); + } + +#else // !defined(_LIBCPP_CXX03_LANG) + template + pair __emplace_unique_key_args(_Key const&, _Args& __args); + + iterator __insert_multi(const __container_value_type& __x); + iterator __insert_multi(const_iterator __p, const __container_value_type& __x); +#endif + + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(const __container_value_type& __x) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); + } + + void clear() _NOEXCEPT; + void rehash(size_type __n); + _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) + {rehash(static_cast(ceil(__n / max_load_factor())));} + + _LIBCPP_INLINE_VISIBILITY + size_type bucket_count() const _NOEXCEPT + { + return __bucket_list_.get_deleter().size(); + } + + _LIBCPP_INLINE_VISIBILITY + iterator begin() _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + iterator end() _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + const_iterator begin() const _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + const_iterator end() const _NOEXCEPT; + + template + _LIBCPP_INLINE_VISIBILITY + size_type bucket(const _Key& __k) const + { + _LIBCPP_ASSERT(bucket_count() > 0, + "unordered container::bucket(key) called when bucket_count() == 0"); + return __constrain_hash(hash_function()(__k), bucket_count()); + } + + template + iterator find(const _Key& __x); + template + const_iterator find(const _Key& __x) const; + + typedef __hash_node_destructor<__node_allocator> _Dp; + typedef unique_ptr<__node, _Dp> __node_holder; + + iterator erase(const_iterator __p); + iterator erase(const_iterator __first, const_iterator __last); + template + size_type __erase_unique(const _Key& __k); + template + size_type __erase_multi(const _Key& __k); + __node_holder remove(const_iterator __p) _NOEXCEPT; + + template + _LIBCPP_INLINE_VISIBILITY + size_type __count_unique(const _Key& __k) const; + template + size_type __count_multi(const _Key& __k) const; + + template + pair + __equal_range_unique(const _Key& __k); + template + pair + __equal_range_unique(const _Key& __k) const; + + template + pair + __equal_range_multi(const _Key& __k); + template + pair + __equal_range_multi(const _Key& __k) const; + +// For some reason VS compiler does not support having intermixed ifdefs in _NOEXCEPT_ +// Initially, we had to rewrite the declaration to silence the compilation errors. +// However, this issue has been addressed in rev. 242623 + void swap(__hash_table& __u) +#if _LIBCPP_STD_VER <= 11 + _NOEXCEPT_( + __is_nothrow_swappable::value && __is_nothrow_swappable::value + && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value + || __is_nothrow_swappable<__pointer_allocator>::value) + && (!__node_traits::propagate_on_container_swap::value + || __is_nothrow_swappable<__node_allocator>::value) + ); +#else + _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value); +#endif + + _LIBCPP_INLINE_VISIBILITY + size_type max_bucket_count() const _NOEXCEPT + {return __pointer_alloc_traits::max_size(__bucket_list_.get_deleter().__alloc());} + size_type bucket_size(size_type __n) const; + _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT + { + size_type __bc = bucket_count(); + return __bc != 0 ? (float)size() / __bc : 0.f; + } + _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT + { + _LIBCPP_ASSERT(__mlf > 0, + "unordered container::max_load_factor(lf) called with lf <= 0"); + max_load_factor() = _VSTD::max(__mlf, load_factor()); + } + + _LIBCPP_INLINE_VISIBILITY + local_iterator + begin(size_type __n) + { + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::begin(n) called with n >= bucket_count()"); +#if _LIBCPP_DEBUG_LEVEL >= 2 + return local_iterator(__bucket_list_[__n], __n, bucket_count(), this); +#else + return local_iterator(__bucket_list_[__n], __n, bucket_count()); +#endif + } + + _LIBCPP_INLINE_VISIBILITY + local_iterator + end(size_type __n) + { + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::end(n) called with n >= bucket_count()"); +#if _LIBCPP_DEBUG_LEVEL >= 2 + return local_iterator(nullptr, __n, bucket_count(), this); +#else + return local_iterator(nullptr, __n, bucket_count()); +#endif + } + + _LIBCPP_INLINE_VISIBILITY + const_local_iterator + cbegin(size_type __n) const + { + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::cbegin(n) called with n >= bucket_count()"); +#if _LIBCPP_DEBUG_LEVEL >= 2 + return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this); +#else + return const_local_iterator(__bucket_list_[__n], __n, bucket_count()); +#endif + } + + _LIBCPP_INLINE_VISIBILITY + const_local_iterator + cend(size_type __n) const + { + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::cend(n) called with n >= bucket_count()"); +#if _LIBCPP_DEBUG_LEVEL >= 2 + return const_local_iterator(nullptr, __n, bucket_count(), this); +#else + return const_local_iterator(nullptr, __n, bucket_count()); +#endif + } + +#if _LIBCPP_DEBUG_LEVEL >= 2 + + bool __dereferenceable(const const_iterator* __i) const; + bool __decrementable(const const_iterator* __i) const; + bool __addable(const const_iterator* __i, ptrdiff_t __n) const; + bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; + +#endif // _LIBCPP_DEBUG_LEVEL >= 2 + +private: + void __rehash(size_type __n); + +#ifndef _LIBCPP_CXX03_LANG + template + __node_holder __construct_node(_Args&& ...__args); + + template + __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest); +#else // _LIBCPP_CXX03_LANG + __node_holder __construct_node(const __container_value_type& __v); + __node_holder __construct_node_hash(size_t __hash, const __container_value_type& __v); +#endif + + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const __hash_table& __u) + {__copy_assign_alloc(__u, integral_constant());} + void __copy_assign_alloc(const __hash_table& __u, true_type); + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const __hash_table&, false_type) {} + +#ifndef _LIBCPP_CXX03_LANG + void __move_assign(__hash_table& __u, false_type); + void __move_assign(__hash_table& __u, true_type) + _NOEXCEPT_( + is_nothrow_move_assignable<__node_allocator>::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable::value); + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__hash_table& __u) + _NOEXCEPT_( + !__node_traits::propagate_on_container_move_assignment::value || + (is_nothrow_move_assignable<__pointer_allocator>::value && + is_nothrow_move_assignable<__node_allocator>::value)) + {__move_assign_alloc(__u, integral_constant());} + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__hash_table& __u, true_type) + _NOEXCEPT_( + is_nothrow_move_assignable<__pointer_allocator>::value && + is_nothrow_move_assignable<__node_allocator>::value) + { + __bucket_list_.get_deleter().__alloc() = + _VSTD::move(__u.__bucket_list_.get_deleter().__alloc()); + __node_alloc() = _VSTD::move(__u.__node_alloc()); + } + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {} +#endif // _LIBCPP_CXX03_LANG + + void __deallocate(__node_pointer __np) _NOEXCEPT; + __node_pointer __detach() _NOEXCEPT; + + template friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; + template friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; +}; + +template +inline +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table() + _NOEXCEPT_( + is_nothrow_default_constructible<__bucket_list>::value && + is_nothrow_default_constructible<__first_node>::value && + is_nothrow_default_constructible<__node_allocator>::value && + is_nothrow_default_constructible::value && + is_nothrow_default_constructible::value) + : __p2_(0), + __p3_(1.0f) +{ +} + +template +inline +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, + const key_equal& __eql) + : __bucket_list_(nullptr, __bucket_list_deleter()), + __p1_(), + __p2_(0, __hf), + __p3_(1.0f, __eql) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, + const key_equal& __eql, + const allocator_type& __a) + : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), + __p1_(__node_allocator(__a)), + __p2_(0, __hf), + __p3_(1.0f, __eql) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a) + : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), + __p1_(__node_allocator(__a)), + __p2_(0), + __p3_(1.0f) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u) + : __bucket_list_(nullptr, + __bucket_list_deleter(allocator_traits<__pointer_allocator>:: + select_on_container_copy_construction( + __u.__bucket_list_.get_deleter().__alloc()), 0)), + __p1_(allocator_traits<__node_allocator>:: + select_on_container_copy_construction(__u.__node_alloc())), + __p2_(0, __u.hash_function()), + __p3_(__u.__p3_) +{ +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u, + const allocator_type& __a) + : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), + __p1_(__node_allocator(__a)), + __p2_(0, __u.hash_function()), + __p3_(__u.__p3_) +{ +} + +#ifndef _LIBCPP_CXX03_LANG + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) + _NOEXCEPT_( + is_nothrow_move_constructible<__bucket_list>::value && + is_nothrow_move_constructible<__first_node>::value && + is_nothrow_move_constructible<__node_allocator>::value && + is_nothrow_move_constructible::value && + is_nothrow_move_constructible::value) + : __bucket_list_(_VSTD::move(__u.__bucket_list_)), + __p1_(_VSTD::move(__u.__p1_)), + __p2_(_VSTD::move(__u.__p2_)), + __p3_(_VSTD::move(__u.__p3_)) +{ + if (size() > 0) + { + __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = + static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); + __u.__p1_.first().__next_ = nullptr; + __u.size() = 0; + } +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, + const allocator_type& __a) + : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), + __p1_(__node_allocator(__a)), + __p2_(0, _VSTD::move(__u.hash_function())), + __p3_(_VSTD::move(__u.__p3_)) +{ + if (__a == allocator_type(__u.__node_alloc())) + { + __bucket_list_.reset(__u.__bucket_list_.release()); + __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size(); + __u.__bucket_list_.get_deleter().size() = 0; + if (__u.size() > 0) + { + __p1_.first().__next_ = __u.__p1_.first().__next_; + __u.__p1_.first().__next_ = nullptr; + __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = + static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); + size() = __u.size(); + __u.size() = 0; + } + } +} + +#endif // _LIBCPP_CXX03_LANG + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() +{ + static_assert((is_copy_constructible::value), + "Predicate must be copy-constructible."); + static_assert((is_copy_constructible::value), + "Hasher must be copy-constructible."); + __deallocate(__p1_.first().__next_); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__erase_c(this); +#endif +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc( + const __hash_table& __u, true_type) +{ + if (__node_alloc() != __u.__node_alloc()) + { + clear(); + __bucket_list_.reset(); + __bucket_list_.get_deleter().size() = 0; + } + __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc(); + __node_alloc() = __u.__node_alloc(); +} + +template +__hash_table<_Tp, _Hash, _Equal, _Alloc>& +__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u) +{ + if (this != &__u) + { + __copy_assign_alloc(__u); + hash_function() = __u.hash_function(); + key_eq() = __u.key_eq(); + max_load_factor() = __u.max_load_factor(); + __assign_multi(__u.begin(), __u.end()); + } + return *this; +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np) + _NOEXCEPT +{ + __node_allocator& __na = __node_alloc(); + while (__np != nullptr) + { + __node_pointer __next = __np->__next_; +#if _LIBCPP_DEBUG_LEVEL >= 2 + __c_node* __c = __get_db()->__find_c_and_lock(this); + for (__i_node** __p = __c->end_; __p != __c->beg_; ) + { + --__p; + iterator* __i = static_cast((*__p)->__i_); + if (__i->__node_ == __np) + { + (*__p)->__c_ = nullptr; + if (--__c->end_ != __p) + memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); + } + } + __get_db()->unlock(); +#endif + __node_traits::destroy(__na, _NodeTypes::__get_ptr(__np->__value_)); + __node_traits::deallocate(__na, __np, 1); + __np = __next; + } +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT +{ + size_type __bc = bucket_count(); + for (size_type __i = 0; __i < __bc; ++__i) + __bucket_list_[__i] = nullptr; + size() = 0; + __node_pointer __cache = __p1_.first().__next_; + __p1_.first().__next_ = nullptr; + return __cache; +} + +#ifndef _LIBCPP_CXX03_LANG + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( + __hash_table& __u, true_type) + _NOEXCEPT_( + is_nothrow_move_assignable<__node_allocator>::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable::value) +{ + clear(); + __bucket_list_.reset(__u.__bucket_list_.release()); + __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size(); + __u.__bucket_list_.get_deleter().size() = 0; + __move_assign_alloc(__u); + size() = __u.size(); + hash_function() = _VSTD::move(__u.hash_function()); + max_load_factor() = __u.max_load_factor(); + key_eq() = _VSTD::move(__u.key_eq()); + __p1_.first().__next_ = __u.__p1_.first().__next_; + if (size() > 0) + { + __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = + static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); + __u.__p1_.first().__next_ = nullptr; + __u.size() = 0; + } +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->swap(this, &__u); +#endif +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( + __hash_table& __u, false_type) +{ + if (__node_alloc() == __u.__node_alloc()) + __move_assign(__u, true_type()); + else + { + hash_function() = _VSTD::move(__u.hash_function()); + key_eq() = _VSTD::move(__u.key_eq()); + max_load_factor() = __u.max_load_factor(); + if (bucket_count() != 0) + { + __node_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + const_iterator __i = __u.begin(); + while (__cache != nullptr && __u.size() != 0) + { + __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_); + __node_pointer __next = __cache->__next_; + __node_insert_multi(__cache); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __deallocate(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + __deallocate(__cache); + } + const_iterator __i = __u.begin(); + while (__u.size() != 0) + { + __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__value_)); + __node_insert_multi(__h.get()); + __h.release(); + } + } +} + +template +inline +__hash_table<_Tp, _Hash, _Equal, _Alloc>& +__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable<__node_allocator>::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable::value) +{ + __move_assign(__u, integral_constant()); + return *this; +} + +#endif // _LIBCPP_CXX03_LANG + +template +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, + _InputIterator __last) +{ + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value), + "__assign_unique may only be called with the containers value type"); + + if (bucket_count() != 0) + { + __node_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + for (; __cache != nullptr && __first != __last; ++__first) + { + __cache->__value_ = *__first; + __node_pointer __next = __cache->__next_; + __node_insert_unique(__cache); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __deallocate(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + __deallocate(__cache); + } + for (; __first != __last; ++__first) + __insert_unique(*__first); +} + +template +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, + _InputIterator __last) +{ + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value || + is_same<_ItValueType, __node_value_type>::value), + "__assign_multi may only be called with the containers value type" + " or the nodes value type"); + if (bucket_count() != 0) + { + __node_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + for (; __cache != nullptr && __first != __last; ++__first) + { + __cache->__value_ = *__first; + __node_pointer __next = __cache->__next_; + __node_insert_multi(__cache); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __deallocate(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + __deallocate(__cache); + } + for (; __first != __last; ++__first) + __insert_multi(_NodeTypes::__get_value(*__first)); +} + +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + return iterator(__p1_.first().__next_, this); +#else + return iterator(__p1_.first().__next_); +#endif +} + +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + return iterator(nullptr, this); +#else + return iterator(nullptr); +#endif +} + +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + return const_iterator(__p1_.first().__next_, this); +#else + return const_iterator(__p1_.first().__next_); +#endif +} + +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + return const_iterator(nullptr, this); +#else + return const_iterator(nullptr); +#endif +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT +{ + if (size() > 0) + { + __deallocate(__p1_.first().__next_); + __p1_.first().__next_ = nullptr; + size_type __bc = bucket_count(); + for (size_type __i = 0; __i < __bc; ++__i) + __bucket_list_[__i] = nullptr; + size() = 0; + } +} + +template +pair::iterator, bool> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd) +{ + __nd->__hash_ = hash_function()(__nd->__value_); + size_type __bc = bucket_count(); + bool __inserted = false; + __node_pointer __ndptr; + size_t __chash; + if (__bc != 0) + { + __chash = __constrain_hash(__nd->__hash_, __bc); + __ndptr = __bucket_list_[__chash]; + if (__ndptr != nullptr) + { + for (__ndptr = __ndptr->__next_; __ndptr != nullptr && + __constrain_hash(__ndptr->__hash_, __bc) == __chash; + __ndptr = __ndptr->__next_) + { + if (key_eq()(__ndptr->__value_, __nd->__value_)) + goto __done; + } + } + } + { + if (size()+1 > __bc * max_load_factor() || __bc == 0) + { + rehash(_VSTD::max(2 * __bc + !__is_hash_power2(__bc), + size_type(ceil(float(size() + 1) / max_load_factor())))); + __bc = bucket_count(); + __chash = __constrain_hash(__nd->__hash_, __bc); + } + // insert_after __bucket_list_[__chash], or __first_node if bucket is null + __node_pointer __pn = __bucket_list_[__chash]; + if (__pn == nullptr) + { + __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); + __nd->__next_ = __pn->__next_; + __pn->__next_ = __nd; + // fix up __bucket_list_ + __bucket_list_[__chash] = __pn; + if (__nd->__next_ != nullptr) + __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd; + } + else + { + __nd->__next_ = __pn->__next_; + __pn->__next_ = __nd; + } + __ndptr = __nd; + // increment size + ++size(); + __inserted = true; + } +__done: +#if _LIBCPP_DEBUG_LEVEL >= 2 + return pair(iterator(__ndptr, this), __inserted); +#else + return pair(iterator(__ndptr), __inserted); +#endif +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp) +{ + __cp->__hash_ = hash_function()(__cp->__value_); + size_type __bc = bucket_count(); + if (size()+1 > __bc * max_load_factor() || __bc == 0) + { + rehash(_VSTD::max(2 * __bc + !__is_hash_power2(__bc), + size_type(ceil(float(size() + 1) / max_load_factor())))); + __bc = bucket_count(); + } + size_t __chash = __constrain_hash(__cp->__hash_, __bc); + __node_pointer __pn = __bucket_list_[__chash]; + if (__pn == nullptr) + { + __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); + __cp->__next_ = __pn->__next_; + __pn->__next_ = __cp; + // fix up __bucket_list_ + __bucket_list_[__chash] = __pn; + if (__cp->__next_ != nullptr) + __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp; + } + else + { + for (bool __found = false; __pn->__next_ != nullptr && + __constrain_hash(__pn->__next_->__hash_, __bc) == __chash; + __pn = __pn->__next_) + { + // __found key_eq() action + // false false loop + // true true loop + // false true set __found to true + // true false break + if (__found != (__pn->__next_->__hash_ == __cp->__hash_ && + key_eq()(__pn->__next_->__value_, __cp->__value_))) + { + if (!__found) + __found = true; + else + break; + } + } + __cp->__next_ = __pn->__next_; + __pn->__next_ = __cp; + if (__cp->__next_ != nullptr) + { + size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc); + if (__nhash != __chash) + __bucket_list_[__nhash] = __cp; + } + } + ++size(); +#if _LIBCPP_DEBUG_LEVEL >= 2 + return iterator(__cp, this); +#else + return iterator(__cp); +#endif +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( + const_iterator __p, __node_pointer __cp) +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" + " referring to this unordered container"); +#endif + if (__p != end() && key_eq()(*__p, __cp->__value_)) + { + __node_pointer __np = __p.__node_; + __cp->__hash_ = __np->__hash_; + size_type __bc = bucket_count(); + if (size()+1 > __bc * max_load_factor() || __bc == 0) + { + rehash(_VSTD::max(2 * __bc + !__is_hash_power2(__bc), + size_type(ceil(float(size() + 1) / max_load_factor())))); + __bc = bucket_count(); + } + size_t __chash = __constrain_hash(__cp->__hash_, __bc); + __node_pointer __pp = __bucket_list_[__chash]; + while (__pp->__next_ != __np) + __pp = __pp->__next_; + __cp->__next_ = __np; + __pp->__next_ = __cp; + ++size(); +#if _LIBCPP_DEBUG_LEVEL >= 2 + return iterator(__cp, this); +#else + return iterator(__cp); +#endif + } + return __node_insert_multi(__cp); +} + + + +#ifndef _LIBCPP_CXX03_LANG +template +template +_LIBCPP_INLINE_VISIBILITY +pair::iterator, bool> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) +#else +template +template +_LIBCPP_INLINE_VISIBILITY +pair::iterator, bool> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args& __args) +#endif +{ + + size_t __hash = hash_function()(__k); + size_type __bc = bucket_count(); + bool __inserted = false; + __node_pointer __nd; + size_t __chash; + if (__bc != 0) + { + __chash = __constrain_hash(__hash, __bc); + __nd = __bucket_list_[__chash]; + if (__nd != nullptr) + { + for (__nd = __nd->__next_; __nd != nullptr && + __constrain_hash(__nd->__hash_, __bc) == __chash; + __nd = __nd->__next_) + { + if (key_eq()(__nd->__value_, __k)) + goto __done; + } + } + } + { +#ifndef _LIBCPP_CXX03_LANG + __node_holder __h = __construct_node_hash(__hash, _VSTD::forward<_Args>(__args)...); +#else + __node_holder __h = __construct_node_hash(__hash, __args); +#endif + if (size()+1 > __bc * max_load_factor() || __bc == 0) + { + rehash(_VSTD::max(2 * __bc + !__is_hash_power2(__bc), + size_type(ceil(float(size() + 1) / max_load_factor())))); + __bc = bucket_count(); + __chash = __constrain_hash(__hash, __bc); + } + // insert_after __bucket_list_[__chash], or __first_node if bucket is null + __node_pointer __pn = __bucket_list_[__chash]; + if (__pn == nullptr) + { + __pn = static_cast<__node_pointer>(static_cast<__void_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))); + __h->__next_ = __pn->__next_; + __pn->__next_ = __h.get(); + // fix up __bucket_list_ + __bucket_list_[__chash] = __pn; + if (__h->__next_ != nullptr) + __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get(); + } + else + { + __h->__next_ = __pn->__next_; + __pn->__next_ = __h.get(); + } + __nd = __h.release(); + // increment size + ++size(); + __inserted = true; + } +__done: +#if _LIBCPP_DEBUG_LEVEL >= 2 + return pair(iterator(__nd, this), __inserted); +#else + return pair(iterator(__nd), __inserted); +#endif +} + +#ifndef _LIBCPP_CXX03_LANG + +template +template +pair::iterator, bool> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args) +{ + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + pair __r = __node_insert_unique(__h.get()); + if (__r.second) + __h.release(); + return __r; +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args) +{ + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + iterator __r = __node_insert_multi(__h.get()); + __h.release(); + return __r; +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi( + const_iterator __p, _Args&&... __args) +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" + " referring to this unordered container"); +#endif + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + iterator __r = __node_insert_multi(__p, __h.get()); + __h.release(); + return __r; +} + +#else // _LIBCPP_CXX03_LANG + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const __container_value_type& __x) +{ + __node_holder __h = __construct_node(__x); + iterator __r = __node_insert_multi(__h.get()); + __h.release(); + return __r; +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p, + const __container_value_type& __x) +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + "unordered container::insert(const_iterator, lvalue) called with an iterator not" + " referring to this unordered container"); +#endif + __node_holder __h = __construct_node(__x); + iterator __r = __node_insert_multi(__p, __h.get()); + __h.release(); + return __r; +} + +#endif // _LIBCPP_CXX03_LANG + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n) +{ + if (__n == 1) + __n = 2; + else if (__n & (__n - 1)) + __n = __next_prime(__n); + size_type __bc = bucket_count(); + if (__n > __bc) + __rehash(__n); + else if (__n < __bc) + { + __n = _VSTD::max + ( + __n, + __is_hash_power2(__bc) ? __next_hash_pow2(size_t(ceil(float(size()) / max_load_factor()))) : + __next_prime(size_t(ceil(float(size()) / max_load_factor()))) + ); + if (__n < __bc) + __rehash(__n); + } +} + +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc) +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__invalidate_all(this); +#endif // _LIBCPP_DEBUG_LEVEL >= 2 + __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc(); + __bucket_list_.reset(__nbc > 0 ? + __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr); + __bucket_list_.get_deleter().size() = __nbc; + if (__nbc > 0) + { + for (size_type __i = 0; __i < __nbc; ++__i) + __bucket_list_[__i] = nullptr; + __node_pointer __pp(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))); + __node_pointer __cp = __pp->__next_; + if (__cp != nullptr) + { + size_type __chash = __constrain_hash(__cp->__hash_, __nbc); + __bucket_list_[__chash] = __pp; + size_type __phash = __chash; + for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr; + __cp = __pp->__next_) + { + __chash = __constrain_hash(__cp->__hash_, __nbc); + if (__chash == __phash) + __pp = __cp; + else + { + if (__bucket_list_[__chash] == nullptr) + { + __bucket_list_[__chash] = __pp; + __pp = __cp; + __phash = __chash; + } + else + { + __node_pointer __np = __cp; + for (; __np->__next_ != nullptr && + key_eq()(__cp->__value_, __np->__next_->__value_); + __np = __np->__next_) + ; + __pp->__next_ = __np->__next_; + __np->__next_ = __bucket_list_[__chash]->__next_; + __bucket_list_[__chash]->__next_ = __cp; + + } + } + } + } + } +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) +{ + size_t __hash = hash_function()(__k); + size_type __bc = bucket_count(); + if (__bc != 0) + { + size_t __chash = __constrain_hash(__hash, __bc); + __node_pointer __nd = __bucket_list_[__chash]; + if (__nd != nullptr) + { + for (__nd = __nd->__next_; __nd != nullptr && + (__nd->__hash_ == __hash + || __constrain_hash(__nd->__hash_, __bc) == __chash); + __nd = __nd->__next_) + { + if ((__nd->__hash_ == __hash) && key_eq()(__nd->__value_, __k)) +#if _LIBCPP_DEBUG_LEVEL >= 2 + return iterator(__nd, this); +#else + return iterator(__nd); +#endif + } + } + } + return end(); +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const +{ + size_t __hash = hash_function()(__k); + size_type __bc = bucket_count(); + if (__bc != 0) + { + size_t __chash = __constrain_hash(__hash, __bc); + __node_const_pointer __nd = __bucket_list_[__chash]; + if (__nd != nullptr) + { + for (__nd = __nd->__next_; __nd != nullptr && + (__hash == __nd->__hash_ || __constrain_hash(__nd->__hash_, __bc) == __chash); + __nd = __nd->__next_) + { + if ((__nd->__hash_ == __hash) && key_eq()(__nd->__value_, __k)) +#if _LIBCPP_DEBUG_LEVEL >= 2 + return const_iterator(__nd, this); +#else + return const_iterator(__nd); +#endif + } + } + + } + return end(); +} + +#ifndef _LIBCPP_CXX03_LANG + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args) +{ + static_assert(!__is_hash_value_type<_Args...>::value, + "Construct cannot be called with a hash value type"); + __node_allocator& __na = __node_alloc(); + __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...); + __h.get_deleter().__value_constructed = true; + __h->__hash_ = hash_function()(__h->__value_); + __h->__next_ = nullptr; + return __h; +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash( + size_t __hash, _First&& __f, _Rest&& ...__rest) +{ + static_assert(!__is_hash_value_type<_First, _Rest...>::value, + "Construct cannot be called with a hash value type"); + __node_allocator& __na = __node_alloc(); + __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), + _VSTD::forward<_First>(__f), + _VSTD::forward<_Rest>(__rest)...); + __h.get_deleter().__value_constructed = true; + __h->__hash_ = __hash; + __h->__next_ = nullptr; + return __h; +} + +#else // _LIBCPP_CXX03_LANG + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const __container_value_type& __v) +{ + __node_allocator& __na = __node_alloc(); + __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v); + __h.get_deleter().__value_constructed = true; + __h->__hash_ = hash_function()(__h->__value_); + __h->__next_ = nullptr; + return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, + const __container_value_type& __v) +{ + __node_allocator& __na = __node_alloc(); + __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v); + __h.get_deleter().__value_constructed = true; + __h->__hash_ = __hash; + __h->__next_ = nullptr; + return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 +} + +#endif // _LIBCPP_CXX03_LANG + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) +{ + __node_pointer __np = __p.__node_; +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, + "unordered container erase(iterator) called with an iterator not" + " referring to this container"); + _LIBCPP_ASSERT(__p != end(), + "unordered container erase(iterator) called with a non-dereferenceable iterator"); + iterator __r(__np, this); +#else + iterator __r(__np); +#endif + ++__r; + remove(__p); + return __r; +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, + const_iterator __last) +{ +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, + "unodered container::erase(iterator, iterator) called with an iterator not" + " referring to this unodered container"); + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this, + "unodered container::erase(iterator, iterator) called with an iterator not" + " referring to this unodered container"); +#endif + for (const_iterator __p = __first; __first != __last; __p = __first) + { + ++__first; + erase(__p); + } + __node_pointer __np = __last.__node_; +#if _LIBCPP_DEBUG_LEVEL >= 2 + return iterator (__np, this); +#else + return iterator (__np); +#endif +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k) +{ + iterator __i = find(__k); + if (__i == end()) + return 0; + erase(__i); + return 1; +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k) +{ + size_type __r = 0; + iterator __i = find(__k); + if (__i != end()) + { + iterator __e = end(); + do + { + erase(__i++); + ++__r; + } while (__i != __e && key_eq()(*__i, __k)); + } + return __r; +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder +__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT +{ + // current node + __node_pointer __cn = __p.__node_; + size_type __bc = bucket_count(); + size_t __chash = __constrain_hash(__cn->__hash_, __bc); + // find previous node + __node_pointer __pn = __bucket_list_[__chash]; + for (; __pn->__next_ != __cn; __pn = __pn->__next_) + ; + // Fix up __bucket_list_ + // if __pn is not in same bucket (before begin is not in same bucket) && + // if __cn->__next_ is not in same bucket (nullptr is not in same bucket) + if (__pn == static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())) + || __constrain_hash(__pn->__hash_, __bc) != __chash) + { + if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash) + __bucket_list_[__chash] = nullptr; + } + // if __cn->__next_ is not in same bucket (nullptr is in same bucket) + if (__cn->__next_ != nullptr) + { + size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc); + if (__nhash != __chash) + __bucket_list_[__nhash] = __pn; + } + // remove __cn + __pn->__next_ = __cn->__next_; + __cn->__next_ = nullptr; + --size(); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __c_node* __c = __get_db()->__find_c_and_lock(this); + for (__i_node** __p = __c->end_; __p != __c->beg_; ) + { + --__p; + iterator* __i = static_cast((*__p)->__i_); + if (__i->__node_ == __cn) + { + (*__p)->__c_ = nullptr; + if (--__c->end_ != __p) + memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); + } + } + __get_db()->unlock(); +#endif + return __node_holder(__cn, _Dp(__node_alloc(), true)); +} + +template +template +inline +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const +{ + return static_cast(find(__k) != end()); +} + +template +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const +{ + size_type __r = 0; + const_iterator __i = find(__k); + if (__i != end()) + { + const_iterator __e = end(); + do + { + ++__i; + ++__r; + } while (__i != __e && key_eq()(*__i, __k)); + } + return __r; +} + +template +template +pair::iterator, + typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique( + const _Key& __k) +{ + iterator __i = find(__k); + iterator __j = __i; + if (__i != end()) + ++__j; + return pair(__i, __j); +} + +template +template +pair::const_iterator, + typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique( + const _Key& __k) const +{ + const_iterator __i = find(__k); + const_iterator __j = __i; + if (__i != end()) + ++__j; + return pair(__i, __j); +} + +template +template +pair::iterator, + typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi( + const _Key& __k) +{ + iterator __i = find(__k); + iterator __j = __i; + if (__i != end()) + { + iterator __e = end(); + do + { + ++__j; + } while (__j != __e && key_eq()(*__j, __k)); + } + return pair(__i, __j); +} + +template +template +pair::const_iterator, + typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator> +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi( + const _Key& __k) const +{ + const_iterator __i = find(__k); + const_iterator __j = __i; + if (__i != end()) + { + const_iterator __e = end(); + do + { + ++__j; + } while (__j != __e && key_eq()(*__j, __k)); + } + return pair(__i, __j); +} + +// For some reason VS compiler does not support having intermixed ifdefs in _NOEXCEPT_ +// We had to rewrite the declaration to silence the compilation errors. +// However, this issue has been addressed in rev. 242623 +template +void +__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) +#if _LIBCPP_STD_VER <= 11 + _NOEXCEPT_( + __is_nothrow_swappable::value && __is_nothrow_swappable::value + && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value + || __is_nothrow_swappable<__pointer_allocator>::value) + && (!__node_traits::propagate_on_container_swap::value + || __is_nothrow_swappable<__node_allocator>::value) + ) +#else + _NOEXCEPT_(__is_nothrow_swappable::value && __is_nothrow_swappable::value) +#endif +{ + { + __node_pointer_pointer __npp = __bucket_list_.release(); + __bucket_list_.reset(__u.__bucket_list_.release()); + __u.__bucket_list_.reset(__npp); + } + _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size()); + __swap_allocator(__bucket_list_.get_deleter().__alloc(), + __u.__bucket_list_.get_deleter().__alloc()); + __swap_allocator(__node_alloc(), __u.__node_alloc()); + _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_); + __p2_.swap(__u.__p2_); + __p3_.swap(__u.__p3_); + if (size() > 0) + __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = + static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); + if (__u.size() > 0) + __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] = + static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__u.__p1_.first())); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->swap(this, &__u); +#endif +} + +template +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type +__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const +{ + _LIBCPP_ASSERT(__n < bucket_count(), + "unordered container::bucket_size(n) called with n >= bucket_count()"); + __node_const_pointer __np = __bucket_list_[__n]; + size_type __bc = bucket_count(); + size_type __r = 0; + if (__np != nullptr) + { + for (__np = __np->__next_; __np != nullptr && + __constrain_hash(__np->__hash_, __bc) == __n; + __np = __np->__next_, ++__r) + ; + } + return __r; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, + __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) +{ + __x.swap(__y); +} + +#if _LIBCPP_DEBUG_LEVEL >= 2 + +template +bool +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const +{ + return __i->__node_ != nullptr; +} + +template +bool +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const +{ + return false; +} + +template +bool +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const +{ + return false; +} + +template +bool +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const +{ + return false; +} + +#endif // _LIBCPP_DEBUG_LEVEL >= 2 +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP__HASH_TABLE diff --git a/sdk/tlibcxx/include/__locale b/sdk/tlibcxx/include/__locale new file mode 100644 index 00000000..3d5b7911 --- /dev/null +++ b/sdk/tlibcxx/include/__locale @@ -0,0 +1,1481 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE +#define _LIBCPP___LOCALE + +// Not supported in SGX. +#include <__config> +#if !defined(_LIBCPP_SGX_CONFIG) +#include +#include +#include +#include +#include +#include +#include +#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) +# include +#elif defined(_AIX) +# include +#elif defined(__ANDROID__) +// Android gained the locale aware functions in L (API level 21) +# include +# if __ANDROID_API__ <= 20 +# include +# endif +#elif defined(__sun__) +# include +# include +#elif defined(_NEWLIB_VERSION) +# include +#elif (defined(__GLIBC__) || defined(__APPLE__) || defined(__FreeBSD__) \ + || defined(__EMSCRIPTEN__) || defined(__IBMCPP__)) +# include +#elif defined(_LIBCPP_HAS_MUSL_LIBC) +# include +#endif // __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun__ || __EMSCRIPTEN__ || __IBMCPP__ + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_TYPE_VIS locale; + +template +_LIBCPP_INLINE_VISIBILITY +bool +has_facet(const locale&) _NOEXCEPT; + +template +_LIBCPP_INLINE_VISIBILITY +const _Facet& +use_facet(const locale&); + +class _LIBCPP_TYPE_VIS locale +{ +public: + // types: + class _LIBCPP_TYPE_VIS facet; + class _LIBCPP_TYPE_VIS id; + + typedef int category; + static const category // values assigned here are for exposition only + none = 0, + collate = LC_COLLATE_MASK, + ctype = LC_CTYPE_MASK, + monetary = LC_MONETARY_MASK, + numeric = LC_NUMERIC_MASK, + time = LC_TIME_MASK, + messages = LC_MESSAGES_MASK, + all = collate | ctype | monetary | numeric | time | messages; + + // construct/copy/destroy: + locale() _NOEXCEPT; + locale(const locale&) _NOEXCEPT; + explicit locale(const char*); + explicit locale(const string&); + locale(const locale&, const char*, category); + locale(const locale&, const string&, category); + template + _LIBCPP_INLINE_VISIBILITY locale(const locale&, _Facet*); + locale(const locale&, const locale&, category); + + ~locale(); + + const locale& operator=(const locale&) _NOEXCEPT; + + template locale combine(const locale&) const; + + // locale operations: + string name() const; + bool operator==(const locale&) const; + bool operator!=(const locale& __y) const {return !(*this == __y);} + template + bool operator()(const basic_string<_CharT, _Traits, _Allocator>&, + const basic_string<_CharT, _Traits, _Allocator>&) const; + + // global locale objects: + static locale global(const locale&); + static const locale& classic(); + +private: + class __imp; + __imp* __locale_; + + void __install_ctor(const locale&, facet*, long); + static locale& __global(); + bool has_facet(id&) const; + const facet* use_facet(id&) const; + + template friend bool has_facet(const locale&) _NOEXCEPT; + template friend const _Facet& use_facet(const locale&); +}; + +class _LIBCPP_TYPE_VIS locale::facet + : public __shared_count +{ +protected: + _LIBCPP_INLINE_VISIBILITY + explicit facet(size_t __refs = 0) + : __shared_count(static_cast(__refs)-1) {} + + virtual ~facet(); + +// facet(const facet&) = delete; // effectively done in __shared_count +// void operator=(const facet&) = delete; +private: + virtual void __on_zero_shared() _NOEXCEPT; +}; + +class _LIBCPP_TYPE_VIS locale::id +{ + once_flag __flag_; + int32_t __id_; + + static int32_t __next_id; +public: + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR id() :__id_(0) {} +private: + void __init(); + void operator=(const id&); // = delete; + id(const id&); // = delete; +public: // only needed for tests + long __get(); + + friend class locale; + friend class locale::__imp; +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +locale::locale(const locale& __other, _Facet* __f) +{ + __install_ctor(__other, __f, __f ? __f->id.__get() : 0); +} + +template +locale +locale::combine(const locale& __other) const +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + if (!_VSTD::has_facet<_Facet>(__other)) + throw runtime_error("locale::combine: locale missing facet"); +#endif // _LIBCPP_NO_EXCEPTIONS + return locale(*this, &const_cast<_Facet&>(_VSTD::use_facet<_Facet>(__other))); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +has_facet(const locale& __l) _NOEXCEPT +{ + return __l.has_facet(_Facet::id); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +const _Facet& +use_facet(const locale& __l) +{ + return static_cast(*__l.use_facet(_Facet::id)); +} + +// template class collate; + +template +class _LIBCPP_TYPE_VIS_ONLY collate + : public locale::facet +{ +public: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_INLINE_VISIBILITY + explicit collate(size_t __refs = 0) + : locale::facet(__refs) {} + + _LIBCPP_INLINE_VISIBILITY + int compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const + { + return do_compare(__lo1, __hi1, __lo2, __hi2); + } + + _LIBCPP_INLINE_VISIBILITY + string_type transform(const char_type* __lo, const char_type* __hi) const + { + return do_transform(__lo, __hi); + } + + _LIBCPP_INLINE_VISIBILITY + long hash(const char_type* __lo, const char_type* __hi) const + { + return do_hash(__lo, __hi); + } + + static locale::id id; + +protected: + ~collate(); + virtual int do_compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const; + virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const + {return string_type(__lo, __hi);} + virtual long do_hash(const char_type* __lo, const char_type* __hi) const; +}; + +template locale::id collate<_CharT>::id; + +template +collate<_CharT>::~collate() +{ +} + +template +int +collate<_CharT>::do_compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const +{ + for (; __lo2 != __hi2; ++__lo1, ++__lo2) + { + if (__lo1 == __hi1 || *__lo1 < *__lo2) + return -1; + if (*__lo2 < *__lo1) + return 1; + } + return __lo1 != __hi1; +} + +template +long +collate<_CharT>::do_hash(const char_type* __lo, const char_type* __hi) const +{ + size_t __h = 0; + const size_t __sr = __CHAR_BIT__ * sizeof(size_t) - 8; + const size_t __mask = size_t(0xF) << (__sr + 4); + for(const char_type* __p = __lo; __p != __hi; ++__p) + { + __h = (__h << 4) + static_cast(*__p); + size_t __g = __h & __mask; + __h ^= __g | (__g >> __sr); + } + return static_cast(__h); +} + +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS collate) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS collate) + +// template class collate_byname; + +template class _LIBCPP_TYPE_VIS_ONLY collate_byname; + +template <> +class _LIBCPP_TYPE_VIS collate_byname + : public collate +{ + locale_t __l; +public: + typedef char char_type; + typedef basic_string string_type; + + explicit collate_byname(const char* __n, size_t __refs = 0); + explicit collate_byname(const string& __n, size_t __refs = 0); + +protected: + ~collate_byname(); + virtual int do_compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const; + virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const; +}; + +template <> +class _LIBCPP_TYPE_VIS collate_byname + : public collate +{ + locale_t __l; +public: + typedef wchar_t char_type; + typedef basic_string string_type; + + explicit collate_byname(const char* __n, size_t __refs = 0); + explicit collate_byname(const string& __n, size_t __refs = 0); + +protected: + ~collate_byname(); + + virtual int do_compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const; + virtual string_type do_transform(const char_type* __lo, const char_type* __hi) const; +}; + +template +bool +locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x, + const basic_string<_CharT, _Traits, _Allocator>& __y) const +{ + return _VSTD::use_facet<_VSTD::collate<_CharT> >(*this).compare( + __x.data(), __x.data() + __x.size(), + __y.data(), __y.data() + __y.size()) < 0; +} + +// template class ctype + +class _LIBCPP_TYPE_VIS ctype_base +{ +public: +#if defined(__GLIBC__) + typedef unsigned short mask; + static const mask space = _ISspace; + static const mask print = _ISprint; + static const mask cntrl = _IScntrl; + static const mask upper = _ISupper; + static const mask lower = _ISlower; + static const mask alpha = _ISalpha; + static const mask digit = _ISdigit; + static const mask punct = _ISpunct; + static const mask xdigit = _ISxdigit; + static const mask blank = _ISblank; +#elif defined(_WIN32) + typedef unsigned short mask; + static const mask space = _SPACE; + static const mask print = _BLANK|_PUNCT|_ALPHA|_DIGIT; + static const mask cntrl = _CONTROL; + static const mask upper = _UPPER; + static const mask lower = _LOWER; + static const mask alpha = _ALPHA; + static const mask digit = _DIGIT; + static const mask punct = _PUNCT; + static const mask xdigit = _HEX; + static const mask blank = _BLANK; +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT +#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) +# ifdef __APPLE__ + typedef __uint32_t mask; +# elif defined(__FreeBSD__) + typedef unsigned long mask; +# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__) + typedef unsigned short mask; +# endif + static const mask space = _CTYPE_S; + static const mask print = _CTYPE_R; + static const mask cntrl = _CTYPE_C; + static const mask upper = _CTYPE_U; + static const mask lower = _CTYPE_L; + static const mask alpha = _CTYPE_A; + static const mask digit = _CTYPE_D; + static const mask punct = _CTYPE_P; + static const mask xdigit = _CTYPE_X; + +# if defined(__NetBSD__) + static const mask blank = _CTYPE_BL; +# else + static const mask blank = _CTYPE_B; +# endif +#elif defined(__sun__) || defined(_AIX) + typedef unsigned int mask; + static const mask space = _ISSPACE; + static const mask print = _ISPRINT; + static const mask cntrl = _ISCNTRL; + static const mask upper = _ISUPPER; + static const mask lower = _ISLOWER; + static const mask alpha = _ISALPHA; + static const mask digit = _ISDIGIT; + static const mask punct = _ISPUNCT; + static const mask xdigit = _ISXDIGIT; + static const mask blank = _ISBLANK; +#elif defined(_NEWLIB_VERSION) + // Same type as Newlib's _ctype_ array in newlib/libc/include/ctype.h. + typedef char mask; + static const mask space = _S; + static const mask print = _P | _U | _L | _N | _B; + static const mask cntrl = _C; + static const mask upper = _U; + static const mask lower = _L; + static const mask alpha = _U | _L; + static const mask digit = _N; + static const mask punct = _P; + static const mask xdigit = _X | _N; + static const mask blank = _B; +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA +# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT +#else + typedef unsigned long mask; + static const mask space = 1<<0; + static const mask print = 1<<1; + static const mask cntrl = 1<<2; + static const mask upper = 1<<3; + static const mask lower = 1<<4; + static const mask alpha = 1<<5; + static const mask digit = 1<<6; + static const mask punct = 1<<7; + static const mask xdigit = 1<<8; + static const mask blank = 1<<9; +#endif + static const mask alnum = alpha | digit; + static const mask graph = alnum | punct; + + _LIBCPP_ALWAYS_INLINE ctype_base() {} +}; + +template class _LIBCPP_TYPE_VIS_ONLY ctype; + +template <> +class _LIBCPP_TYPE_VIS ctype + : public locale::facet, + public ctype_base +{ +public: + typedef wchar_t char_type; + + _LIBCPP_ALWAYS_INLINE + explicit ctype(size_t __refs = 0) + : locale::facet(__refs) {} + + _LIBCPP_ALWAYS_INLINE + bool is(mask __m, char_type __c) const + { + return do_is(__m, __c); + } + + _LIBCPP_ALWAYS_INLINE + const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const + { + return do_is(__low, __high, __vec); + } + + _LIBCPP_ALWAYS_INLINE + const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const + { + return do_scan_is(__m, __low, __high); + } + + _LIBCPP_ALWAYS_INLINE + const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const + { + return do_scan_not(__m, __low, __high); + } + + _LIBCPP_ALWAYS_INLINE + char_type toupper(char_type __c) const + { + return do_toupper(__c); + } + + _LIBCPP_ALWAYS_INLINE + const char_type* toupper(char_type* __low, const char_type* __high) const + { + return do_toupper(__low, __high); + } + + _LIBCPP_ALWAYS_INLINE + char_type tolower(char_type __c) const + { + return do_tolower(__c); + } + + _LIBCPP_ALWAYS_INLINE + const char_type* tolower(char_type* __low, const char_type* __high) const + { + return do_tolower(__low, __high); + } + + _LIBCPP_ALWAYS_INLINE + char_type widen(char __c) const + { + return do_widen(__c); + } + + _LIBCPP_ALWAYS_INLINE + const char* widen(const char* __low, const char* __high, char_type* __to) const + { + return do_widen(__low, __high, __to); + } + + _LIBCPP_ALWAYS_INLINE + char narrow(char_type __c, char __dfault) const + { + return do_narrow(__c, __dfault); + } + + _LIBCPP_ALWAYS_INLINE + const char_type* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const + { + return do_narrow(__low, __high, __dfault, __to); + } + + static locale::id id; + +protected: + ~ctype(); + virtual bool do_is(mask __m, char_type __c) const; + virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const; + virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const; + virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const; + virtual char_type do_toupper(char_type) const; + virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const; + virtual char_type do_tolower(char_type) const; + virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const; + virtual char_type do_widen(char) const; + virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const; + virtual char do_narrow(char_type, char __dfault) const; + virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const; +}; + +template <> +class _LIBCPP_TYPE_VIS ctype + : public locale::facet, public ctype_base +{ + const mask* __tab_; + bool __del_; +public: + typedef char char_type; + + explicit ctype(const mask* __tab = 0, bool __del = false, size_t __refs = 0); + + _LIBCPP_ALWAYS_INLINE + bool is(mask __m, char_type __c) const + { + return isascii(__c) ? (__tab_[static_cast(__c)] & __m) !=0 : false; + } + + _LIBCPP_ALWAYS_INLINE + const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const + { + for (; __low != __high; ++__low, ++__vec) + *__vec = isascii(*__low) ? __tab_[static_cast(*__low)] : 0; + return __low; + } + + _LIBCPP_ALWAYS_INLINE + const char_type* scan_is (mask __m, const char_type* __low, const char_type* __high) const + { + for (; __low != __high; ++__low) + if (isascii(*__low) && (__tab_[static_cast(*__low)] & __m)) + break; + return __low; + } + + _LIBCPP_ALWAYS_INLINE + const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const + { + for (; __low != __high; ++__low) + if (!(isascii(*__low) && (__tab_[static_cast(*__low)] & __m))) + break; + return __low; + } + + _LIBCPP_ALWAYS_INLINE + char_type toupper(char_type __c) const + { + return do_toupper(__c); + } + + _LIBCPP_ALWAYS_INLINE + const char_type* toupper(char_type* __low, const char_type* __high) const + { + return do_toupper(__low, __high); + } + + _LIBCPP_ALWAYS_INLINE + char_type tolower(char_type __c) const + { + return do_tolower(__c); + } + + _LIBCPP_ALWAYS_INLINE + const char_type* tolower(char_type* __low, const char_type* __high) const + { + return do_tolower(__low, __high); + } + + _LIBCPP_ALWAYS_INLINE + char_type widen(char __c) const + { + return do_widen(__c); + } + + _LIBCPP_ALWAYS_INLINE + const char* widen(const char* __low, const char* __high, char_type* __to) const + { + return do_widen(__low, __high, __to); + } + + _LIBCPP_ALWAYS_INLINE + char narrow(char_type __c, char __dfault) const + { + return do_narrow(__c, __dfault); + } + + _LIBCPP_ALWAYS_INLINE + const char* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const + { + return do_narrow(__low, __high, __dfault, __to); + } + + static locale::id id; + +#ifdef _CACHED_RUNES + static const size_t table_size = _CACHED_RUNES; +#else + static const size_t table_size = 256; // FIXME: Don't hardcode this. +#endif + _LIBCPP_ALWAYS_INLINE const mask* table() const _NOEXCEPT {return __tab_;} + static const mask* classic_table() _NOEXCEPT; +#if defined(__GLIBC__) || defined(__EMSCRIPTEN__) + static const int* __classic_upper_table() _NOEXCEPT; + static const int* __classic_lower_table() _NOEXCEPT; +#endif +#if defined(__NetBSD__) + static const short* __classic_upper_table() _NOEXCEPT; + static const short* __classic_lower_table() _NOEXCEPT; +#endif + +protected: + ~ctype(); + virtual char_type do_toupper(char_type __c) const; + virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const; + virtual char_type do_tolower(char_type __c) const; + virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const; + virtual char_type do_widen(char __c) const; + virtual const char* do_widen(const char* __low, const char* __high, char_type* __to) const; + virtual char do_narrow(char_type __c, char __dfault) const; + virtual const char* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const; +}; + +// template class ctype_byname; + +template class _LIBCPP_TYPE_VIS_ONLY ctype_byname; + +template <> +class _LIBCPP_TYPE_VIS ctype_byname + : public ctype +{ + locale_t __l; + +public: + explicit ctype_byname(const char*, size_t = 0); + explicit ctype_byname(const string&, size_t = 0); + +protected: + ~ctype_byname(); + virtual char_type do_toupper(char_type) const; + virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const; + virtual char_type do_tolower(char_type) const; + virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const; +}; + +template <> +class _LIBCPP_TYPE_VIS ctype_byname + : public ctype +{ + locale_t __l; + +public: + explicit ctype_byname(const char*, size_t = 0); + explicit ctype_byname(const string&, size_t = 0); + +protected: + ~ctype_byname(); + virtual bool do_is(mask __m, char_type __c) const; + virtual const char_type* do_is(const char_type* __low, const char_type* __high, mask* __vec) const; + virtual const char_type* do_scan_is(mask __m, const char_type* __low, const char_type* __high) const; + virtual const char_type* do_scan_not(mask __m, const char_type* __low, const char_type* __high) const; + virtual char_type do_toupper(char_type) const; + virtual const char_type* do_toupper(char_type* __low, const char_type* __high) const; + virtual char_type do_tolower(char_type) const; + virtual const char_type* do_tolower(char_type* __low, const char_type* __high) const; + virtual char_type do_widen(char) const; + virtual const char* do_widen(const char* __low, const char* __high, char_type* __dest) const; + virtual char do_narrow(char_type, char __dfault) const; + virtual const char_type* do_narrow(const char_type* __low, const char_type* __high, char __dfault, char* __dest) const; +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +isspace(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::space, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +isprint(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::print, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +iscntrl(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::cntrl, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +isupper(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::upper, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +islower(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::lower, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +isalpha(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::alpha, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +isdigit(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::digit, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +ispunct(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::punct, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +isxdigit(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::xdigit, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +isalnum(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::alnum, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +isgraph(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).is(ctype_base::graph, __c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_CharT +toupper(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).toupper(__c); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_CharT +tolower(_CharT __c, const locale& __loc) +{ + return use_facet >(__loc).tolower(__c); +} + +// codecvt_base + +class _LIBCPP_TYPE_VIS codecvt_base +{ +public: + _LIBCPP_ALWAYS_INLINE codecvt_base() {} + enum result {ok, partial, error, noconv}; +}; + +// template class codecvt; + +template class _LIBCPP_TYPE_VIS_ONLY codecvt; + +// template <> class codecvt + +template <> +class _LIBCPP_TYPE_VIS codecvt + : public locale::facet, + public codecvt_base +{ +public: + typedef char intern_type; + typedef char extern_type; + typedef mbstate_t state_type; + + _LIBCPP_ALWAYS_INLINE + explicit codecvt(size_t __refs = 0) + : locale::facet(__refs) {} + + _LIBCPP_ALWAYS_INLINE + result out(state_type& __st, + const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const + { + return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + result unshift(state_type& __st, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const + { + return do_unshift(__st, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + result in(state_type& __st, + const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, + intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const + { + return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + int encoding() const _NOEXCEPT + { + return do_encoding(); + } + + _LIBCPP_ALWAYS_INLINE + bool always_noconv() const _NOEXCEPT + { + return do_always_noconv(); + } + + _LIBCPP_ALWAYS_INLINE + int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const + { + return do_length(__st, __frm, __end, __mx); + } + + _LIBCPP_ALWAYS_INLINE + int max_length() const _NOEXCEPT + { + return do_max_length(); + } + + static locale::id id; + +protected: + _LIBCPP_ALWAYS_INLINE + explicit codecvt(const char*, size_t __refs = 0) + : locale::facet(__refs) {} + + ~codecvt(); + + virtual result do_out(state_type& __st, + const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const; + virtual result do_in(state_type& __st, + const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, + intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const; + virtual result do_unshift(state_type& __st, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const; + virtual int do_encoding() const _NOEXCEPT; + virtual bool do_always_noconv() const _NOEXCEPT; + virtual int do_length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const; + virtual int do_max_length() const _NOEXCEPT; +}; + +// template <> class codecvt + +template <> +class _LIBCPP_TYPE_VIS codecvt + : public locale::facet, + public codecvt_base +{ + locale_t __l; +public: + typedef wchar_t intern_type; + typedef char extern_type; + typedef mbstate_t state_type; + + explicit codecvt(size_t __refs = 0); + + _LIBCPP_ALWAYS_INLINE + result out(state_type& __st, + const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const + { + return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + result unshift(state_type& __st, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const + { + return do_unshift(__st, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + result in(state_type& __st, + const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, + intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const + { + return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + int encoding() const _NOEXCEPT + { + return do_encoding(); + } + + _LIBCPP_ALWAYS_INLINE + bool always_noconv() const _NOEXCEPT + { + return do_always_noconv(); + } + + _LIBCPP_ALWAYS_INLINE + int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const + { + return do_length(__st, __frm, __end, __mx); + } + + _LIBCPP_ALWAYS_INLINE + int max_length() const _NOEXCEPT + { + return do_max_length(); + } + + static locale::id id; + +protected: + explicit codecvt(const char*, size_t __refs = 0); + + ~codecvt(); + + virtual result do_out(state_type& __st, + const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const; + virtual result do_in(state_type& __st, + const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, + intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const; + virtual result do_unshift(state_type& __st, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const; + virtual int do_encoding() const _NOEXCEPT; + virtual bool do_always_noconv() const _NOEXCEPT; + virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const; + virtual int do_max_length() const _NOEXCEPT; +}; + +// template <> class codecvt + +template <> +class _LIBCPP_TYPE_VIS codecvt + : public locale::facet, + public codecvt_base +{ +public: + typedef char16_t intern_type; + typedef char extern_type; + typedef mbstate_t state_type; + + _LIBCPP_ALWAYS_INLINE + explicit codecvt(size_t __refs = 0) + : locale::facet(__refs) {} + + _LIBCPP_ALWAYS_INLINE + result out(state_type& __st, + const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const + { + return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + result unshift(state_type& __st, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const + { + return do_unshift(__st, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + result in(state_type& __st, + const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, + intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const + { + return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + int encoding() const _NOEXCEPT + { + return do_encoding(); + } + + _LIBCPP_ALWAYS_INLINE + bool always_noconv() const _NOEXCEPT + { + return do_always_noconv(); + } + + _LIBCPP_ALWAYS_INLINE + int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const + { + return do_length(__st, __frm, __end, __mx); + } + + _LIBCPP_ALWAYS_INLINE + int max_length() const _NOEXCEPT + { + return do_max_length(); + } + + static locale::id id; + +protected: + _LIBCPP_ALWAYS_INLINE + explicit codecvt(const char*, size_t __refs = 0) + : locale::facet(__refs) {} + + ~codecvt(); + + virtual result do_out(state_type& __st, + const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const; + virtual result do_in(state_type& __st, + const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, + intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const; + virtual result do_unshift(state_type& __st, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const; + virtual int do_encoding() const _NOEXCEPT; + virtual bool do_always_noconv() const _NOEXCEPT; + virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const; + virtual int do_max_length() const _NOEXCEPT; +}; + +// template <> class codecvt + +template <> +class _LIBCPP_TYPE_VIS codecvt + : public locale::facet, + public codecvt_base +{ +public: + typedef char32_t intern_type; + typedef char extern_type; + typedef mbstate_t state_type; + + _LIBCPP_ALWAYS_INLINE + explicit codecvt(size_t __refs = 0) + : locale::facet(__refs) {} + + _LIBCPP_ALWAYS_INLINE + result out(state_type& __st, + const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const + { + return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + result unshift(state_type& __st, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const + { + return do_unshift(__st, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + result in(state_type& __st, + const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, + intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const + { + return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + } + + _LIBCPP_ALWAYS_INLINE + int encoding() const _NOEXCEPT + { + return do_encoding(); + } + + _LIBCPP_ALWAYS_INLINE + bool always_noconv() const _NOEXCEPT + { + return do_always_noconv(); + } + + _LIBCPP_ALWAYS_INLINE + int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const + { + return do_length(__st, __frm, __end, __mx); + } + + _LIBCPP_ALWAYS_INLINE + int max_length() const _NOEXCEPT + { + return do_max_length(); + } + + static locale::id id; + +protected: + _LIBCPP_ALWAYS_INLINE + explicit codecvt(const char*, size_t __refs = 0) + : locale::facet(__refs) {} + + ~codecvt(); + + virtual result do_out(state_type& __st, + const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const; + virtual result do_in(state_type& __st, + const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, + intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const; + virtual result do_unshift(state_type& __st, + extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const; + virtual int do_encoding() const _NOEXCEPT; + virtual bool do_always_noconv() const _NOEXCEPT; + virtual int do_length(state_type&, const extern_type* __frm, const extern_type* __end, size_t __mx) const; + virtual int do_max_length() const _NOEXCEPT; +}; + +// template class codecvt_byname + +template +class _LIBCPP_TYPE_VIS_ONLY codecvt_byname + : public codecvt<_InternT, _ExternT, _StateT> +{ +public: + _LIBCPP_ALWAYS_INLINE + explicit codecvt_byname(const char* __nm, size_t __refs = 0) + : codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {} + _LIBCPP_ALWAYS_INLINE + explicit codecvt_byname(const string& __nm, size_t __refs = 0) + : codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {} +protected: + ~codecvt_byname(); +}; + +template +codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname() +{ +} + +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname) + +_LIBCPP_FUNC_VIS void __throw_runtime_error(const char*); + +template +struct __narrow_to_utf8 +{ + template + _OutputIterator + operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const; +}; + +template <> +struct __narrow_to_utf8<8> +{ + template + _LIBCPP_ALWAYS_INLINE + _OutputIterator + operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const + { + for (; __wb < __we; ++__wb, ++__s) + *__s = *__wb; + return __s; + } +}; + +template <> +struct __narrow_to_utf8<16> + : public codecvt +{ + _LIBCPP_ALWAYS_INLINE + __narrow_to_utf8() : codecvt(1) {} + + ~__narrow_to_utf8(); + + template + _LIBCPP_ALWAYS_INLINE + _OutputIterator + operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const + { + result __r = ok; + mbstate_t __mb; + while (__wb < __we && __r != error) + { + const int __sz = 32; + char __buf[__sz]; + char* __bn; + const char16_t* __wn = (const char16_t*)__wb; + __r = do_out(__mb, (const char16_t*)__wb, (const char16_t*)__we, __wn, + __buf, __buf+__sz, __bn); + if (__r == codecvt_base::error || __wn == (const char16_t*)__wb) + __throw_runtime_error("locale not supported"); + for (const char* __p = __buf; __p < __bn; ++__p, ++__s) + *__s = *__p; + __wb = (const _CharT*)__wn; + } + return __s; + } +}; + +template <> +struct __narrow_to_utf8<32> + : public codecvt +{ + _LIBCPP_ALWAYS_INLINE + __narrow_to_utf8() : codecvt(1) {} + + ~__narrow_to_utf8(); + + template + _LIBCPP_ALWAYS_INLINE + _OutputIterator + operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const + { + result __r = ok; + mbstate_t __mb; + while (__wb < __we && __r != error) + { + const int __sz = 32; + char __buf[__sz]; + char* __bn; + const char32_t* __wn = (const char32_t*)__wb; + __r = do_out(__mb, (const char32_t*)__wb, (const char32_t*)__we, __wn, + __buf, __buf+__sz, __bn); + if (__r == codecvt_base::error || __wn == (const char32_t*)__wb) + __throw_runtime_error("locale not supported"); + for (const char* __p = __buf; __p < __bn; ++__p, ++__s) + *__s = *__p; + __wb = (const _CharT*)__wn; + } + return __s; + } +}; + +template +struct __widen_from_utf8 +{ + template + _OutputIterator + operator()(_OutputIterator __s, const char* __nb, const char* __ne) const; +}; + +template <> +struct __widen_from_utf8<8> +{ + template + _LIBCPP_ALWAYS_INLINE + _OutputIterator + operator()(_OutputIterator __s, const char* __nb, const char* __ne) const + { + for (; __nb < __ne; ++__nb, ++__s) + *__s = *__nb; + return __s; + } +}; + +template <> +struct __widen_from_utf8<16> + : public codecvt +{ + _LIBCPP_ALWAYS_INLINE + __widen_from_utf8() : codecvt(1) {} + + ~__widen_from_utf8(); + + template + _LIBCPP_ALWAYS_INLINE + _OutputIterator + operator()(_OutputIterator __s, const char* __nb, const char* __ne) const + { + result __r = ok; + mbstate_t __mb; + while (__nb < __ne && __r != error) + { + const int __sz = 32; + char16_t __buf[__sz]; + char16_t* __bn; + const char* __nn = __nb; + __r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb+__sz : __ne, __nn, + __buf, __buf+__sz, __bn); + if (__r == codecvt_base::error || __nn == __nb) + __throw_runtime_error("locale not supported"); + for (const char16_t* __p = __buf; __p < __bn; ++__p, ++__s) + *__s = (wchar_t)*__p; + __nb = __nn; + } + return __s; + } +}; + +template <> +struct __widen_from_utf8<32> + : public codecvt +{ + _LIBCPP_ALWAYS_INLINE + __widen_from_utf8() : codecvt(1) {} + + ~__widen_from_utf8(); + + template + _LIBCPP_ALWAYS_INLINE + _OutputIterator + operator()(_OutputIterator __s, const char* __nb, const char* __ne) const + { + result __r = ok; + mbstate_t __mb; + while (__nb < __ne && __r != error) + { + const int __sz = 32; + char32_t __buf[__sz]; + char32_t* __bn; + const char* __nn = __nb; + __r = do_in(__mb, __nb, __ne - __nb > __sz ? __nb+__sz : __ne, __nn, + __buf, __buf+__sz, __bn); + if (__r == codecvt_base::error || __nn == __nb) + __throw_runtime_error("locale not supported"); + for (const char32_t* __p = __buf; __p < __bn; ++__p, ++__s) + *__s = (wchar_t)*__p; + __nb = __nn; + } + return __s; + } +}; + +// template class numpunct + +template class _LIBCPP_TYPE_VIS_ONLY numpunct; + +template <> +class _LIBCPP_TYPE_VIS numpunct + : public locale::facet +{ +public: + typedef char char_type; + typedef basic_string string_type; + + explicit numpunct(size_t __refs = 0); + + _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} + _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();} + _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();} + + static locale::id id; + +protected: + ~numpunct(); + virtual char_type do_decimal_point() const; + virtual char_type do_thousands_sep() const; + virtual string do_grouping() const; + virtual string_type do_truename() const; + virtual string_type do_falsename() const; + + char_type __decimal_point_; + char_type __thousands_sep_; + string __grouping_; +}; + +template <> +class _LIBCPP_TYPE_VIS numpunct + : public locale::facet +{ +public: + typedef wchar_t char_type; + typedef basic_string string_type; + + explicit numpunct(size_t __refs = 0); + + _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} + _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();} + _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();} + + static locale::id id; + +protected: + ~numpunct(); + virtual char_type do_decimal_point() const; + virtual char_type do_thousands_sep() const; + virtual string do_grouping() const; + virtual string_type do_truename() const; + virtual string_type do_falsename() const; + + char_type __decimal_point_; + char_type __thousands_sep_; + string __grouping_; +}; + +// template class numpunct_byname + +template class _LIBCPP_TYPE_VIS_ONLY numpunct_byname; + +template <> +class _LIBCPP_TYPE_VIS numpunct_byname +: public numpunct +{ +public: + typedef char char_type; + typedef basic_string string_type; + + explicit numpunct_byname(const char* __nm, size_t __refs = 0); + explicit numpunct_byname(const string& __nm, size_t __refs = 0); + +protected: + ~numpunct_byname(); + +private: + void __init(const char*); +}; + +template <> +class _LIBCPP_TYPE_VIS numpunct_byname +: public numpunct +{ +public: + typedef wchar_t char_type; + typedef basic_string string_type; + + explicit numpunct_byname(const char* __nm, size_t __refs = 0); + explicit numpunct_byname(const string& __nm, size_t __refs = 0); + +protected: + ~numpunct_byname(); + +private: + void __init(const char*); +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // !defined(_LIBCPP_SGX_CONFIG) + +#endif // _LIBCPP___LOCALE diff --git a/sdk/tlibcxx/include/__mutex_base b/sdk/tlibcxx/include/__mutex_base new file mode 100644 index 00000000..38a76ac6 --- /dev/null +++ b/sdk/tlibcxx/include/__mutex_base @@ -0,0 +1,438 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MUTEX_BASE +#define _LIBCPP___MUTEX_BASE + +#include <__config> +#include +#include +#include <__threading_support> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS + +#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION +# ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS +# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) +# else +# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) +# endif +#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION + +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex +{ +#ifndef _LIBCPP_HAS_NO_CONSTEXPR + __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; +#else + __libcpp_mutex_t __m_; +#endif + +public: + _LIBCPP_INLINE_VISIBILITY +#ifndef _LIBCPP_HAS_NO_CONSTEXPR + constexpr mutex() _NOEXCEPT _LIBCPP_DEFAULT +#else + mutex() _NOEXCEPT {__m_ = (__libcpp_mutex_t)_LIBCPP_MUTEX_INITIALIZER;} +#endif + ~mutex(); + +private: + mutex(const mutex&);// = delete; + mutex& operator=(const mutex&);// = delete; + +public: + void lock() _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability()); + bool try_lock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(try_acquire_capability(true)); + void unlock() _NOEXCEPT _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()); + + typedef __libcpp_mutex_t* native_handle_type; + _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} +}; + +struct _LIBCPP_TYPE_VIS defer_lock_t {}; +struct _LIBCPP_TYPE_VIS try_to_lock_t {}; +struct _LIBCPP_TYPE_VIS adopt_lock_t {}; + +#if defined(_LIBCPP_HAS_NO_CONSTEXPR) || defined(_LIBCPP_BUILDING_MUTEX) + +extern const defer_lock_t defer_lock; +extern const try_to_lock_t try_to_lock; +extern const adopt_lock_t adopt_lock; + +#else + +constexpr defer_lock_t defer_lock = defer_lock_t(); +constexpr try_to_lock_t try_to_lock = try_to_lock_t(); +constexpr adopt_lock_t adopt_lock = adopt_lock_t(); + +#endif + + +// Forward declare lock_guard as a variadic template even in C++03 to keep +// the mangling consistent between dialects. +#if defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) +template +class _LIBCPP_TYPE_VIS_ONLY lock_guard; +#endif + +template +class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable) +#if !defined(_LIBCPP_ABI_VARIADIC_LOCK_GUARD) +lock_guard +#else +lock_guard<_Mutex> +#endif +{ +public: + typedef _Mutex mutex_type; + +private: + mutex_type& __m_; +public: + + _LIBCPP_INLINE_VISIBILITY + explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_SAFETY_ANNOTATION(acquire_capability(__m)) + : __m_(__m) {__m_.lock();} + _LIBCPP_INLINE_VISIBILITY + lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_SAFETY_ANNOTATION(requires_capability(__m)) + : __m_(__m) {} + _LIBCPP_INLINE_VISIBILITY + ~lock_guard() _LIBCPP_THREAD_SAFETY_ANNOTATION(release_capability()) {__m_.unlock();} + +private: + lock_guard(lock_guard const&) _LIBCPP_EQUAL_DELETE; + lock_guard& operator=(lock_guard const&) _LIBCPP_EQUAL_DELETE; +}; + +template +class _LIBCPP_TYPE_VIS_ONLY unique_lock +{ +public: + typedef _Mutex mutex_type; + +private: + mutex_type* __m_; + bool __owns_; + +public: + _LIBCPP_INLINE_VISIBILITY + unique_lock() _NOEXCEPT : __m_(nullptr), __owns_(false) {} + _LIBCPP_INLINE_VISIBILITY + explicit unique_lock(mutex_type& __m) + : __m_(_VSTD::addressof(__m)), __owns_(true) {__m_->lock();} + _LIBCPP_INLINE_VISIBILITY + unique_lock(mutex_type& __m, defer_lock_t) _NOEXCEPT + : __m_(_VSTD::addressof(__m)), __owns_(false) {} + _LIBCPP_INLINE_VISIBILITY + unique_lock(mutex_type& __m, try_to_lock_t) + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock()) {} + _LIBCPP_INLINE_VISIBILITY + unique_lock(mutex_type& __m, adopt_lock_t) + : __m_(_VSTD::addressof(__m)), __owns_(true) {} + template + _LIBCPP_INLINE_VISIBILITY + unique_lock(mutex_type& __m, const chrono::time_point<_Clock, _Duration>& __t) + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_until(__t)) {} + template + _LIBCPP_INLINE_VISIBILITY + unique_lock(mutex_type& __m, const chrono::duration<_Rep, _Period>& __d) + : __m_(_VSTD::addressof(__m)), __owns_(__m.try_lock_for(__d)) {} + _LIBCPP_INLINE_VISIBILITY + ~unique_lock() + { + if (__owns_) + __m_->unlock(); + } + +private: + unique_lock(unique_lock const&); // = delete; + unique_lock& operator=(unique_lock const&); // = delete; + +public: +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + _LIBCPP_INLINE_VISIBILITY + unique_lock(unique_lock&& __u) _NOEXCEPT + : __m_(__u.__m_), __owns_(__u.__owns_) + {__u.__m_ = nullptr; __u.__owns_ = false;} + _LIBCPP_INLINE_VISIBILITY + unique_lock& operator=(unique_lock&& __u) _NOEXCEPT + { + if (__owns_) + __m_->unlock(); + __m_ = __u.__m_; + __owns_ = __u.__owns_; + __u.__m_ = nullptr; + __u.__owns_ = false; + return *this; + } + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + + void lock(); + bool try_lock(); + + template + bool try_lock_for(const chrono::duration<_Rep, _Period>& __d); + template + bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); + + void unlock(); + + _LIBCPP_INLINE_VISIBILITY + void swap(unique_lock& __u) _NOEXCEPT + { + _VSTD::swap(__m_, __u.__m_); + _VSTD::swap(__owns_, __u.__owns_); + } + _LIBCPP_INLINE_VISIBILITY + mutex_type* release() _NOEXCEPT + { + mutex_type* __m = __m_; + __m_ = nullptr; + __owns_ = false; + return __m; + } + + _LIBCPP_INLINE_VISIBILITY + bool owns_lock() const _NOEXCEPT {return __owns_;} + _LIBCPP_INLINE_VISIBILITY + _LIBCPP_EXPLICIT + operator bool () const _NOEXCEPT {return __owns_;} + _LIBCPP_INLINE_VISIBILITY + mutex_type* mutex() const _NOEXCEPT {return __m_;} +}; + +template +void +unique_lock<_Mutex>::lock() +{ + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::lock: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::lock: already locked"); + __m_->lock(); + __owns_ = true; +} + +template +bool +unique_lock<_Mutex>::try_lock() +{ + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock: already locked"); + __owns_ = __m_->try_lock(); + return __owns_; +} + +template +template +bool +unique_lock<_Mutex>::try_lock_for(const chrono::duration<_Rep, _Period>& __d) +{ + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock_for: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock_for: already locked"); + __owns_ = __m_->try_lock_for(__d); + return __owns_; +} + +template +template +bool +unique_lock<_Mutex>::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) +{ + if (__m_ == nullptr) + __throw_system_error(EPERM, "unique_lock::try_lock_until: references null mutex"); + if (__owns_) + __throw_system_error(EDEADLK, "unique_lock::try_lock_until: already locked"); + __owns_ = __m_->try_lock_until(__t); + return __owns_; +} + +template +void +unique_lock<_Mutex>::unlock() +{ + if (!__owns_) + __throw_system_error(EPERM, "unique_lock::unlock: not locked"); + __m_->unlock(); + __owns_ = false; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) _NOEXCEPT + {__x.swap(__y);} + +//enum class cv_status +_LIBCPP_DECLARE_STRONG_ENUM(cv_status) +{ + no_timeout, + timeout +}; +_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) + +class _LIBCPP_TYPE_VIS condition_variable +{ +#ifndef _LIBCPP_HAS_NO_CONSTEXPR + __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; +#else + __libcpp_condvar_t __cv_; +#endif + +public: + _LIBCPP_INLINE_VISIBILITY +#ifndef _LIBCPP_HAS_NO_CONSTEXPR + constexpr condition_variable() _NOEXCEPT _LIBCPP_DEFAULT +#else + condition_variable() _NOEXCEPT {__cv_ = (__libcpp_condvar_t)_LIBCPP_CONDVAR_INITIALIZER;} +#endif + ~condition_variable(); + +private: + condition_variable(const condition_variable&); // = delete; + condition_variable& operator=(const condition_variable&); // = delete; + +public: + void notify_one() _NOEXCEPT; + void notify_all() _NOEXCEPT; + + void wait(unique_lock& __lk) _NOEXCEPT; + template + void wait(unique_lock& __lk, _Predicate __pred); + + template + cv_status + wait_until(unique_lock& __lk, + const chrono::time_point<_Clock, _Duration>& __t); + + template + bool + wait_until(unique_lock& __lk, + const chrono::time_point<_Clock, _Duration>& __t, + _Predicate __pred); + + template + cv_status + wait_for(unique_lock& __lk, + const chrono::duration<_Rep, _Period>& __d); + + template + bool + _LIBCPP_INLINE_VISIBILITY + wait_for(unique_lock& __lk, + const chrono::duration<_Rep, _Period>& __d, + _Predicate __pred); + + typedef __libcpp_condvar_t* native_handle_type; + _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__cv_;} + +private: + void __do_timed_wait(unique_lock& __lk, + chrono::time_point) _NOEXCEPT; +}; +#endif // !_LIBCPP_HAS_NO_THREADS + +template +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if +< + chrono::__is_duration<_To>::value, + _To +>::type +__ceil(chrono::duration<_Rep, _Period> __d) +{ + using namespace chrono; + _To __r = duration_cast<_To>(__d); + if (__r < __d) + ++__r; + return __r; +} + +#ifndef _LIBCPP_HAS_NO_THREADS +template +void +condition_variable::wait(unique_lock& __lk, _Predicate __pred) +{ + while (!__pred()) + wait(__lk); +} + +template +cv_status +condition_variable::wait_until(unique_lock& __lk, + const chrono::time_point<_Clock, _Duration>& __t) +{ + using namespace chrono; + wait_for(__lk, __t - _Clock::now()); + return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; +} + +template +bool +condition_variable::wait_until(unique_lock& __lk, + const chrono::time_point<_Clock, _Duration>& __t, + _Predicate __pred) +{ + while (!__pred()) + { + if (wait_until(__lk, __t) == cv_status::timeout) + return __pred(); + } + return true; +} + +template +cv_status +condition_variable::wait_for(unique_lock& __lk, + const chrono::duration<_Rep, _Period>& __d) +{ + using namespace chrono; + if (__d <= __d.zero()) + return cv_status::timeout; + typedef time_point > __sys_tpf; + typedef time_point __sys_tpi; + __sys_tpf _Max = __sys_tpi::max(); + system_clock::time_point __s_now = system_clock::now(); + steady_clock::time_point __c_now = steady_clock::now(); + if (_Max - __d > __s_now) + __do_timed_wait(__lk, __s_now + __ceil(__d)); + else + __do_timed_wait(__lk, __sys_tpi::max()); + return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : + cv_status::timeout; +} + +template +inline +bool +condition_variable::wait_for(unique_lock& __lk, + const chrono::duration<_Rep, _Period>& __d, + _Predicate __pred) +{ + return wait_until(__lk, chrono::steady_clock::now() + __d, + _VSTD::move(__pred)); +} + +#endif // !_LIBCPP_HAS_NO_THREADS + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MUTEX_BASE diff --git a/sdk/tlibcxx/include/__nullptr b/sdk/tlibcxx/include/__nullptr new file mode 100644 index 00000000..95415a63 --- /dev/null +++ b/sdk/tlibcxx/include/__nullptr @@ -0,0 +1,66 @@ +// -*- C++ -*- +//===--------------------------- __nullptr --------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_NULLPTR +#define _LIBCPP_NULLPTR + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#ifdef _LIBCPP_HAS_NO_NULLPTR + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_TYPE_VIS_ONLY nullptr_t +{ + void* __lx; + + struct __nat {int __for_bool_;}; + + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {} + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {} + + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;} + + template + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR + operator _Tp* () const {return 0;} + + template + _LIBCPP_ALWAYS_INLINE + operator _Tp _Up::* () const {return 0;} + + friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;} + friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;} + friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator<(nullptr_t, nullptr_t) {return false;} + friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator<=(nullptr_t, nullptr_t) {return true;} + friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator>(nullptr_t, nullptr_t) {return false;} + friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator>=(nullptr_t, nullptr_t) {return true;} +}; + +inline _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);} + +#define nullptr _VSTD::__get_nullptr_t() + +_LIBCPP_END_NAMESPACE_STD + +#else // _LIBCPP_HAS_NO_NULLPTR + +namespace std +{ + typedef decltype(nullptr) nullptr_t; +} + +#endif // _LIBCPP_HAS_NO_NULLPTR + +#endif // _LIBCPP_NULLPTR diff --git a/sdk/tlibcxx/include/__refstring b/sdk/tlibcxx/include/__refstring new file mode 100644 index 00000000..61ccc751 --- /dev/null +++ b/sdk/tlibcxx/include/__refstring @@ -0,0 +1,139 @@ +//===------------------------ __refstring ---------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___REFSTRING +#define _LIBCPP___REFSTRING + +#include <__config> +#include +#include +#ifdef __APPLE__ +#include +#include +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_HIDDEN __libcpp_refstring +{ +private: + const char* str_; + + typedef int count_t; + + struct _Rep_base + { + std::size_t len; + std::size_t cap; + count_t count; + }; + + static + _Rep_base* + rep_from_data(const char *data_) _NOEXCEPT + { + char *data = const_cast(data_); + return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); + } + static + char * + data_from_rep(_Rep_base *rep) _NOEXCEPT + { + char *data = reinterpret_cast(rep); + return data + sizeof(*rep); + } + +#ifdef __APPLE__ + static + const char* + compute_gcc_empty_string_storage() _NOEXCEPT + { + void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); + if (handle == nullptr) + return nullptr; + void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); + if (sym == nullptr) + return nullptr; + return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); + } + + static + const char* + get_gcc_empty_string_storage() _NOEXCEPT + { + static const char* p = compute_gcc_empty_string_storage(); + return p; + } + + bool + uses_refcount() const + { + return str_ != get_gcc_empty_string_storage(); + } +#else + bool + uses_refcount() const + { + return true; + } +#endif + +public: + explicit __libcpp_refstring(const char* msg) { + std::size_t len = strlen(msg); + _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); + rep->len = len; + rep->cap = len; + rep->count = 0; + char *data = data_from_rep(rep); + std::memcpy(data, msg, len + 1); + str_ = data; + } + + __libcpp_refstring(const __libcpp_refstring& s) _NOEXCEPT : str_(s.str_) + { + if (uses_refcount()) + __sync_add_and_fetch(&rep_from_data(str_)->count, 1); + } + + __libcpp_refstring& operator=(const __libcpp_refstring& s) _NOEXCEPT + { + bool adjust_old_count = uses_refcount(); + struct _Rep_base *old_rep = rep_from_data(str_); + str_ = s.str_; + if (uses_refcount()) + __sync_add_and_fetch(&rep_from_data(str_)->count, 1); + if (adjust_old_count) + { + if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0) + { + ::operator delete(old_rep); + } + } + return *this; + } + + ~__libcpp_refstring() + { + if (uses_refcount()) + { + _Rep_base* rep = rep_from_data(str_); + if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) + { + ::operator delete(rep); + } + } + } + + const char* c_str() const _NOEXCEPT {return str_;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPP___REFSTRING diff --git a/sdk/tlibcxx/include/__sgx b/sdk/tlibcxx/include/__sgx new file mode 100644 index 00000000..87287cd8 --- /dev/null +++ b/sdk/tlibcxx/include/__sgx @@ -0,0 +1,310 @@ +/** + * + * INTEL CONFIDENTIAL + * Copyright(c) 2011-2016 Intel Corporation All Rights Reserved. + * + * The source code contained or described herein and all documents related to + * the source code ("Material") are owned by Intel Corporation or its suppliers + * or licensors. Title to the Material remains with Intel Corporation or its + * suppliers and licensors. The Material contains trade secrets and proprietary + * and confidential information of Intel or its suppliers and licensors. The + * Material is protected by worldwide copyright and trade secret laws and treaty + * provisions. No part of the Material may be used, copied, reproduced, modified, + * published, uploaded, posted, transmitted, distributed, or disclosed in any + * way without Intel's prior express written permission. + * + * No license under any patent, copyright, trade secret or other intellectual + * property right is granted to or conferred upon you by disclosure or delivery + * of the Materials, either expressly, by implication, inducement, estoppel or + * otherwise. Any license under such intellectual property rights must be + * express and approved by Intel(R) in writing. + * + */ + +#ifndef __LIBCPP_SGX +#define __LIBCPP_SGX + + +// Note: ICC16 compiler predefines the following (which are usually defined by VS compiler) +// _WIN32 +// _MSC_VER && _MSC_VER >= 1400 + +// Note: The following defines will have different meaning +// _LIBCPP_MSVC - Using ICC 16 C++ compiler +// _LIBCPP_MSVCRT - Using SGX cpprt runtime library + +/* + * libc++ configuration file specific to SGX SDK + * It is internal libc++ header - DO NOT include it directly + */ + +#ifndef UNREFERENCED_PARAMETER +# define UNREFERENCED_PARAMETER(P) (P) +#endif //UNREFERENCED_PARAMETER + +// SECTION 1: NEW DEFINES SPECIFIC TO SGX + +#define _LIBCPP_SGX_CONFIG + +/* No I/O operations that involve OCALLs allowed */ +#define _LIBCPP_SGX_NO_IOSTREAMS + +// Intel Compiler +#define _LIBCPP_ICC + +// Define to replace usage of __cplusplus +// The compiler sets this to latest standard it supports although we want code using +// this to conform to C++11 not C++14 or later. +// More specific we should not compile code under __cplusplus > 201103L. +// Code under __cplusplus >= 201103L is fine. +#define sgx__cplusplus 201103L +// We need to make sure that where __cplusplus is used in defines it always goes to path for +// #define __cplusplus 201103L because it might be defined to something higher. + +// Set SGX platform specifics +#if defined(__INTEL_COMPILER) || defined(_MSC_VER) //compile with ICC or VS +# if defined _M_IX86 +# define _LIBCPP_SGX_I386 _M_IX86 +# endif +# if defined _M_X64 +# define _LIBCPP_SGX_X86_64 _M_X64 +# endif +#endif + +// This is defined in case MS VS compiler has been detected +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +# define _LIBCPP_SGX_MSVS_COMPILER +#endif //_MSC_VER + +// Set SGX specific endianess below +#include +#ifdef _LIBCPP_LITTLE_ENDIAN +#undef _LIBCPP_LITTLE_ENDIAN +#endif // _LIBCPP_LITTLE_ENDIAN +#ifdef _LIBCPP_BIG_ENDIAN +#undef _LIBCPP_BIG_ENDIAN +#endif //_LIBCPP_BIG_ENDIAN +#if _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 1 +# define _LIBCPP_BIG_ENDIAN 0 +#else // _BYTE_ORDER == _LITTLE_ENDIAN +# define _LIBCPP_LITTLE_ENDIAN 0 +# define _LIBCPP_BIG_ENDIAN 1 +#endif // _BYTE_ORDER == _LITTLE_ENDIAN + +// Use sgx assert +#include +#if defined(_LIBCPP_ASSERT) +#undef _LIBCPP_ASSERT +#endif // _LIBCPP_ASSERT +#define _LIBCPP_ASSERT(x, m) (assert(x)) + +// RTTI comes from cpprt. Undefine NO_RTTI +#if defined(_LIBCPP_NO_RTTI) +#undef _LIBCPP_NO_RTTI +#endif // _LIBCPP_NO_RTTI + +// SECTION 2: DISABLE CLANG'S BUILTINs BELOW + +/* Disable clang's builtins because ICC16 doesn't support them */ +#if defined(__has_attribute) +#undef __has_attribute +#endif +#define __has_attribute(__x) 0 + +#if defined(__has_builtin) +#undef __has_builtin +#endif +#define __has_builtin(__x) 0 + +#if defined(__has_extension) +#undef __has_extension +#endif +#define __has_extension(__x) 0 + +#if defined(__has_feature) +#undef __has_feature +#endif +#define __has_feature(x) 0 + +#if defined(__is_identifier) +#undef __is_identifier +#endif +#define __is_identifier(__x) 1 + +// Platform specific? +GCC_MESSAGE("Platform check") + +#if defined(_MSC_VER) +GCC_MESSAGE("_MSC_VER defined") + +///////////// +// SECTION 3: UNDEF VARIOUS LIBC++ DEFINES FOR SUPPORTED FEATURES +///////////// +#undef _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#undef _LIBCPP_HAS_NO_CONSTEXPR +#undef _LIBCPP_HAS_NO_UNICODE_CHARS +#undef _LIBCPP_HAS_NO_DELETED_FUNCTIONS +#undef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#undef _LIBCPP_HAS_NO_VARIADICS +#undef _LIBCPP_HAS_NO_ADVANCED_SFINAE +#undef _LIBCPP_HAS_NO_VARIABLE_TEMPLATES +#undef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS +#undef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#undef _LIBCPP_HAS_QUICK_EXIT +#undef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS +#undef _LIBCPP_NO_EXCEPTIONS + +#undef _LIBCPP_DEBUG + +#undef _LIBCPP_USING_WIN32_RANDOM // WIN32 +#define _LIBCPP_USING_SGX_RANDOM + +// Current goal is to support C++11 so define the version accordingly. +// Libc++ also supports 14 and beyond. +#define _LIBCPP_STD_VER 11 + +///////////// +// SECTION 4: DEFINE VARIOUS LIBC++ DEFINES TO CUSTOMIZE USAGE FOR SGX AND ICC16 +///////////// +#define _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE + +#define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#define _LIBCPP_HAS_NO_CXX14_CONSTEXPR + +#define __alignof__ __alignof +#define _LIBCPP_NORETURN __declspec(noreturn) +#define _ALIGNAS_TYPE(x) alignas(x) +#define _ALIGNAS(x) __declspec(align(x)) +#define _LIBCPP_UNUSED + +#define _LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T) +#define _LIBCPP_IS_LITERAL(T) __is_literal_type(T) + +#define _LIBCPP_HAS_IS_FINAL +#define _LIBCPP_HAS_NO_THREADS +#define _LIBCPP_HAS_NO_STDIN +#define _LIBCPP_HAS_NO_STDOUT +#define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE + +#define _LIBCPP_BUILDING_SYSTEM_ERROR + +#define _NOEXCEPT noexcept +#define _NOEXCEPT_(x) noexcept(x) +#define _NOEXCEPT_OR_FALSE(x) noexcept(x) + +#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std { +#define _LIBCPP_END_NAMESPACE_STD } +#define _VSTD std + +# define _LIBCPP_WEAK +namespace std { +} + +#define _LIBCPP_HAS_NO_ASAN + +#if defined _LIBCPP_SGX_I386 +# define __SIZEOF_SIZE_T__ 4 +#elif defined _LIBCPP_SGX_X86_64 +# define __SIZEOF_SIZE_T__ 8 +#endif + +#undef _LIBCPP_SGX_HAS_NO_THREADS +#undef _LIBCPP_SGX_HAS_NO_ATOMIC + +///////////// +// SECTION 5: SGX specific defines which replace __has_feature(cxx_something) +///////////// +// All below are supported by Intel Compiler in SGX +#define _LIBCPP_SGX_HAS_CXX_NOEXCEPT // __has_feature(cxx_noexcept) +#define _LIBCPP_SGX_HAS_TRAIT_IS_UNION // __has_feature(is_union) +#define _LIBCPP_SGX_HAS_TRAIT_IS_CLASS // __has_feature(is_class) +#define _LIBCPP_SGX_HAS_TRAIT_IS_ENUM //__has_feature(is_enum) +#define _LIBCPP_SGX_HAS_TRAIT_IS_CONVERTIBLE_TO // __has_feature(is_convertible_to) +#define _LIBCPP_SGX_HAS_TRAIT_IS_EMPTY __has_feature(is_empty) +#define _LIBCPP_SGX_HAS_TRAIT_IS_POLYMORPHIC //__has_feature(is_polymorphic) +#define _LIBCPP_SGX_HAS_TRAIT_IS_TRIVIAL // __has_feature(__is_trivial) +#define _LIBCPP_SGX_HAS_TRAIT_HAS_VIRTUAL_DESTRUCTOR //__has_feature(has_virtual_destructor) +#define _LIBCPP_SGX_HAS_TRAIT_IS_TRIVIALLY_COPYABLE // __has_feature(is_trivially_copyable) +#define _LIBCPP_SGX_HAS_TRAIT_IS_TRIVIALLY_CONSTRUCTIBLE //__has_feature(is_trivially_constructible) +#define _LIBCPP_SGX_HAS_TRAIT_HAS_TRIVIAL_CONSTRUCTOR //__has_feature(has_trivial_constructor) +#define _LIBCPP_SGX_HAS_TRAIT_IS_TRIVIALLY_ASSIGNABLE // __has_feature(is_trivially_assignable) +#define _LIBCPP_SGX_HAS_TRAIT_HAS_TRIVIAL_DESTRUCTOR //__has_feature(has_trivial_destructor) +#define _LIBCPP_SGX_HAS_TRAIT_IS_DESTRUCTIBLE +#define _LIBCPP_SGX_HAS_TRAIT_IS_CONSTRUCTIBLE // __has_feature(is_constructible) +#define _LIBCPP_SGX_HAS_TRAIT_IS_NOTHROW_CONSTRUCTIBLE // __has_feature(is_nothrow_constructible) +#define _LIBCPP_SGX_HAS_TRAIT_HAS_NOTHROW_CONSTRUCTOR //__has_feature(has_nothrow_constructor) +#define _LIBCPP_SGX_HAS_TRAIT_HAS_NOTHROW_COPY //__has_feature(has_nothrow_copy) +#define _LIBCPP_SGX_HAS_TRAIT_HAS_NOTHROW_ASSIGN //__has_feature(has_nothrow_assign) +#define _LIBCPP_SGX_HAS_TRAIT_IS_POD //__has_feature(is_pod) +#define _LIBCPP_SGX_HAS_TRAIT_IS_STANDARD_LAYOUT //__has_feature(is_standard_layout) +#define _LIBCPP_SGX_HAS_CXX_REFERENCE_QUALIFIED_FUNCTIONS //__has_feature(cxx_reference_qualified_functions) +#define _LIBCPP_SGX_HAS_CXX_ATOMIC //__has_feature(cxx_atomic) +#define _LIBCPP_SGX_HAS_CXX_STRONG_ENUMS //__has_feature(cxx_strong_enums) +#define _LIBCPP_SGX_HAS_CXX_ACCESS_CONTROL_SFINAE //__has_feature(cxx_access_control_sfinae) +#undef _LIBCPP_SGX_HAS_CXX_UNRESTRICTED_UNIONS // __has_feature(cxx_unrestricted_unions) + +#elif defined(__GNUC__) +GCC_MESSAGE("__GNUC__ defined") + +///////////// +// SECTION 3: UNDEF VARIOUS LIBC++ DEFINES FOR SUPPORTED FEATURES +///////////// +#undef _LIBCPP_USING_DEV_RANDOM +#define _LIBCPP_USING_SGX_RANDOM +#undef _LIBCPP_NO_EXCEPTIONS +#undef _LIBCPP_HAS_NO_TEMPLATE_ALIASES +#undef _LIBCPP_HAS_NO_CONSTEXPR +#undef _LIBCPP_HAS_NO_UNICODE_CHARS +#undef _LIBCPP_HAS_NO_DELETED_FUNCTIONS +#undef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS +#undef _LIBCPP_HAS_NO_VARIADICS +#undef _LIBCPP_HAS_NO_ADVANCED_SFINAE +#undef _LIBCPP_HAS_NO_VARIABLE_TEMPLATES // Will be set +#undef _LIBCPP_HAS_NO_RVALUE_REFERENCES +#undef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS + +//#undef _LIBCPP_DEBUG // TBD. Debug without I/O? +#undef _LIBCPP_HAS_QUICK_EXIT +#undef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS // Not used + +// Current goal is to support C++11 so define the version accordingly. +// Libc++ also supports 14 and beyond. +#define _LIBCPP_STD_VER 11 + +///////////// +// SECTION 4: DEFINE VARIOUS LIBC++ DEFINES TO CUSTOMIZE USAGE FOR SGX +///////////// +//#define _LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE +//#define __alignof__ __alignof + +//#define _LIBCPP_UNDERLYING_TYPE(T) __underlying_type(T) +//#define _LIBCPP_IS_LITERAL(T) __is_literal_type(T) +//#define _LIBCPP_HAS_IS_FINAL + +#define _LIBCPP_HAS_NO_THREADS +#define _LIBCPP_HAS_NO_STDIN +#define _LIBCPP_HAS_NO_STDOUT +#define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE + +//#define _LIBCPP_BUILDING_SYSTEM_ERROR + + +//#if defined _LIBCPP_SGX_I386 +//# define __SIZEOF_SIZE_T__ 4 +//#elif defined _LIBCPP_SGX_X86_64 +//# define __SIZEOF_SIZE_T__ 8 +//#endif + +#undef _LIBCPP_SGX_HAS_NO_THREADS +#undef _LIBCPP_SGX_HAS_NO_ATOMIC + +///////////// +// SECTION 5: SGX specific defines which replace __has_feature(cxx_something) +///////////// + +#else +GCC_MESSAGE("Unsupported platform") +#endif + +#endif // _LIBCPP_SGX diff --git a/sdk/tlibcxx/include/__split_buffer b/sdk/tlibcxx/include/__split_buffer new file mode 100644 index 00000000..79d1aa1d --- /dev/null +++ b/sdk/tlibcxx/include/__split_buffer @@ -0,0 +1,640 @@ +// -*- C++ -*- +#ifndef _LIBCPP_SPLIT_BUFFER +#define _LIBCPP_SPLIT_BUFFER + +#include <__config> +#include +#include + +#include <__undef_min_max> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class __split_buffer_common +{ +protected: + void __throw_length_error() const; + void __throw_out_of_range() const; +}; + +template > +struct __split_buffer + : private __split_buffer_common +{ +private: + __split_buffer(const __split_buffer&); + __split_buffer& operator=(const __split_buffer&); +public: + typedef _Tp value_type; + typedef _Allocator allocator_type; + typedef typename remove_reference::type __alloc_rr; + typedef allocator_traits<__alloc_rr> __alloc_traits; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef typename __alloc_traits::size_type size_type; + typedef typename __alloc_traits::difference_type difference_type; + typedef typename __alloc_traits::pointer pointer; + typedef typename __alloc_traits::const_pointer const_pointer; + typedef pointer iterator; + typedef const_pointer const_iterator; + + pointer __first_; + pointer __begin_; + pointer __end_; + __compressed_pair __end_cap_; + + typedef typename add_lvalue_reference::type __alloc_ref; + typedef typename add_lvalue_reference::type __alloc_const_ref; + + _LIBCPP_INLINE_VISIBILITY __alloc_rr& __alloc() _NOEXCEPT {return __end_cap_.second();} + _LIBCPP_INLINE_VISIBILITY const __alloc_rr& __alloc() const _NOEXCEPT {return __end_cap_.second();} + _LIBCPP_INLINE_VISIBILITY pointer& __end_cap() _NOEXCEPT {return __end_cap_.first();} + _LIBCPP_INLINE_VISIBILITY const pointer& __end_cap() const _NOEXCEPT {return __end_cap_.first();} + + _LIBCPP_INLINE_VISIBILITY + __split_buffer() + _NOEXCEPT_(is_nothrow_default_constructible::value); + _LIBCPP_INLINE_VISIBILITY + explicit __split_buffer(__alloc_rr& __a); + _LIBCPP_INLINE_VISIBILITY + explicit __split_buffer(const __alloc_rr& __a); + __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a); + ~__split_buffer(); + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + __split_buffer(__split_buffer&& __c) + _NOEXCEPT_(is_nothrow_move_constructible::value); + __split_buffer(__split_buffer&& __c, const __alloc_rr& __a); + __split_buffer& operator=(__split_buffer&& __c) + _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable::value) || + !__alloc_traits::propagate_on_container_move_assignment::value); +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + + _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return __begin_;} + _LIBCPP_INLINE_VISIBILITY const_iterator begin() const _NOEXCEPT {return __begin_;} + _LIBCPP_INLINE_VISIBILITY iterator end() _NOEXCEPT {return __end_;} + _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return __end_;} + + _LIBCPP_INLINE_VISIBILITY + void clear() _NOEXCEPT + {__destruct_at_end(__begin_);} + _LIBCPP_INLINE_VISIBILITY size_type size() const {return static_cast(__end_ - __begin_);} + _LIBCPP_INLINE_VISIBILITY bool empty() const {return __end_ == __begin_;} + _LIBCPP_INLINE_VISIBILITY size_type capacity() const {return static_cast(__end_cap() - __first_);} + _LIBCPP_INLINE_VISIBILITY size_type __front_spare() const {return static_cast(__begin_ - __first_);} + _LIBCPP_INLINE_VISIBILITY size_type __back_spare() const {return static_cast(__end_cap() - __end_);} + + _LIBCPP_INLINE_VISIBILITY reference front() {return *__begin_;} + _LIBCPP_INLINE_VISIBILITY const_reference front() const {return *__begin_;} + _LIBCPP_INLINE_VISIBILITY reference back() {return *(__end_ - 1);} + _LIBCPP_INLINE_VISIBILITY const_reference back() const {return *(__end_ - 1);} + + void reserve(size_type __n); + void shrink_to_fit() _NOEXCEPT; + void push_front(const_reference __x); + _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x); +#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) + void push_front(value_type&& __x); + void push_back(value_type&& __x); +#if !defined(_LIBCPP_HAS_NO_VARIADICS) + template + void emplace_back(_Args&&... __args); +#endif // !defined(_LIBCPP_HAS_NO_VARIADICS) +#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) + + _LIBCPP_INLINE_VISIBILITY void pop_front() {__destruct_at_begin(__begin_+1);} + _LIBCPP_INLINE_VISIBILITY void pop_back() {__destruct_at_end(__end_-1);} + + void __construct_at_end(size_type __n); + void __construct_at_end(size_type __n, const_reference __x); + template + typename enable_if + < + __is_input_iterator<_InputIter>::value && + !__is_forward_iterator<_InputIter>::value, + void + >::type + __construct_at_end(_InputIter __first, _InputIter __last); + template + typename enable_if + < + __is_forward_iterator<_ForwardIterator>::value, + void + >::type + __construct_at_end(_ForwardIterator __first, _ForwardIterator __last); + + _LIBCPP_INLINE_VISIBILITY void __destruct_at_begin(pointer __new_begin) + {__destruct_at_begin(__new_begin, is_trivially_destructible());} + _LIBCPP_INLINE_VISIBILITY + void __destruct_at_begin(pointer __new_begin, false_type); + _LIBCPP_INLINE_VISIBILITY + void __destruct_at_begin(pointer __new_begin, true_type); + + _LIBCPP_INLINE_VISIBILITY + void __destruct_at_end(pointer __new_last) _NOEXCEPT + {__destruct_at_end(__new_last, false_type());} + _LIBCPP_INLINE_VISIBILITY + void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT; + + void swap(__split_buffer& __x) + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| + __is_nothrow_swappable<__alloc_rr>::value); + + bool __invariants() const; + +private: + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__split_buffer& __c, true_type) + _NOEXCEPT_(is_nothrow_move_assignable::value) + { + __alloc() = _VSTD::move(__c.__alloc()); + } + + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT + {} +}; + +template +bool +__split_buffer<_Tp, _Allocator>::__invariants() const +{ + if (__first_ == nullptr) + { + if (__begin_ != nullptr) + return false; + if (__end_ != nullptr) + return false; + if (__end_cap() != nullptr) + return false; + } + else + { + if (__begin_ < __first_) + return false; + if (__end_ < __begin_) + return false; + if (__end_cap() < __end_) + return false; + } + return true; +} + +// Default constructs __n objects starting at __end_ +// throws if construction throws +// Precondition: __n > 0 +// Precondition: size() + __n <= capacity() +// Postcondition: size() == size() + __n +template +void +__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) +{ + __alloc_rr& __a = this->__alloc(); + do + { + __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_)); + ++this->__end_; + --__n; + } while (__n > 0); +} + +// Copy constructs __n objects starting at __end_ from __x +// throws if construction throws +// Precondition: __n > 0 +// Precondition: size() + __n <= capacity() +// Postcondition: size() == old size() + __n +// Postcondition: [i] == __x for all i in [size() - __n, __n) +template +void +__split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) +{ + __alloc_rr& __a = this->__alloc(); + do + { + __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), __x); + ++this->__end_; + --__n; + } while (__n > 0); +} + +template +template +typename enable_if +< + __is_input_iterator<_InputIter>::value && + !__is_forward_iterator<_InputIter>::value, + void +>::type +__split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last) +{ + __alloc_rr& __a = this->__alloc(); + for (; __first != __last; ++__first) + { + if (__end_ == __end_cap()) + { + size_type __old_cap = __end_cap() - __first_; + size_type __new_cap = _VSTD::max(2 * __old_cap, 8); + __split_buffer __buf(__new_cap, 0, __a); + for (pointer __p = __begin_; __p != __end_; ++__p, ++__buf.__end_) + __alloc_traits::construct(__buf.__alloc(), + _VSTD::__to_raw_pointer(__buf.__end_), _VSTD::move(*__p)); + swap(__buf); + } + __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first); + ++this->__end_; + } +} + +template +template +typename enable_if +< + __is_forward_iterator<_ForwardIterator>::value, + void +>::type +__split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) +{ + __alloc_rr& __a = this->__alloc(); + for (; __first != __last; ++__first) + { + __alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first); + ++this->__end_; + } +} + +template +inline +void +__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) +{ + while (__begin_ != __new_begin) + __alloc_traits::destroy(__alloc(), __to_raw_pointer(__begin_++)); +} + +template +inline +void +__split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) +{ + __begin_ = __new_begin; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT +{ + while (__new_last != __end_) + __alloc_traits::destroy(__alloc(), __to_raw_pointer(--__end_)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +__split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT +{ + __end_ = __new_last; +} + +template +__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a) + : __end_cap_(nullptr, __a) +{ + __first_ = __cap != 0 ? __alloc_traits::allocate(__alloc(), __cap) : nullptr; + __begin_ = __end_ = __first_ + __start; + __end_cap() = __first_ + __cap; +} + +template +inline +__split_buffer<_Tp, _Allocator>::__split_buffer() + _NOEXCEPT_(is_nothrow_default_constructible::value) + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr) +{ +} + +template +inline +__split_buffer<_Tp, _Allocator>::__split_buffer(__alloc_rr& __a) + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) +{ +} + +template +inline +__split_buffer<_Tp, _Allocator>::__split_buffer(const __alloc_rr& __a) + : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) +{ +} + +template +__split_buffer<_Tp, _Allocator>::~__split_buffer() +{ + clear(); + if (__first_) + __alloc_traits::deallocate(__alloc(), __first_, capacity()); +} + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c) + _NOEXCEPT_(is_nothrow_move_constructible::value) + : __first_(_VSTD::move(__c.__first_)), + __begin_(_VSTD::move(__c.__begin_)), + __end_(_VSTD::move(__c.__end_)), + __end_cap_(_VSTD::move(__c.__end_cap_)) +{ + __c.__first_ = nullptr; + __c.__begin_ = nullptr; + __c.__end_ = nullptr; + __c.__end_cap() = nullptr; +} + +template +__split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a) + : __end_cap_(__a) +{ + if (__a == __c.__alloc()) + { + __first_ = __c.__first_; + __begin_ = __c.__begin_; + __end_ = __c.__end_; + __end_cap() = __c.__end_cap(); + __c.__first_ = nullptr; + __c.__begin_ = nullptr; + __c.__end_ = nullptr; + __c.__end_cap() = nullptr; + } + else + { + size_type __cap = __c.size(); + __first_ = __alloc_traits::allocate(__alloc(), __cap); + __begin_ = __end_ = __first_; + __end_cap() = __first_ + __cap; + typedef move_iterator _Ip; + __construct_at_end(_Ip(__c.begin()), _Ip(__c.end())); + } +} + +template +__split_buffer<_Tp, _Allocator>& +__split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c) + _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable::value) || + !__alloc_traits::propagate_on_container_move_assignment::value) +{ + clear(); + shrink_to_fit(); + __first_ = __c.__first_; + __begin_ = __c.__begin_; + __end_ = __c.__end_; + __end_cap() = __c.__end_cap(); + __move_assign_alloc(__c, + integral_constant()); + __c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr; + return *this; +} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +void +__split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x) + _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value|| + __is_nothrow_swappable<__alloc_rr>::value) +{ + _VSTD::swap(__first_, __x.__first_); + _VSTD::swap(__begin_, __x.__begin_); + _VSTD::swap(__end_, __x.__end_); + _VSTD::swap(__end_cap(), __x.__end_cap()); + __swap_allocator(__alloc(), __x.__alloc()); +} + +template +void +__split_buffer<_Tp, _Allocator>::reserve(size_type __n) +{ + if (__n < capacity()) + { + __split_buffer __t(__n, 0, __alloc()); + __t.__construct_at_end(move_iterator(__begin_), + move_iterator(__end_)); + _VSTD::swap(__first_, __t.__first_); + _VSTD::swap(__begin_, __t.__begin_); + _VSTD::swap(__end_, __t.__end_); + _VSTD::swap(__end_cap(), __t.__end_cap()); + } +} + +template +void +__split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT +{ + if (capacity() > size()) + { +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + __split_buffer __t(size(), 0, __alloc()); + __t.__construct_at_end(move_iterator(__begin_), + move_iterator(__end_)); + __t.__end_ = __t.__begin_ + (__end_ - __begin_); + _VSTD::swap(__first_, __t.__first_); + _VSTD::swap(__begin_, __t.__begin_); + _VSTD::swap(__end_, __t.__end_); + _VSTD::swap(__end_cap(), __t.__end_cap()); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCPP_NO_EXCEPTIONS + } +} + +template +void +__split_buffer<_Tp, _Allocator>::push_front(const_reference __x) +{ + if (__begin_ == __first_) + { + if (__end_ < __end_cap()) + { + difference_type __d = __end_cap() - __end_; + __d = (__d + 1) / 2; + __begin_ = _VSTD::move_backward(__begin_, __end_, __end_ + __d); + __end_ += __d; + } + else + { + size_type __c = max(2 * static_cast(__end_cap() - __first_), 1); + __split_buffer __t(__c, (__c + 3) / 4, __alloc()); + __t.__construct_at_end(move_iterator(__begin_), + move_iterator(__end_)); + _VSTD::swap(__first_, __t.__first_); + _VSTD::swap(__begin_, __t.__begin_); + _VSTD::swap(__end_, __t.__end_); + _VSTD::swap(__end_cap(), __t.__end_cap()); + } + } + __alloc_traits::construct(__alloc(), _VSTD::__to_raw_pointer(__begin_-1), __x); + --__begin_; +} + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +void +__split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) +{ + if (__begin_ == __first_) + { + if (__end_ < __end_cap()) + { + difference_type __d = __end_cap() - __end_; + __d = (__d + 1) / 2; + __begin_ = _VSTD::move_backward(__begin_, __end_, __end_ + __d); + __end_ += __d; + } + else + { + size_type __c = max(2 * static_cast(__end_cap() - __first_), 1); + __split_buffer __t(__c, (__c + 3) / 4, __alloc()); + __t.__construct_at_end(move_iterator(__begin_), + move_iterator(__end_)); + _VSTD::swap(__first_, __t.__first_); + _VSTD::swap(__begin_, __t.__begin_); + _VSTD::swap(__end_, __t.__end_); + _VSTD::swap(__end_cap(), __t.__end_cap()); + } + } + __alloc_traits::construct(__alloc(), _VSTD::__to_raw_pointer(__begin_-1), + _VSTD::move(__x)); + --__begin_; +} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +inline _LIBCPP_INLINE_VISIBILITY +void +__split_buffer<_Tp, _Allocator>::push_back(const_reference __x) +{ + if (__end_ == __end_cap()) + { + if (__begin_ > __first_) + { + difference_type __d = __begin_ - __first_; + __d = (__d + 1) / 2; + __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d); + __begin_ -= __d; + } + else + { + size_type __c = max(2 * static_cast(__end_cap() - __first_), 1); + __split_buffer __t(__c, __c / 4, __alloc()); + __t.__construct_at_end(move_iterator(__begin_), + move_iterator(__end_)); + _VSTD::swap(__first_, __t.__first_); + _VSTD::swap(__begin_, __t.__begin_); + _VSTD::swap(__end_, __t.__end_); + _VSTD::swap(__end_cap(), __t.__end_cap()); + } + } + __alloc_traits::construct(__alloc(), _VSTD::__to_raw_pointer(__end_), __x); + ++__end_; +} + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +void +__split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) +{ + if (__end_ == __end_cap()) + { + if (__begin_ > __first_) + { + difference_type __d = __begin_ - __first_; + __d = (__d + 1) / 2; + __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d); + __begin_ -= __d; + } + else + { + size_type __c = max(2 * static_cast(__end_cap() - __first_), 1); + __split_buffer __t(__c, __c / 4, __alloc()); + __t.__construct_at_end(move_iterator(__begin_), + move_iterator(__end_)); + _VSTD::swap(__first_, __t.__first_); + _VSTD::swap(__begin_, __t.__begin_); + _VSTD::swap(__end_, __t.__end_); + _VSTD::swap(__end_cap(), __t.__end_cap()); + } + } + __alloc_traits::construct(__alloc(), _VSTD::__to_raw_pointer(__end_), + _VSTD::move(__x)); + ++__end_; +} + +#ifndef _LIBCPP_HAS_NO_VARIADICS + +template +template +void +__split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) +{ + if (__end_ == __end_cap()) + { + if (__begin_ > __first_) + { + difference_type __d = __begin_ - __first_; + __d = (__d + 1) / 2; + __end_ = _VSTD::move(__begin_, __end_, __begin_ - __d); + __begin_ -= __d; + } + else + { + size_type __c = max(2 * static_cast(__end_cap() - __first_), 1); + __split_buffer __t(__c, __c / 4, __alloc()); + __t.__construct_at_end(move_iterator(__begin_), + move_iterator(__end_)); + _VSTD::swap(__first_, __t.__first_); + _VSTD::swap(__begin_, __t.__begin_); + _VSTD::swap(__end_, __t.__end_); + _VSTD::swap(__end_cap(), __t.__end_cap()); + } + } + __alloc_traits::construct(__alloc(), _VSTD::__to_raw_pointer(__end_), + _VSTD::forward<_Args>(__args)...); + ++__end_; +} + +#endif // _LIBCPP_HAS_NO_VARIADICS + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) +{ + __x.swap(__y); +} + + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_SPLIT_BUFFER diff --git a/sdk/tlibcxx/include/__sso_allocator b/sdk/tlibcxx/include/__sso_allocator new file mode 100644 index 00000000..ca3b937c --- /dev/null +++ b/sdk/tlibcxx/include/__sso_allocator @@ -0,0 +1,79 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___SSO_ALLOCATOR +#define _LIBCPP___SSO_ALLOCATOR + +#include <__config> +#include +#include + +#include <__undef___deallocate> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class _LIBCPP_HIDDEN __sso_allocator; + +template +class _LIBCPP_HIDDEN __sso_allocator +{ +public: + typedef const void* const_pointer; + typedef void value_type; +}; + +template +class _LIBCPP_HIDDEN __sso_allocator +{ + typename aligned_storage::type buf_; + bool __allocated_; +public: + typedef size_t size_type; + typedef _Tp* pointer; + typedef _Tp value_type; + + _LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {} + _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {} + template _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw() + : __allocated_(false) {} +private: + __sso_allocator& operator=(const __sso_allocator&); +public: + _LIBCPP_INLINE_VISIBILITY pointer allocate(size_type __n, typename __sso_allocator::const_pointer = 0) + { + if (!__allocated_ && __n <= _Np) + { + __allocated_ = true; + return (pointer)&buf_; + } + return static_cast(_VSTD::__allocate(__n * sizeof(_Tp))); + } + _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type) + { + if (__p == (pointer)&buf_) + __allocated_ = false; + else + _VSTD::__deallocate(__p); + } + _LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);} + + _LIBCPP_INLINE_VISIBILITY + bool operator==(__sso_allocator& __a) const {return &buf_ == &__a.buf_;} + _LIBCPP_INLINE_VISIBILITY + bool operator!=(__sso_allocator& __a) const {return &buf_ != &__a.buf_;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___SSO_ALLOCATOR diff --git a/sdk/tlibcxx/include/__std_stream b/sdk/tlibcxx/include/__std_stream new file mode 100644 index 00000000..f867cd23 --- /dev/null +++ b/sdk/tlibcxx/include/__std_stream @@ -0,0 +1,358 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___STD_STREAM +#define _LIBCPP___STD_STREAM + +#include <__config> +#include +#include +#include <__locale> +#include + +#include <__undef_min_max> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +static const int __limit = 8; + +// __stdinbuf + +template +class _LIBCPP_HIDDEN __stdinbuf + : public basic_streambuf<_CharT, char_traits<_CharT> > +{ +public: + typedef _CharT char_type; + typedef char_traits traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::pos_type pos_type; + typedef typename traits_type::off_type off_type; + typedef typename traits_type::state_type state_type; + + __stdinbuf(FILE* __fp, state_type* __st); + +protected: + virtual int_type underflow(); + virtual int_type uflow(); + virtual int_type pbackfail(int_type __c = traits_type::eof()); + virtual void imbue(const locale& __loc); + +private: + + FILE* __file_; + const codecvt* __cv_; + state_type* __st_; + int __encoding_; + int_type __last_consumed_; + bool __last_consumed_is_next_; + bool __always_noconv_; + + __stdinbuf(const __stdinbuf&); + __stdinbuf& operator=(const __stdinbuf&); + + int_type __getchar(bool __consume); +}; + +template +__stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st) + : __file_(__fp), + __st_(__st), + __last_consumed_(traits_type::eof()), + __last_consumed_is_next_(false) +{ + imbue(this->getloc()); +} + +template +void +__stdinbuf<_CharT>::imbue(const locale& __loc) +{ + __cv_ = &use_facet >(__loc); + __encoding_ = __cv_->encoding(); + __always_noconv_ = __cv_->always_noconv(); + if (__encoding_ > __limit) + __throw_runtime_error("unsupported locale for standard input"); +} + +template +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::underflow() +{ + return __getchar(false); +} + +template +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::uflow() +{ + return __getchar(true); +} + +template +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::__getchar(bool __consume) +{ + if (__last_consumed_is_next_) + { + int_type __result = __last_consumed_; + if (__consume) + { + __last_consumed_ = traits_type::eof(); + __last_consumed_is_next_ = false; + } + return __result; + } + char __extbuf[__limit]; + int __nread = _VSTD::max(1, __encoding_); + for (int __i = 0; __i < __nread; ++__i) + { + int __c = getc(__file_); + if (__c == EOF) + return traits_type::eof(); + __extbuf[__i] = static_cast(__c); + } + char_type __1buf; + if (__always_noconv_) + __1buf = static_cast(__extbuf[0]); + else + { + const char* __enxt; + char_type* __inxt; + codecvt_base::result __r; + do + { + state_type __sv_st = *__st_; + __r = __cv_->in(*__st_, __extbuf, __extbuf + __nread, __enxt, + &__1buf, &__1buf + 1, __inxt); + switch (__r) + { + case _VSTD::codecvt_base::ok: + break; + case codecvt_base::partial: + *__st_ = __sv_st; + if (__nread == sizeof(__extbuf)) + return traits_type::eof(); + { + int __c = getc(__file_); + if (__c == EOF) + return traits_type::eof(); + __extbuf[__nread] = static_cast(__c); + } + ++__nread; + break; + case codecvt_base::error: + return traits_type::eof(); + case _VSTD::codecvt_base::noconv: + __1buf = static_cast(__extbuf[0]); + break; + } + } while (__r == _VSTD::codecvt_base::partial); + } + if (!__consume) + { + for (int __i = __nread; __i > 0;) + { + if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF) + return traits_type::eof(); + } + } + else + __last_consumed_ = traits_type::to_int_type(__1buf); + return traits_type::to_int_type(__1buf); +} + +template +typename __stdinbuf<_CharT>::int_type +__stdinbuf<_CharT>::pbackfail(int_type __c) +{ + if (traits_type::eq_int_type(__c, traits_type::eof())) + { + if (!__last_consumed_is_next_) + { + __c = __last_consumed_; + __last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_, + traits_type::eof()); + } + return __c; + } + if (__last_consumed_is_next_) + { + char __extbuf[__limit]; + char* __enxt; + const char_type __ci = traits_type::to_char_type(__last_consumed_); + const char_type* __inxt; + switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt, + __extbuf, __extbuf + sizeof(__extbuf), __enxt)) + { + case _VSTD::codecvt_base::ok: + break; + case _VSTD::codecvt_base::noconv: + __extbuf[0] = static_cast(__last_consumed_); + __enxt = __extbuf + 1; + break; + case codecvt_base::partial: + case codecvt_base::error: + return traits_type::eof(); + } + while (__enxt > __extbuf) + if (ungetc(*--__enxt, __file_) == EOF) + return traits_type::eof(); + } + __last_consumed_ = __c; + __last_consumed_is_next_ = true; + return __c; +} + +// __stdoutbuf + +template +class _LIBCPP_HIDDEN __stdoutbuf + : public basic_streambuf<_CharT, char_traits<_CharT> > +{ +public: + typedef _CharT char_type; + typedef char_traits traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::pos_type pos_type; + typedef typename traits_type::off_type off_type; + typedef typename traits_type::state_type state_type; + + __stdoutbuf(FILE* __fp, state_type* __st); + +protected: + virtual int_type overflow (int_type __c = traits_type::eof()); + virtual streamsize xsputn(const char_type* __s, streamsize __n); + virtual int sync(); + virtual void imbue(const locale& __loc); + +private: + FILE* __file_; + const codecvt* __cv_; + state_type* __st_; + bool __always_noconv_; + + __stdoutbuf(const __stdoutbuf&); + __stdoutbuf& operator=(const __stdoutbuf&); +}; + +template +__stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st) + : __file_(__fp), + __cv_(&use_facet >(this->getloc())), + __st_(__st), + __always_noconv_(__cv_->always_noconv()) +{ +} + +template +typename __stdoutbuf<_CharT>::int_type +__stdoutbuf<_CharT>::overflow(int_type __c) +{ + char __extbuf[__limit]; + char_type __1buf; + if (!traits_type::eq_int_type(__c, traits_type::eof())) + { + __1buf = traits_type::to_char_type(__c); + if (__always_noconv_) + { + if (fwrite(&__1buf, sizeof(char_type), 1, __file_) != 1) + return traits_type::eof(); + } + else + { + char* __extbe = __extbuf; + codecvt_base::result __r; + char_type* pbase = &__1buf; + char_type* pptr = pbase + 1; + do + { + const char_type* __e; + __r = __cv_->out(*__st_, pbase, pptr, __e, + __extbuf, + __extbuf + sizeof(__extbuf), + __extbe); + if (__e == pbase) + return traits_type::eof(); + if (__r == codecvt_base::noconv) + { + if (fwrite(pbase, 1, 1, __file_) != 1) + return traits_type::eof(); + } + else if (__r == codecvt_base::ok || __r == codecvt_base::partial) + { + size_t __nmemb = static_cast(__extbe - __extbuf); + if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) + return traits_type::eof(); + if (__r == codecvt_base::partial) + { + pbase = (char_type*)__e; + } + } + else + return traits_type::eof(); + } while (__r == codecvt_base::partial); + } + } + return traits_type::not_eof(__c); +} + +template +streamsize +__stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n) +{ + if (__always_noconv_) + return fwrite(__s, sizeof(char_type), __n, __file_); + streamsize __i = 0; + for (; __i < __n; ++__i, ++__s) + if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof()) + break; + return __i; +} + +template +int +__stdoutbuf<_CharT>::sync() +{ + char __extbuf[__limit]; + codecvt_base::result __r; + do + { + char* __extbe; + __r = __cv_->unshift(*__st_, __extbuf, + __extbuf + sizeof(__extbuf), + __extbe); + size_t __nmemb = static_cast(__extbe - __extbuf); + if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb) + return -1; + } while (__r == codecvt_base::partial); + if (__r == codecvt_base::error) + return -1; + if (fflush(__file_)) + return -1; + return 0; +} + +template +void +__stdoutbuf<_CharT>::imbue(const locale& __loc) +{ + sync(); + __cv_ = &use_facet >(__loc); + __always_noconv_ = __cv_->always_noconv(); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___STD_STREAM diff --git a/sdk/tlibcxx/include/__threading_support b/sdk/tlibcxx/include/__threading_support new file mode 100644 index 00000000..65668859 --- /dev/null +++ b/sdk/tlibcxx/include/__threading_support @@ -0,0 +1,206 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_THREADING_SUPPORT +#define _LIBCPP_THREADING_SUPPORT + +#include <__config> + +#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER +#pragma GCC system_header +#endif + +// Not supported in SGX. +#ifndef _LIBCPP_HAS_NO_THREADS + +#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +#include +#include +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) + +// Mutex +#define _LIBCPP_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +typedef pthread_mutex_t __libcpp_mutex_t; + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_recursive_mutex_init(__libcpp_mutex_t* __m) +{ + pthread_mutexattr_t attr; + int __ec = pthread_mutexattr_init(&attr); + if (__ec) return __ec; + __ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (__ec) + { + pthread_mutexattr_destroy(&attr); + return __ec; + } + __ec = pthread_mutex_init(__m, &attr); + if (__ec) + { + pthread_mutexattr_destroy(&attr); + return __ec; + } + __ec = pthread_mutexattr_destroy(&attr); + if (__ec) + { + pthread_mutex_destroy(__m); + return __ec; + } + return 0; +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_lock(__libcpp_mutex_t* __m) +{ + return pthread_mutex_lock(__m); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_trylock(__libcpp_mutex_t* __m) +{ + return pthread_mutex_trylock(__m); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_unlock(__libcpp_mutex_t* __m) +{ + return pthread_mutex_unlock(__m); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_mutex_destroy(__libcpp_mutex_t* __m) +{ + return pthread_mutex_destroy(__m); +} + +// Condition variable +#define _LIBCPP_CONDVAR_INITIALIZER PTHREAD_COND_INITIALIZER +typedef pthread_cond_t __libcpp_condvar_t; + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_signal(__libcpp_condvar_t* __cv) +{ + return pthread_cond_signal(__cv); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv) +{ + return pthread_cond_broadcast(__cv); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m) +{ + return pthread_cond_wait(__cv, __m); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_timedwait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m, timespec* __ts) +{ + return pthread_cond_timedwait(__cv, __m, __ts); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_condvar_destroy(__libcpp_condvar_t* __cv) +{ + return pthread_cond_destroy(__cv); +} + +// Thread id +typedef pthread_t __libcpp_thread_id; + +// Returns non-zero if the thread ids are equal, otherwise 0 +inline _LIBCPP_ALWAYS_INLINE +bool __libcpp_thread_id_equal(__libcpp_thread_id t1, __libcpp_thread_id t2) +{ + return pthread_equal(t1, t2) != 0; +} + +// Returns non-zero if t1 < t2, otherwise 0 +inline _LIBCPP_ALWAYS_INLINE +bool __libcpp_thread_id_less(__libcpp_thread_id t1, __libcpp_thread_id t2) +{ + return t1 < t2; +} + +// Thread +typedef pthread_t __libcpp_thread_t; + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_thread_create(__libcpp_thread_t* __t, void* (*__func)(void*), void* __arg) +{ + return pthread_create(__t, 0, __func, __arg); +} + +inline _LIBCPP_ALWAYS_INLINE +__libcpp_thread_id __libcpp_thread_get_current_id() +{ + return pthread_self(); +} + +inline _LIBCPP_ALWAYS_INLINE +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t* __t) +{ + return *__t; +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_thread_join(__libcpp_thread_t* __t) +{ + return pthread_join(*__t, 0); +} + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_thread_detach(__libcpp_thread_t* __t) +{ + return pthread_detach(*__t); +} + +inline _LIBCPP_ALWAYS_INLINE +void __libcpp_thread_yield() +{ + sched_yield(); +} + +// Thread local storage +typedef pthread_key_t __libcpp_tl_key; + +inline _LIBCPP_ALWAYS_INLINE +int __libcpp_tl_create(__libcpp_tl_key* __key, void (*__at_exit)(void*)) +{ + return pthread_key_create(__key, __at_exit); +} + +inline _LIBCPP_ALWAYS_INLINE +void* __libcpp_tl_get(__libcpp_tl_key __key) +{ + return pthread_getspecific(__key); +} + +inline _LIBCPP_ALWAYS_INLINE +void __libcpp_tl_set(__libcpp_tl_key __key, void* __p) +{ + pthread_setspecific(__key, __p); +} + +#else // !_LIBCPP_HAS_THREAD_API_PTHREAD + #error "No thread API selected." +#endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_NO_THREADS + +#endif // _LIBCPP_THREADING_SUPPORT diff --git a/sdk/tlibcxx/include/__tree b/sdk/tlibcxx/include/__tree new file mode 100644 index 00000000..dad7e179 --- /dev/null +++ b/sdk/tlibcxx/include/__tree @@ -0,0 +1,2687 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TREE +#define _LIBCPP___TREE + +#include <__config> +#include +#include +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class __tree; +template + class _LIBCPP_TYPE_VIS_ONLY __tree_iterator; +template + class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator; + +template class __tree_end_node; +template class __tree_node_base; +template class __tree_node; + +#ifndef _LIBCPP_CXX03_LANG +template +union __value_type; +#else +template +struct __value_type; +#endif + +template class __map_node_destructor; +template class _LIBCPP_TYPE_VIS_ONLY __map_iterator; +template class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; + +/* + +_NodePtr algorithms + +The algorithms taking _NodePtr are red black tree algorithms. Those +algorithms taking a parameter named __root should assume that __root +points to a proper red black tree (unless otherwise specified). + +Each algorithm herein assumes that __root->__parent_ points to a non-null +structure which has a member __left_ which points back to __root. No other +member is read or written to at __root->__parent_. + +__root->__parent_ will be referred to below (in comments only) as end_node. +end_node->__left_ is an externably accessible lvalue for __root, and can be +changed by node insertion and removal (without explicit reference to end_node). + +All nodes (with the exception of end_node), even the node referred to as +__root, have a non-null __parent_ field. + +*/ + +// Returns: true if __x is a left child of its parent, else false +// Precondition: __x != nullptr. +template +inline _LIBCPP_INLINE_VISIBILITY +bool +__tree_is_left_child(_NodePtr __x) _NOEXCEPT +{ + return __x == __x->__parent_->__left_; +} + +// Determintes if the subtree rooted at __x is a proper red black subtree. If +// __x is a proper subtree, returns the black height (null counts as 1). If +// __x is an improper subtree, returns 0. +template +unsigned +__tree_sub_invariant(_NodePtr __x) +{ + if (__x == nullptr) + return 1; + // parent consistency checked by caller + // check __x->__left_ consistency + if (__x->__left_ != nullptr && __x->__left_->__parent_ != __x) + return 0; + // check __x->__right_ consistency + if (__x->__right_ != nullptr && __x->__right_->__parent_ != __x) + return 0; + // check __x->__left_ != __x->__right_ unless both are nullptr + if (__x->__left_ == __x->__right_ && __x->__left_ != nullptr) + return 0; + // If this is red, neither child can be red + if (!__x->__is_black_) + { + if (__x->__left_ && !__x->__left_->__is_black_) + return 0; + if (__x->__right_ && !__x->__right_->__is_black_) + return 0; + } + unsigned __h = __tree_sub_invariant(__x->__left_); + if (__h == 0) + return 0; // invalid left subtree + if (__h != __tree_sub_invariant(__x->__right_)) + return 0; // invalid or different height right subtree + return __h + __x->__is_black_; // return black height of this node +} + +// Determintes if the red black tree rooted at __root is a proper red black tree. +// __root == nullptr is a proper tree. Returns true is __root is a proper +// red black tree, else returns false. +template +bool +__tree_invariant(_NodePtr __root) +{ + if (__root == nullptr) + return true; + // check __x->__parent_ consistency + if (__root->__parent_ == nullptr) + return false; + if (!__tree_is_left_child(__root)) + return false; + // root must be black + if (!__root->__is_black_) + return false; + // do normal node checks + return __tree_sub_invariant(__root) != 0; +} + +// Returns: pointer to the left-most node under __x. +// Precondition: __x != nullptr. +template +inline _LIBCPP_INLINE_VISIBILITY +_NodePtr +__tree_min(_NodePtr __x) _NOEXCEPT +{ + while (__x->__left_ != nullptr) + __x = __x->__left_; + return __x; +} + +// Returns: pointer to the right-most node under __x. +// Precondition: __x != nullptr. +template +inline _LIBCPP_INLINE_VISIBILITY +_NodePtr +__tree_max(_NodePtr __x) _NOEXCEPT +{ + while (__x->__right_ != nullptr) + __x = __x->__right_; + return __x; +} + +// Returns: pointer to the next in-order node after __x. +// Precondition: __x != nullptr. +template +_NodePtr +__tree_next(_NodePtr __x) _NOEXCEPT +{ + if (__x->__right_ != nullptr) + return __tree_min(__x->__right_); + while (!__tree_is_left_child(__x)) + __x = __x->__parent_unsafe(); + return __x->__parent_unsafe(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +_EndNodePtr +__tree_next_iter(_NodePtr __x) _NOEXCEPT +{ + if (__x->__right_ != nullptr) + return static_cast<_EndNodePtr>(__tree_min(__x->__right_)); + while (!__tree_is_left_child(__x)) + __x = __x->__parent_unsafe(); + return static_cast<_EndNodePtr>(__x->__parent_); +} + +// Returns: pointer to the previous in-order node before __x. +// Precondition: __x != nullptr. +// Note: __x may be the end node. +template +inline _LIBCPP_INLINE_VISIBILITY +_NodePtr +__tree_prev_iter(_EndNodePtr __x) _NOEXCEPT +{ + if (__x->__left_ != nullptr) + return __tree_max(__x->__left_); + _NodePtr __xx = static_cast<_NodePtr>(__x); + while (__tree_is_left_child(__xx)) + __xx = __xx->__parent_unsafe(); + return __xx->__parent_unsafe(); +} + +// Returns: pointer to a node which has no children +// Precondition: __x != nullptr. +template +_NodePtr +__tree_leaf(_NodePtr __x) _NOEXCEPT +{ + while (true) + { + if (__x->__left_ != nullptr) + { + __x = __x->__left_; + continue; + } + if (__x->__right_ != nullptr) + { + __x = __x->__right_; + continue; + } + break; + } + return __x; +} + +// Effects: Makes __x->__right_ the subtree root with __x as its left child +// while preserving in-order order. +// Precondition: __x->__right_ != nullptr +template +void +__tree_left_rotate(_NodePtr __x) _NOEXCEPT +{ + _NodePtr __y = __x->__right_; + __x->__right_ = __y->__left_; + if (__x->__right_ != nullptr) + __x->__right_->__set_parent(__x); + __y->__parent_ = __x->__parent_; + if (__tree_is_left_child(__x)) + __x->__parent_->__left_ = __y; + else + __x->__parent_unsafe()->__right_ = __y; + __y->__left_ = __x; + __x->__set_parent(__y); +} + +// Effects: Makes __x->__left_ the subtree root with __x as its right child +// while preserving in-order order. +// Precondition: __x->__left_ != nullptr +template +void +__tree_right_rotate(_NodePtr __x) _NOEXCEPT +{ + _NodePtr __y = __x->__left_; + __x->__left_ = __y->__right_; + if (__x->__left_ != nullptr) + __x->__left_->__set_parent(__x); + __y->__parent_ = __x->__parent_; + if (__tree_is_left_child(__x)) + __x->__parent_->__left_ = __y; + else + __x->__parent_unsafe()->__right_ = __y; + __y->__right_ = __x; + __x->__set_parent(__y); +} + +// Effects: Rebalances __root after attaching __x to a leaf. +// Precondition: __root != nulptr && __x != nullptr. +// __x has no children. +// __x == __root or == a direct or indirect child of __root. +// If __x were to be unlinked from __root (setting __root to +// nullptr if __root == __x), __tree_invariant(__root) == true. +// Postcondition: __tree_invariant(end_node->__left_) == true. end_node->__left_ +// may be different than the value passed in as __root. +template +void +__tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT +{ + __x->__is_black_ = __x == __root; + while (__x != __root && !__x->__parent_unsafe()->__is_black_) + { + // __x->__parent_ != __root because __x->__parent_->__is_black == false + if (__tree_is_left_child(__x->__parent_unsafe())) + { + _NodePtr __y = __x->__parent_unsafe()->__parent_unsafe()->__right_; + if (__y != nullptr && !__y->__is_black_) + { + __x = __x->__parent_unsafe(); + __x->__is_black_ = true; + __x = __x->__parent_unsafe(); + __x->__is_black_ = __x == __root; + __y->__is_black_ = true; + } + else + { + if (!__tree_is_left_child(__x)) + { + __x = __x->__parent_unsafe(); + __tree_left_rotate(__x); + } + __x = __x->__parent_unsafe(); + __x->__is_black_ = true; + __x = __x->__parent_unsafe(); + __x->__is_black_ = false; + __tree_right_rotate(__x); + break; + } + } + else + { + _NodePtr __y = __x->__parent_unsafe()->__parent_->__left_; + if (__y != nullptr && !__y->__is_black_) + { + __x = __x->__parent_unsafe(); + __x->__is_black_ = true; + __x = __x->__parent_unsafe(); + __x->__is_black_ = __x == __root; + __y->__is_black_ = true; + } + else + { + if (__tree_is_left_child(__x)) + { + __x = __x->__parent_unsafe(); + __tree_right_rotate(__x); + } + __x = __x->__parent_unsafe(); + __x->__is_black_ = true; + __x = __x->__parent_unsafe(); + __x->__is_black_ = false; + __tree_left_rotate(__x); + break; + } + } + } +} + +// Precondition: __root != nullptr && __z != nullptr. +// __tree_invariant(__root) == true. +// __z == __root or == a direct or indirect child of __root. +// Effects: unlinks __z from the tree rooted at __root, rebalancing as needed. +// Postcondition: __tree_invariant(end_node->__left_) == true && end_node->__left_ +// nor any of its children refer to __z. end_node->__left_ +// may be different than the value passed in as __root. +template +void +__tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT +{ + // __z will be removed from the tree. Client still needs to destruct/deallocate it + // __y is either __z, or if __z has two children, __tree_next(__z). + // __y will have at most one child. + // __y will be the initial hole in the tree (make the hole at a leaf) + _NodePtr __y = (__z->__left_ == nullptr || __z->__right_ == nullptr) ? + __z : __tree_next(__z); + // __x is __y's possibly null single child + _NodePtr __x = __y->__left_ != nullptr ? __y->__left_ : __y->__right_; + // __w is __x's possibly null uncle (will become __x's sibling) + _NodePtr __w = nullptr; + // link __x to __y's parent, and find __w + if (__x != nullptr) + __x->__parent_ = __y->__parent_; + if (__tree_is_left_child(__y)) + { + __y->__parent_->__left_ = __x; + if (__y != __root) + __w = __y->__parent_unsafe()->__right_; + else + __root = __x; // __w == nullptr + } + else + { + __y->__parent_unsafe()->__right_ = __x; + // __y can't be root if it is a right child + __w = __y->__parent_->__left_; + } + bool __removed_black = __y->__is_black_; + // If we didn't remove __z, do so now by splicing in __y for __z, + // but copy __z's color. This does not impact __x or __w. + if (__y != __z) + { + // __z->__left_ != nulptr but __z->__right_ might == __x == nullptr + __y->__parent_ = __z->__parent_; + if (__tree_is_left_child(__z)) + __y->__parent_->__left_ = __y; + else + __y->__parent_unsafe()->__right_ = __y; + __y->__left_ = __z->__left_; + __y->__left_->__set_parent(__y); + __y->__right_ = __z->__right_; + if (__y->__right_ != nullptr) + __y->__right_->__set_parent(__y); + __y->__is_black_ = __z->__is_black_; + if (__root == __z) + __root = __y; + } + // There is no need to rebalance if we removed a red, or if we removed + // the last node. + if (__removed_black && __root != nullptr) + { + // Rebalance: + // __x has an implicit black color (transferred from the removed __y) + // associated with it, no matter what its color is. + // If __x is __root (in which case it can't be null), it is supposed + // to be black anyway, and if it is doubly black, then the double + // can just be ignored. + // If __x is red (in which case it can't be null), then it can absorb + // the implicit black just by setting its color to black. + // Since __y was black and only had one child (which __x points to), __x + // is either red with no children, else null, otherwise __y would have + // different black heights under left and right pointers. + // if (__x == __root || __x != nullptr && !__x->__is_black_) + if (__x != nullptr) + __x->__is_black_ = true; + else + { + // Else __x isn't root, and is "doubly black", even though it may + // be null. __w can not be null here, else the parent would + // see a black height >= 2 on the __x side and a black height + // of 1 on the __w side (__w must be a non-null black or a red + // with a non-null black child). + while (true) + { + if (!__tree_is_left_child(__w)) // if x is left child + { + if (!__w->__is_black_) + { + __w->__is_black_ = true; + __w->__parent_unsafe()->__is_black_ = false; + __tree_left_rotate(__w->__parent_unsafe()); + // __x is still valid + // reset __root only if necessary + if (__root == __w->__left_) + __root = __w; + // reset sibling, and it still can't be null + __w = __w->__left_->__right_; + } + // __w->__is_black_ is now true, __w may have null children + if ((__w->__left_ == nullptr || __w->__left_->__is_black_) && + (__w->__right_ == nullptr || __w->__right_->__is_black_)) + { + __w->__is_black_ = false; + __x = __w->__parent_unsafe(); + // __x can no longer be null + if (__x == __root || !__x->__is_black_) + { + __x->__is_black_ = true; + break; + } + // reset sibling, and it still can't be null + __w = __tree_is_left_child(__x) ? + __x->__parent_unsafe()->__right_ : + __x->__parent_->__left_; + // continue; + } + else // __w has a red child + { + if (__w->__right_ == nullptr || __w->__right_->__is_black_) + { + // __w left child is non-null and red + __w->__left_->__is_black_ = true; + __w->__is_black_ = false; + __tree_right_rotate(__w); + // __w is known not to be root, so root hasn't changed + // reset sibling, and it still can't be null + __w = __w->__parent_unsafe(); + } + // __w has a right red child, left child may be null + __w->__is_black_ = __w->__parent_unsafe()->__is_black_; + __w->__parent_unsafe()->__is_black_ = true; + __w->__right_->__is_black_ = true; + __tree_left_rotate(__w->__parent_unsafe()); + break; + } + } + else + { + if (!__w->__is_black_) + { + __w->__is_black_ = true; + __w->__parent_unsafe()->__is_black_ = false; + __tree_right_rotate(__w->__parent_unsafe()); + // __x is still valid + // reset __root only if necessary + if (__root == __w->__right_) + __root = __w; + // reset sibling, and it still can't be null + __w = __w->__right_->__left_; + } + // __w->__is_black_ is now true, __w may have null children + if ((__w->__left_ == nullptr || __w->__left_->__is_black_) && + (__w->__right_ == nullptr || __w->__right_->__is_black_)) + { + __w->__is_black_ = false; + __x = __w->__parent_unsafe(); + // __x can no longer be null + if (!__x->__is_black_ || __x == __root) + { + __x->__is_black_ = true; + break; + } + // reset sibling, and it still can't be null + __w = __tree_is_left_child(__x) ? + __x->__parent_unsafe()->__right_ : + __x->__parent_->__left_; + // continue; + } + else // __w has a red child + { + if (__w->__left_ == nullptr || __w->__left_->__is_black_) + { + // __w right child is non-null and red + __w->__right_->__is_black_ = true; + __w->__is_black_ = false; + __tree_left_rotate(__w); + // __w is known not to be root, so root hasn't changed + // reset sibling, and it still can't be null + __w = __w->__parent_unsafe(); + } + // __w has a left red child, right child may be null + __w->__is_black_ = __w->__parent_unsafe()->__is_black_; + __w->__parent_unsafe()->__is_black_ = true; + __w->__left_->__is_black_ = true; + __tree_right_rotate(__w->__parent_unsafe()); + break; + } + } + } + } + } +} + +// node traits + + +#ifndef _LIBCPP_CXX03_LANG +template +struct __is_tree_value_type_imp : false_type {}; + +template +struct __is_tree_value_type_imp<__value_type<_Key, _Value>> : true_type {}; + +template +struct __is_tree_value_type : false_type {}; + +template +struct __is_tree_value_type<_One> : __is_tree_value_type_imp::type> {}; +#endif + +template +struct __tree_key_value_types { + typedef _Tp key_type; + typedef _Tp __node_value_type; + typedef _Tp __container_value_type; + static const bool __is_map = false; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& __get_key(_Tp const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type const& __get_value(__node_value_type const& __v) { + return __v; + } + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n); + } + +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + static __container_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v); + } +#endif +}; + +template +struct __tree_key_value_types<__value_type<_Key, _Tp> > { + typedef _Key key_type; + typedef _Tp mapped_type; + typedef __value_type<_Key, _Tp> __node_value_type; + typedef pair __container_value_type; + typedef pair<_Key, _Tp> __nc_value_type; + typedef __container_value_type __map_value_type; + static const bool __is_map = true; + + _LIBCPP_INLINE_VISIBILITY + static key_type const& + __get_key(__node_value_type const& __t) { + return __t.__cc.first; + } + + template + _LIBCPP_INLINE_VISIBILITY + static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value, + key_type const&>::type + __get_key(_Up& __t) { + return __t.first; + } + + _LIBCPP_INLINE_VISIBILITY + static __container_value_type const& + __get_value(__node_value_type const& __t) { + return __t.__cc; + } + + template + _LIBCPP_INLINE_VISIBILITY + static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value, + __container_value_type const&>::type + __get_value(_Up& __t) { + return __t; + } + + _LIBCPP_INLINE_VISIBILITY + static __container_value_type* __get_ptr(__node_value_type& __n) { + return _VSTD::addressof(__n.__cc); + } + +#ifndef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + static __nc_value_type&& __move(__node_value_type& __v) { + return _VSTD::move(__v.__nc); + } +#endif +}; + +template +struct __tree_node_base_types { + typedef _VoidPtr __void_pointer; + + typedef __tree_node_base<__void_pointer> __node_base_type; + typedef typename __rebind_pointer<_VoidPtr, __node_base_type>::type + __node_base_pointer; + + typedef __tree_end_node<__node_base_pointer> __end_node_type; + typedef typename __rebind_pointer<_VoidPtr, __end_node_type>::type + __end_node_pointer; +#if defined(_LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB) + typedef __end_node_pointer __parent_pointer; +#else + typedef typename conditional< + is_pointer<__end_node_pointer>::value, + __end_node_pointer, + __node_base_pointer>::type __parent_pointer; +#endif + +private: + static_assert((is_same::element_type, void>::value), + "_VoidPtr does not point to unqualified void type"); +}; + +template , + bool = _KVTypes::__is_map> +struct __tree_map_pointer_types {}; + +template +struct __tree_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> { + typedef typename _KVTypes::__map_value_type _Mv; + typedef typename __rebind_pointer<_AllocPtr, _Mv>::type + __map_value_type_pointer; + typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type + __const_map_value_type_pointer; +}; + +template ::element_type> +struct __tree_node_types; + +template +struct __tree_node_types<_NodePtr, __tree_node<_Tp, _VoidPtr> > + : public __tree_node_base_types<_VoidPtr>, + __tree_key_value_types<_Tp>, + __tree_map_pointer_types<_Tp, _VoidPtr> +{ + typedef __tree_node_base_types<_VoidPtr> __base; + typedef __tree_key_value_types<_Tp> __key_base; + typedef __tree_map_pointer_types<_Tp, _VoidPtr> __map_pointer_base; +public: + + typedef typename pointer_traits<_NodePtr>::element_type __node_type; + typedef _NodePtr __node_pointer; + + typedef _Tp __node_value_type; + typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type + __node_value_type_pointer; + typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type + __const_node_value_type_pointer; +#if defined(_LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB) + typedef typename __base::__end_node_pointer __iter_pointer; +#else + typedef typename conditional< + is_pointer<__node_pointer>::value, + typename __base::__end_node_pointer, + __node_pointer>::type __iter_pointer; +#endif +private: + static_assert(!is_const<__node_type>::value, + "_NodePtr should never be a pointer to const"); + static_assert((is_same::type, + _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr."); +}; + +template +struct __make_tree_node_types { + typedef typename __rebind_pointer<_VoidPtr, __tree_node<_ValueTp, _VoidPtr> >::type + _NodePtr; + typedef __tree_node_types<_NodePtr> type; +}; + +// node + +template +class __tree_end_node +{ +public: + typedef _Pointer pointer; + pointer __left_; + + _LIBCPP_INLINE_VISIBILITY + __tree_end_node() _NOEXCEPT : __left_() {} +}; + +template +class __tree_node_base + : public __tree_node_base_types<_VoidPtr>::__end_node_type +{ + typedef __tree_node_base_types<_VoidPtr> _NodeBaseTypes; + +public: + typedef typename _NodeBaseTypes::__node_base_pointer pointer; + typedef typename _NodeBaseTypes::__parent_pointer __parent_pointer; + + pointer __right_; + __parent_pointer __parent_; + bool __is_black_; + + _LIBCPP_INLINE_VISIBILITY + pointer __parent_unsafe() const { return static_cast(__parent_);} + + _LIBCPP_INLINE_VISIBILITY + void __set_parent(pointer __p) { + __parent_ = static_cast<__parent_pointer>(__p); + } + +private: + ~__tree_node_base() _LIBCPP_EQUAL_DELETE; + __tree_node_base(__tree_node_base const&) _LIBCPP_EQUAL_DELETE; + __tree_node_base& operator=(__tree_node_base const&) _LIBCPP_EQUAL_DELETE; +}; + +template +class __tree_node + : public __tree_node_base<_VoidPtr> +{ +public: + typedef _Tp __node_value_type; + + __node_value_type __value_; + +private: + ~__tree_node() _LIBCPP_EQUAL_DELETE; + __tree_node(__tree_node const&) _LIBCPP_EQUAL_DELETE; + __tree_node& operator=(__tree_node const&) _LIBCPP_EQUAL_DELETE; +}; + + +template +class __tree_node_destructor +{ + typedef _Allocator allocator_type; + typedef allocator_traits __alloc_traits; + +public: + typedef typename __alloc_traits::pointer pointer; +private: + typedef __tree_node_types _NodeTypes; + allocator_type& __na_; + + __tree_node_destructor& operator=(const __tree_node_destructor&); + +public: + bool __value_constructed; + + _LIBCPP_INLINE_VISIBILITY + explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT + : __na_(__na), + __value_constructed(__val) + {} + + _LIBCPP_INLINE_VISIBILITY + void operator()(pointer __p) _NOEXCEPT + { + if (__value_constructed) + __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_)); + if (__p) + __alloc_traits::deallocate(__na_, __p, 1); + } + + template friend class __map_node_destructor; +}; + + +template +class _LIBCPP_TYPE_VIS_ONLY __tree_iterator +{ + typedef __tree_node_types<_NodePtr> _NodeTypes; + typedef _NodePtr __node_pointer; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; + typedef typename _NodeTypes::__end_node_pointer __end_node_pointer; + typedef typename _NodeTypes::__iter_pointer __iter_pointer; + typedef pointer_traits<__node_pointer> __pointer_traits; + + __iter_pointer __ptr_; + +public: + typedef bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _DiffType difference_type; + typedef value_type& reference; + typedef typename _NodeTypes::__node_value_type_pointer pointer; + + _LIBCPP_INLINE_VISIBILITY __tree_iterator() _NOEXCEPT +#if _LIBCPP_STD_VER > 11 + : __ptr_(nullptr) +#endif + {} + + _LIBCPP_INLINE_VISIBILITY reference operator*() const + {return __get_np()->__value_;} + _LIBCPP_INLINE_VISIBILITY pointer operator->() const + {return pointer_traits::pointer_to(__get_np()->__value_);} + + _LIBCPP_INLINE_VISIBILITY + __tree_iterator& operator++() { + __ptr_ = static_cast<__iter_pointer>( + __tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_))); + return *this; + } + _LIBCPP_INLINE_VISIBILITY + __tree_iterator operator++(int) + {__tree_iterator __t(*this); ++(*this); return __t;} + + _LIBCPP_INLINE_VISIBILITY + __tree_iterator& operator--() { + __ptr_ = static_cast<__iter_pointer>(__tree_prev_iter<__node_base_pointer>( + static_cast<__end_node_pointer>(__ptr_))); + return *this; + } + _LIBCPP_INLINE_VISIBILITY + __tree_iterator operator--(int) + {__tree_iterator __t(*this); --(*this); return __t;} + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __tree_iterator& __x, const __tree_iterator& __y) + {return __x.__ptr_ == __y.__ptr_;} + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y) + {return !(__x == __y);} + +private: + _LIBCPP_INLINE_VISIBILITY + explicit __tree_iterator(__node_pointer __p) _NOEXCEPT : __ptr_(__p) {} + _LIBCPP_INLINE_VISIBILITY + explicit __tree_iterator(__end_node_pointer __p) _NOEXCEPT : __ptr_(__p) {} + _LIBCPP_INLINE_VISIBILITY + __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); } + template friend class __tree; + template friend class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator; + template friend class _LIBCPP_TYPE_VIS_ONLY __map_iterator; + template friend class _LIBCPP_TYPE_VIS_ONLY map; + template friend class _LIBCPP_TYPE_VIS_ONLY multimap; + template friend class _LIBCPP_TYPE_VIS_ONLY set; + template friend class _LIBCPP_TYPE_VIS_ONLY multiset; +}; + +template +class _LIBCPP_TYPE_VIS_ONLY __tree_const_iterator +{ + typedef __tree_node_types<_NodePtr> _NodeTypes; + typedef typename _NodeTypes::__node_pointer __node_pointer; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; + typedef typename _NodeTypes::__end_node_pointer __end_node_pointer; + typedef typename _NodeTypes::__iter_pointer __iter_pointer; + typedef pointer_traits<__node_pointer> __pointer_traits; + + __iter_pointer __ptr_; + +public: + typedef bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _DiffType difference_type; + typedef const value_type& reference; + typedef typename _NodeTypes::__const_node_value_type_pointer pointer; + + _LIBCPP_INLINE_VISIBILITY __tree_const_iterator() _NOEXCEPT +#if _LIBCPP_STD_VER > 11 + : __ptr_(nullptr) +#endif + {} + +private: + typedef __tree_iterator + __non_const_iterator; +public: + _LIBCPP_INLINE_VISIBILITY + __tree_const_iterator(__non_const_iterator __p) _NOEXCEPT + : __ptr_(__p.__ptr_) {} + + _LIBCPP_INLINE_VISIBILITY reference operator*() const + {return __get_np()->__value_;} + _LIBCPP_INLINE_VISIBILITY pointer operator->() const + {return pointer_traits::pointer_to(__get_np()->__value_);} + + _LIBCPP_INLINE_VISIBILITY + __tree_const_iterator& operator++() { + __ptr_ = static_cast<__iter_pointer>( + __tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_))); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __tree_const_iterator operator++(int) + {__tree_const_iterator __t(*this); ++(*this); return __t;} + + _LIBCPP_INLINE_VISIBILITY + __tree_const_iterator& operator--() { + __ptr_ = static_cast<__iter_pointer>(__tree_prev_iter<__node_base_pointer>( + static_cast<__end_node_pointer>(__ptr_))); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + __tree_const_iterator operator--(int) + {__tree_const_iterator __t(*this); --(*this); return __t;} + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(const __tree_const_iterator& __x, const __tree_const_iterator& __y) + {return __x.__ptr_ == __y.__ptr_;} + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __tree_const_iterator& __x, const __tree_const_iterator& __y) + {return !(__x == __y);} + +private: + _LIBCPP_INLINE_VISIBILITY + explicit __tree_const_iterator(__node_pointer __p) _NOEXCEPT + : __ptr_(__p) {} + _LIBCPP_INLINE_VISIBILITY + explicit __tree_const_iterator(__end_node_pointer __p) _NOEXCEPT + : __ptr_(__p) {} + _LIBCPP_INLINE_VISIBILITY + __node_pointer __get_np() const { return static_cast<__node_pointer>(__ptr_); } + + template friend class __tree; + template friend class _LIBCPP_TYPE_VIS_ONLY map; + template friend class _LIBCPP_TYPE_VIS_ONLY multimap; + template friend class _LIBCPP_TYPE_VIS_ONLY set; + template friend class _LIBCPP_TYPE_VIS_ONLY multiset; + template friend class _LIBCPP_TYPE_VIS_ONLY __map_const_iterator; + +}; + +template +class __tree +{ +public: + typedef _Tp value_type; + typedef _Compare value_compare; + typedef _Allocator allocator_type; + +private: + typedef allocator_traits __alloc_traits; + typedef typename __make_tree_node_types::type + _NodeTypes; + typedef typename _NodeTypes::key_type key_type; +public: + typedef typename _NodeTypes::__node_value_type __node_value_type; + typedef typename _NodeTypes::__container_value_type __container_value_type; + + typedef typename __alloc_traits::pointer pointer; + typedef typename __alloc_traits::const_pointer const_pointer; + typedef typename __alloc_traits::size_type size_type; + typedef typename __alloc_traits::difference_type difference_type; + +public: + typedef typename _NodeTypes::__void_pointer __void_pointer; + + typedef typename _NodeTypes::__node_type __node; + typedef typename _NodeTypes::__node_pointer __node_pointer; + + typedef typename _NodeTypes::__node_base_type __node_base; + typedef typename _NodeTypes::__node_base_pointer __node_base_pointer; + + typedef typename _NodeTypes::__end_node_type __end_node_t; + typedef typename _NodeTypes::__end_node_pointer __end_node_ptr; + + typedef typename _NodeTypes::__parent_pointer __parent_pointer; + typedef typename _NodeTypes::__iter_pointer __iter_pointer; + + typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator; + typedef allocator_traits<__node_allocator> __node_traits; + +private: + // check for sane allocator pointer rebinding semantics. Rebinding the + // allocator for a new pointer type should be exactly the same as rebinding + // the pointer using 'pointer_traits'. + static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); + typedef typename __rebind_alloc_helper<__node_traits, __node_base>::type + __node_base_allocator; + typedef allocator_traits<__node_base_allocator> __node_base_traits; + static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value), + "Allocator does not rebind pointers in a sane manner."); + +private: + __iter_pointer __begin_node_; + __compressed_pair<__end_node_t, __node_allocator> __pair1_; + __compressed_pair __pair3_; + +public: + _LIBCPP_INLINE_VISIBILITY + __iter_pointer __end_node() _NOEXCEPT + { + return static_cast<__iter_pointer>( + pointer_traits<__end_node_ptr>::pointer_to(__pair1_.first()) + ); + } + _LIBCPP_INLINE_VISIBILITY + __iter_pointer __end_node() const _NOEXCEPT + { + return static_cast<__iter_pointer>( + pointer_traits<__end_node_ptr>::pointer_to( + const_cast<__end_node_t&>(__pair1_.first()) + ) + ); + } + _LIBCPP_INLINE_VISIBILITY + __node_allocator& __node_alloc() _NOEXCEPT {return __pair1_.second();} +private: + _LIBCPP_INLINE_VISIBILITY + const __node_allocator& __node_alloc() const _NOEXCEPT + {return __pair1_.second();} + _LIBCPP_INLINE_VISIBILITY + __iter_pointer& __begin_node() _NOEXCEPT {return __begin_node_;} + _LIBCPP_INLINE_VISIBILITY + const __iter_pointer& __begin_node() const _NOEXCEPT {return __begin_node_;} +public: + _LIBCPP_INLINE_VISIBILITY + allocator_type __alloc() const _NOEXCEPT + {return allocator_type(__node_alloc());} +private: + _LIBCPP_INLINE_VISIBILITY + size_type& size() _NOEXCEPT {return __pair3_.first();} +public: + _LIBCPP_INLINE_VISIBILITY + const size_type& size() const _NOEXCEPT {return __pair3_.first();} + _LIBCPP_INLINE_VISIBILITY + value_compare& value_comp() _NOEXCEPT {return __pair3_.second();} + _LIBCPP_INLINE_VISIBILITY + const value_compare& value_comp() const _NOEXCEPT + {return __pair3_.second();} +public: + + _LIBCPP_INLINE_VISIBILITY + __node_pointer __root() const _NOEXCEPT + {return static_cast<__node_pointer>(__end_node()->__left_);} + + __node_base_pointer* __root_ptr() const _NOEXCEPT { + return _VSTD::addressof(__end_node()->__left_); + } + + typedef __tree_iterator iterator; + typedef __tree_const_iterator const_iterator; + + explicit __tree(const value_compare& __comp) + _NOEXCEPT_( + is_nothrow_default_constructible<__node_allocator>::value && + is_nothrow_copy_constructible::value); + explicit __tree(const allocator_type& __a); + __tree(const value_compare& __comp, const allocator_type& __a); + __tree(const __tree& __t); + __tree& operator=(const __tree& __t); + template + void __assign_unique(_InputIterator __first, _InputIterator __last); + template + void __assign_multi(_InputIterator __first, _InputIterator __last); +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + __tree(__tree&& __t) + _NOEXCEPT_( + is_nothrow_move_constructible<__node_allocator>::value && + is_nothrow_move_constructible::value); + __tree(__tree&& __t, const allocator_type& __a); + __tree& operator=(__tree&& __t) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable<__node_allocator>::value); +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + + ~__tree(); + + _LIBCPP_INLINE_VISIBILITY + iterator begin() _NOEXCEPT {return iterator(__begin_node());} + _LIBCPP_INLINE_VISIBILITY + const_iterator begin() const _NOEXCEPT {return const_iterator(__begin_node());} + _LIBCPP_INLINE_VISIBILITY + iterator end() _NOEXCEPT {return iterator(__end_node());} + _LIBCPP_INLINE_VISIBILITY + const_iterator end() const _NOEXCEPT {return const_iterator(__end_node());} + + _LIBCPP_INLINE_VISIBILITY + size_type max_size() const _NOEXCEPT + {return __node_traits::max_size(__node_alloc());} + + void clear() _NOEXCEPT; + +// For some reason VS compiler does not support having intermixed ifdefs in _NOEXCEPT_ +// We had to rewrite the declaration to silence the compilation errors. +#if !defined(_LIBCPP_SGX_CONFIG) + void swap(__tree& __t) + _NOEXCEPT_( + __is_nothrow_swappable::value +#if _LIBCPP_STD_VER <= 11 + && (!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value) +#endif + ); +#else +#if (_LIBCPP_STD_VER <= 11) + void swap(__tree& __t) + _NOEXCEPT_( + __is_nothrow_swappable::value + && (!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value)); +#else // _LIBCPP_STD_VER > 11 + void swap(__tree& __t) + _NOEXCEPT_( + __is_nothrow_swappable::value + ); +#endif // _LIBCPP_STD_VER <= 11 +#endif // !defined(_LIBCPP_SGX_CONFIG) + +#ifndef _LIBCPP_CXX03_LANG + template + pair + __emplace_unique_key_args(_Key const&, _Args&&... __args); + template + iterator + __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&&...); + + template + pair __emplace_unique_impl(_Args&&... __args); + + template + iterator __emplace_hint_unique_impl(const_iterator __p, _Args&&... __args); + + template + iterator __emplace_multi(_Args&&... __args); + + template + iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Pp&& __x) { + return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x), + __can_extract_key<_Pp, key_type>()); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if< + __can_extract_map_key<_First, key_type, __container_value_type>::value, + pair + >::type __emplace_unique(_First&& __f, _Second&& __s) { + return __emplace_unique_key_args(__f, _VSTD::forward<_First>(__f), + _VSTD::forward<_Second>(__s)); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique(_Args&&... __args) { + return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) { + return __emplace_unique_impl(_VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) { + return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + pair + __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) { + return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_unique(const_iterator __p, _Pp&& __x) { + return __emplace_hint_unique_extract_key(__p, _VSTD::forward<_Pp>(__x), + __can_extract_key<_Pp, key_type>()); + } + + template + _LIBCPP_INLINE_VISIBILITY + typename enable_if< + __can_extract_map_key<_First, key_type, __container_value_type>::value, + iterator + >::type __emplace_hint_unique(const_iterator __p, _First&& __f, _Second&& __s) { + return __emplace_hint_unique_key_args(__p, __f, + _VSTD::forward<_First>(__f), + _VSTD::forward<_Second>(__s)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_unique(const_iterator __p, _Args&&... __args) { + return __emplace_hint_unique_impl(__p, _VSTD::forward<_Args>(__args)...); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator + __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_fail_tag) { + return __emplace_hint_unique_impl(__p, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator + __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_self_tag) { + return __emplace_hint_unique_key_args(__p, __x, _VSTD::forward<_Pp>(__x)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator + __emplace_hint_unique_extract_key(const_iterator __p, _Pp&& __x, __extract_key_first_tag) { + return __emplace_hint_unique_key_args(__p, __x.first, _VSTD::forward<_Pp>(__x)); + } + +#else + template + _LIBCPP_INLINE_VISIBILITY + pair __emplace_unique_key_args(_Key const&, _Args& __args); + template + _LIBCPP_INLINE_VISIBILITY + iterator __emplace_hint_unique_key_args(const_iterator, _Key const&, _Args&); +#endif + + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(const __container_value_type& __v) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__v), __v); + } + + _LIBCPP_INLINE_VISIBILITY + iterator __insert_unique(const_iterator __p, const __container_value_type& __v) { + return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), __v); + } + +#ifdef _LIBCPP_CXX03_LANG + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const __container_value_type& __v); + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, const __container_value_type& __v); +#else + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(__container_value_type&& __v) { + return __emplace_unique_key_args(_NodeTypes::__get_key(__v), _VSTD::move(__v)); + } + + _LIBCPP_INLINE_VISIBILITY + iterator __insert_unique(const_iterator __p, __container_value_type&& __v) { + return __emplace_hint_unique_key_args(__p, _NodeTypes::__get_key(__v), _VSTD::move(__v)); + } + + template ::type, + __container_value_type + >::value + >::type> + _LIBCPP_INLINE_VISIBILITY + pair __insert_unique(_Vp&& __v) { + return __emplace_unique(_VSTD::forward<_Vp>(__v)); + } + + template ::type, + __container_value_type + >::value + >::type> + _LIBCPP_INLINE_VISIBILITY + iterator __insert_unique(const_iterator __p, _Vp&& __v) { + return __emplace_hint_unique(__p, _VSTD::forward<_Vp>(__v)); + } + + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(__container_value_type&& __v) { + return __emplace_multi(_VSTD::move(__v)); + } + + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, __container_value_type&& __v) { + return __emplace_hint_multi(__p, _VSTD::move(__v)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(_Vp&& __v) { + return __emplace_multi(_VSTD::forward<_Vp>(__v)); + } + + template + _LIBCPP_INLINE_VISIBILITY + iterator __insert_multi(const_iterator __p, _Vp&& __v) { + return __emplace_hint_multi(__p, _VSTD::forward<_Vp>(__v)); + } + +#endif // !_LIBCPP_CXX03_LANG + + pair __node_insert_unique(__node_pointer __nd); + iterator __node_insert_unique(const_iterator __p, + __node_pointer __nd); + + iterator __node_insert_multi(__node_pointer __nd); + iterator __node_insert_multi(const_iterator __p, __node_pointer __nd); + + iterator erase(const_iterator __p); + iterator erase(const_iterator __f, const_iterator __l); + template + size_type __erase_unique(const _Key& __k); + template + size_type __erase_multi(const _Key& __k); + + void __insert_node_at(__parent_pointer __parent, + __node_base_pointer& __child, + __node_base_pointer __new_node); + + template + iterator find(const _Key& __v); + template + const_iterator find(const _Key& __v) const; + + template + size_type __count_unique(const _Key& __k) const; + template + size_type __count_multi(const _Key& __k) const; + + template + _LIBCPP_INLINE_VISIBILITY + iterator lower_bound(const _Key& __v) + {return __lower_bound(__v, __root(), __end_node());} + template + iterator __lower_bound(const _Key& __v, + __node_pointer __root, + __iter_pointer __result); + template + _LIBCPP_INLINE_VISIBILITY + const_iterator lower_bound(const _Key& __v) const + {return __lower_bound(__v, __root(), __end_node());} + template + const_iterator __lower_bound(const _Key& __v, + __node_pointer __root, + __iter_pointer __result) const; + template + _LIBCPP_INLINE_VISIBILITY + iterator upper_bound(const _Key& __v) + {return __upper_bound(__v, __root(), __end_node());} + template + iterator __upper_bound(const _Key& __v, + __node_pointer __root, + __iter_pointer __result); + template + _LIBCPP_INLINE_VISIBILITY + const_iterator upper_bound(const _Key& __v) const + {return __upper_bound(__v, __root(), __end_node());} + template + const_iterator __upper_bound(const _Key& __v, + __node_pointer __root, + __iter_pointer __result) const; + template + pair + __equal_range_unique(const _Key& __k); + template + pair + __equal_range_unique(const _Key& __k) const; + + template + pair + __equal_range_multi(const _Key& __k); + template + pair + __equal_range_multi(const _Key& __k) const; + + typedef __tree_node_destructor<__node_allocator> _Dp; + typedef unique_ptr<__node, _Dp> __node_holder; + + __node_holder remove(const_iterator __p) _NOEXCEPT; +private: + __node_base_pointer& + __find_leaf_low(__parent_pointer& __parent, const key_type& __v); + __node_base_pointer& + __find_leaf_high(__parent_pointer& __parent, const key_type& __v); + __node_base_pointer& + __find_leaf(const_iterator __hint, + __parent_pointer& __parent, const key_type& __v); + template + __node_base_pointer& + __find_equal(__parent_pointer& __parent, const _Key& __v); + template + __node_base_pointer& + __find_equal(const_iterator __hint, __parent_pointer& __parent, + __node_base_pointer& __dummy, + const _Key& __v); + +#ifndef _LIBCPP_CXX03_LANG + template + __node_holder __construct_node(_Args&& ...__args); +#else + __node_holder __construct_node(const __container_value_type& __v); +#endif + + void destroy(__node_pointer __nd) _NOEXCEPT; + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const __tree& __t) + {__copy_assign_alloc(__t, integral_constant());} + + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const __tree& __t, true_type) + { + if (__node_alloc() != __t.__node_alloc()) + clear(); + __node_alloc() = __t.__node_alloc(); + } + _LIBCPP_INLINE_VISIBILITY + void __copy_assign_alloc(const __tree& __t, false_type) {} + + void __move_assign(__tree& __t, false_type); + void __move_assign(__tree& __t, true_type) + _NOEXCEPT_(is_nothrow_move_assignable::value && + is_nothrow_move_assignable<__node_allocator>::value); + + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__tree& __t) + _NOEXCEPT_( + !__node_traits::propagate_on_container_move_assignment::value || + is_nothrow_move_assignable<__node_allocator>::value) + {__move_assign_alloc(__t, integral_constant());} + + _LIBCPP_INLINE_VISIBILITY + void __move_assign_alloc(__tree& __t, true_type) + _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) + {__node_alloc() = _VSTD::move(__t.__node_alloc());} + _LIBCPP_INLINE_VISIBILITY +#if !defined(_LIBCPP_SGX_CONFIG) + void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {} +#else + void __move_assign_alloc(__tree& __t, false_type) _NOEXCEPT {UNREFERENCED_PARAMETER(__t);} +#endif // !defined(_LIBCPP_SGX_CONFIG) + + __node_pointer __detach(); + static __node_pointer __detach(__node_pointer); + + template friend class _LIBCPP_TYPE_VIS_ONLY map; + template friend class _LIBCPP_TYPE_VIS_ONLY multimap; +}; + +template +__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp) + _NOEXCEPT_( + is_nothrow_default_constructible<__node_allocator>::value && + is_nothrow_copy_constructible::value) + : __pair3_(0, __comp) +{ + __begin_node() = __end_node(); +} + +template +__tree<_Tp, _Compare, _Allocator>::__tree(const allocator_type& __a) + : __begin_node_(__iter_pointer()), + __pair1_(__node_allocator(__a)), + __pair3_(0) +{ + __begin_node() = __end_node(); +} + +template +__tree<_Tp, _Compare, _Allocator>::__tree(const value_compare& __comp, + const allocator_type& __a) + : __begin_node_(__iter_pointer()), + __pair1_(__node_allocator(__a)), + __pair3_(0, __comp) +{ + __begin_node() = __end_node(); +} + +// Precondition: size() != 0 +template +typename __tree<_Tp, _Compare, _Allocator>::__node_pointer +__tree<_Tp, _Compare, _Allocator>::__detach() +{ + __node_pointer __cache = static_cast<__node_pointer>(__begin_node()); + __begin_node() = __end_node(); + __end_node()->__left_->__parent_ = nullptr; + __end_node()->__left_ = nullptr; + size() = 0; + // __cache->__left_ == nullptr + if (__cache->__right_ != nullptr) + __cache = static_cast<__node_pointer>(__cache->__right_); + // __cache->__left_ == nullptr + // __cache->__right_ == nullptr + return __cache; +} + +// Precondition: __cache != nullptr +// __cache->left_ == nullptr +// __cache->right_ == nullptr +// This is no longer a red-black tree +template +typename __tree<_Tp, _Compare, _Allocator>::__node_pointer +__tree<_Tp, _Compare, _Allocator>::__detach(__node_pointer __cache) +{ + if (__cache->__parent_ == nullptr) + return nullptr; + if (__tree_is_left_child(static_cast<__node_base_pointer>(__cache))) + { + __cache->__parent_->__left_ = nullptr; + __cache = static_cast<__node_pointer>(__cache->__parent_); + if (__cache->__right_ == nullptr) + return __cache; + return static_cast<__node_pointer>(__tree_leaf(__cache->__right_)); + } + // __cache is right child + __cache->__parent_unsafe()->__right_ = nullptr; + __cache = static_cast<__node_pointer>(__cache->__parent_); + if (__cache->__left_ == nullptr) + return __cache; + return static_cast<__node_pointer>(__tree_leaf(__cache->__left_)); +} + +template +__tree<_Tp, _Compare, _Allocator>& +__tree<_Tp, _Compare, _Allocator>::operator=(const __tree& __t) +{ + if (this != &__t) + { + value_comp() = __t.value_comp(); + __copy_assign_alloc(__t); + __assign_multi(__t.begin(), __t.end()); + } + return *this; +} + +template +template +void +__tree<_Tp, _Compare, _Allocator>::__assign_unique(_InputIterator __first, _InputIterator __last) +{ + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value), + "__assign_unique may only be called with the containers value type"); + + if (size() != 0) + { + __node_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + for (; __cache != nullptr && __first != __last; ++__first) + { + __cache->__value_ = *__first; + __node_pointer __next = __detach(__cache); + __node_insert_unique(__cache); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + while (__cache->__parent_ != nullptr) + __cache = static_cast<__node_pointer>(__cache->__parent_); + destroy(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + if (__cache != nullptr) + { + while (__cache->__parent_ != nullptr) + __cache = static_cast<__node_pointer>(__cache->__parent_); + destroy(__cache); + } + } + for (; __first != __last; ++__first) + __insert_unique(*__first); +} + +template +template +void +__tree<_Tp, _Compare, _Allocator>::__assign_multi(_InputIterator __first, _InputIterator __last) +{ + typedef iterator_traits<_InputIterator> _ITraits; + typedef typename _ITraits::value_type _ItValueType; + static_assert((is_same<_ItValueType, __container_value_type>::value || + is_same<_ItValueType, __node_value_type>::value), + "__assign_multi may only be called with the containers value type" + " or the nodes value type"); + if (size() != 0) + { + __node_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + for (; __cache != nullptr && __first != __last; ++__first) + { + __cache->__value_ = *__first; + __node_pointer __next = __detach(__cache); + __node_insert_multi(__cache); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + while (__cache->__parent_ != nullptr) + __cache = static_cast<__node_pointer>(__cache->__parent_); + destroy(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + if (__cache != nullptr) + { + while (__cache->__parent_ != nullptr) + __cache = static_cast<__node_pointer>(__cache->__parent_); + destroy(__cache); + } + } + for (; __first != __last; ++__first) + __insert_multi(_NodeTypes::__get_value(*__first)); +} + +template +__tree<_Tp, _Compare, _Allocator>::__tree(const __tree& __t) + : __begin_node_(__iter_pointer()), + __pair1_(__node_traits::select_on_container_copy_construction(__t.__node_alloc())), + __pair3_(0, __t.value_comp()) +{ + __begin_node() = __end_node(); +} + +#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t) + _NOEXCEPT_( + is_nothrow_move_constructible<__node_allocator>::value && + is_nothrow_move_constructible::value) + : __begin_node_(_VSTD::move(__t.__begin_node_)), + __pair1_(_VSTD::move(__t.__pair1_)), + __pair3_(_VSTD::move(__t.__pair3_)) +{ + if (size() == 0) + __begin_node() = __end_node(); + else + { + __end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__end_node()); + __t.__begin_node() = __t.__end_node(); + __t.__end_node()->__left_ = nullptr; + __t.size() = 0; + } +} + +template +__tree<_Tp, _Compare, _Allocator>::__tree(__tree&& __t, const allocator_type& __a) + : __pair1_(__node_allocator(__a)), + __pair3_(0, _VSTD::move(__t.value_comp())) +{ + if (__a == __t.__alloc()) + { + if (__t.size() == 0) + __begin_node() = __end_node(); + else + { + __begin_node() = __t.__begin_node(); + __end_node()->__left_ = __t.__end_node()->__left_; + __end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__end_node()); + size() = __t.size(); + __t.__begin_node() = __t.__end_node(); + __t.__end_node()->__left_ = nullptr; + __t.size() = 0; + } + } + else + { + __begin_node() = __end_node(); + } +} + +template +void +__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, true_type) + _NOEXCEPT_(is_nothrow_move_assignable::value && + is_nothrow_move_assignable<__node_allocator>::value) +{ + destroy(static_cast<__node_pointer>(__end_node()->__left_)); + __begin_node_ = __t.__begin_node_; + __pair1_.first() = __t.__pair1_.first(); + __move_assign_alloc(__t); + __pair3_ = _VSTD::move(__t.__pair3_); + if (size() == 0) + __begin_node() = __end_node(); + else + { + __end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__end_node()); + __t.__begin_node() = __t.__end_node(); + __t.__end_node()->__left_ = nullptr; + __t.size() = 0; + } +} + +template +void +__tree<_Tp, _Compare, _Allocator>::__move_assign(__tree& __t, false_type) +{ + if (__node_alloc() == __t.__node_alloc()) + __move_assign(__t, true_type()); + else + { + value_comp() = _VSTD::move(__t.value_comp()); + const_iterator __e = end(); + if (size() != 0) + { + __node_pointer __cache = __detach(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + while (__cache != nullptr && __t.size() != 0) + { + __cache->__value_ = _VSTD::move(__t.remove(__t.begin())->__value_); + __node_pointer __next = __detach(__cache); + __node_insert_multi(__cache); + __cache = __next; + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + while (__cache->__parent_ != nullptr) + __cache = static_cast<__node_pointer>(__cache->__parent_); + destroy(__cache); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + if (__cache != nullptr) + { + while (__cache->__parent_ != nullptr) + __cache = static_cast<__node_pointer>(__cache->__parent_); + destroy(__cache); + } + } + while (__t.size() != 0) + __insert_multi(__e, _NodeTypes::__move(__t.remove(__t.begin())->__value_)); + } +} + +template +__tree<_Tp, _Compare, _Allocator>& +__tree<_Tp, _Compare, _Allocator>::operator=(__tree&& __t) + _NOEXCEPT_( + __node_traits::propagate_on_container_move_assignment::value && + is_nothrow_move_assignable::value && + is_nothrow_move_assignable<__node_allocator>::value) + +{ + __move_assign(__t, integral_constant()); + return *this; +} + +#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES + +template +__tree<_Tp, _Compare, _Allocator>::~__tree() +{ + static_assert((is_copy_constructible::value), + "Comparator must be copy-constructible."); + destroy(__root()); +} + +template +void +__tree<_Tp, _Compare, _Allocator>::destroy(__node_pointer __nd) _NOEXCEPT +{ + if (__nd != nullptr) + { + destroy(static_cast<__node_pointer>(__nd->__left_)); + destroy(static_cast<__node_pointer>(__nd->__right_)); + __node_allocator& __na = __node_alloc(); + __node_traits::destroy(__na, _NodeTypes::__get_ptr(__nd->__value_)); + __node_traits::deallocate(__na, __nd, 1); + } +} + +// For some reason VS compiler does not support having intermixed ifdefs in _NOEXCEPT_ +// We had to rewrite the declaration to silence the compilation errors. +#if !defined(_LIBCPP_SGX_CONFIG) +template +void +__tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) + _NOEXCEPT_( + __is_nothrow_swappable::value +#if _LIBCPP_STD_VER <= 11 + && (!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value) +#endif + ) +#else +#if _LIBCPP_STD_VER <= 11 +template +void +__tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) + _NOEXCEPT_( + __is_nothrow_swappable::value + && (!__node_traits::propagate_on_container_swap::value || + __is_nothrow_swappable<__node_allocator>::value)) +#else // _LIBCPP_STD_VER > 11 +template +void +__tree<_Tp, _Compare, _Allocator>::swap(__tree& __t) + _NOEXCEPT_( + __is_nothrow_swappable::value) +#endif // _LIBCPP_STD_VER <= 11 +#endif // !defined(_LIBCPP_SGX_CONFIG) +{ + using _VSTD::swap; + swap(__begin_node_, __t.__begin_node_); + swap(__pair1_.first(), __t.__pair1_.first()); + __swap_allocator(__node_alloc(), __t.__node_alloc()); + __pair3_.swap(__t.__pair3_); + if (size() == 0) + __begin_node() = __end_node(); + else + __end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__end_node()); + if (__t.size() == 0) + __t.__begin_node() = __t.__end_node(); + else + __t.__end_node()->__left_->__parent_ = static_cast<__parent_pointer>(__t.__end_node()); +} + +template +void +__tree<_Tp, _Compare, _Allocator>::clear() _NOEXCEPT +{ + destroy(__root()); + size() = 0; + __begin_node() = __end_node(); + __end_node()->__left_ = nullptr; +} + +// Find lower_bound place to insert +// Set __parent to parent of null leaf +// Return reference to null leaf +template +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_leaf_low(__parent_pointer& __parent, + const key_type& __v) +{ + __node_pointer __nd = __root(); + if (__nd != nullptr) + { + while (true) + { + if (value_comp()(__nd->__value_, __v)) + { + if (__nd->__right_ != nullptr) + __nd = static_cast<__node_pointer>(__nd->__right_); + else + { + __parent = static_cast<__parent_pointer>(__nd); + return __nd->__right_; + } + } + else + { + if (__nd->__left_ != nullptr) + __nd = static_cast<__node_pointer>(__nd->__left_); + else + { + __parent = static_cast<__parent_pointer>(__nd); + return __parent->__left_; + } + } + } + } + __parent = static_cast<__parent_pointer>(__end_node()); + return __parent->__left_; +} + +// Find upper_bound place to insert +// Set __parent to parent of null leaf +// Return reference to null leaf +template +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_leaf_high(__parent_pointer& __parent, + const key_type& __v) +{ + __node_pointer __nd = __root(); + if (__nd != nullptr) + { + while (true) + { + if (value_comp()(__v, __nd->__value_)) + { + if (__nd->__left_ != nullptr) + __nd = static_cast<__node_pointer>(__nd->__left_); + else + { + __parent = static_cast<__parent_pointer>(__nd); + return __parent->__left_; + } + } + else + { + if (__nd->__right_ != nullptr) + __nd = static_cast<__node_pointer>(__nd->__right_); + else + { + __parent = static_cast<__parent_pointer>(__nd); + return __nd->__right_; + } + } + } + } + __parent = static_cast<__parent_pointer>(__end_node()); + return __parent->__left_; +} + +// Find leaf place to insert closest to __hint +// First check prior to __hint. +// Next check after __hint. +// Next do O(log N) search. +// Set __parent to parent of null leaf +// Return reference to null leaf +template +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_leaf(const_iterator __hint, + __parent_pointer& __parent, + const key_type& __v) +{ + if (__hint == end() || !value_comp()(*__hint, __v)) // check before + { + // __v <= *__hint + const_iterator __prior = __hint; + if (__prior == begin() || !value_comp()(__v, *--__prior)) + { + // *prev(__hint) <= __v <= *__hint + if (__hint.__ptr_->__left_ == nullptr) + { + __parent = static_cast<__parent_pointer>(__hint.__ptr_); + return __parent->__left_; + } + else + { + __parent = static_cast<__parent_pointer>(__prior.__ptr_); + return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_; + } + } + // __v < *prev(__hint) + return __find_leaf_high(__parent, __v); + } + // else __v > *__hint + return __find_leaf_low(__parent, __v); +} + +// Find place to insert if __v doesn't exist +// Set __parent to parent of null leaf +// Return reference to null leaf +// If __v exists, set parent to node of __v and return reference to node of __v +template +template +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_equal(__parent_pointer& __parent, + const _Key& __v) +{ + __node_pointer __nd = __root(); + __node_base_pointer* __nd_ptr = __root_ptr(); + if (__nd != nullptr) + { + while (true) + { + if (value_comp()(__v, __nd->__value_)) + { + if (__nd->__left_ != nullptr) { + __nd_ptr = _VSTD::addressof(__nd->__left_); + __nd = static_cast<__node_pointer>(__nd->__left_); + } else { + __parent = static_cast<__parent_pointer>(__nd); + return __parent->__left_; + } + } + else if (value_comp()(__nd->__value_, __v)) + { + if (__nd->__right_ != nullptr) { + __nd_ptr = _VSTD::addressof(__nd->__right_); + __nd = static_cast<__node_pointer>(__nd->__right_); + } else { + __parent = static_cast<__parent_pointer>(__nd); + return __nd->__right_; + } + } + else + { + __parent = static_cast<__parent_pointer>(__nd); + return *__nd_ptr; + } + } + } + __parent = static_cast<__parent_pointer>(__end_node()); + return __parent->__left_; +} + +// Find place to insert if __v doesn't exist +// First check prior to __hint. +// Next check after __hint. +// Next do O(log N) search. +// Set __parent to parent of null leaf +// Return reference to null leaf +// If __v exists, set parent to node of __v and return reference to node of __v +template +template +typename __tree<_Tp, _Compare, _Allocator>::__node_base_pointer& +__tree<_Tp, _Compare, _Allocator>::__find_equal(const_iterator __hint, + __parent_pointer& __parent, + __node_base_pointer& __dummy, + const _Key& __v) +{ + if (__hint == end() || value_comp()(__v, *__hint)) // check before + { + // __v < *__hint + const_iterator __prior = __hint; + if (__prior == begin() || value_comp()(*--__prior, __v)) + { + // *prev(__hint) < __v < *__hint + if (__hint.__ptr_->__left_ == nullptr) + { + __parent = static_cast<__parent_pointer>(__hint.__ptr_); + return __parent->__left_; + } + else + { + __parent = static_cast<__parent_pointer>(__prior.__ptr_); + return static_cast<__node_base_pointer>(__prior.__ptr_)->__right_; + } + } + // __v <= *prev(__hint) + return __find_equal(__parent, __v); + } + else if (value_comp()(*__hint, __v)) // check after + { + // *__hint < __v + const_iterator __next = _VSTD::next(__hint); + if (__next == end() || value_comp()(__v, *__next)) + { + // *__hint < __v < *_VSTD::next(__hint) + if (__hint.__get_np()->__right_ == nullptr) + { + __parent = static_cast<__parent_pointer>(__hint.__ptr_); + return static_cast<__node_base_pointer>(__hint.__ptr_)->__right_; + } + else + { + __parent = static_cast<__parent_pointer>(__next.__ptr_); + return __parent->__left_; + } + } + // *next(__hint) <= __v + return __find_equal(__parent, __v); + } + // else __v == *__hint + __parent = static_cast<__parent_pointer>(__hint.__ptr_); + __dummy = static_cast<__node_base_pointer>(__hint.__ptr_); + return __dummy; +} + +template +void +__tree<_Tp, _Compare, _Allocator>::__insert_node_at(__parent_pointer __parent, + __node_base_pointer& __child, + __node_base_pointer __new_node) +{ + __new_node->__left_ = nullptr; + __new_node->__right_ = nullptr; + __new_node->__parent_ = __parent; + // __new_node->__is_black_ is initialized in __tree_balance_after_insert + __child = __new_node; + if (__begin_node()->__left_ != nullptr) + __begin_node() = static_cast<__iter_pointer>(__begin_node()->__left_); + __tree_balance_after_insert(__end_node()->__left_, __child); + ++size(); +} + +#ifndef _LIBCPP_CXX03_LANG +template +template +pair::iterator, bool> +__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) +#else +template +template +pair::iterator, bool> +__tree<_Tp, _Compare, _Allocator>::__emplace_unique_key_args(_Key const& __k, _Args& __args) +#endif +{ + __parent_pointer __parent; + __node_base_pointer& __child = __find_equal(__parent, __k); + __node_pointer __r = static_cast<__node_pointer>(__child); + bool __inserted = false; + if (__child == nullptr) + { +#ifndef _LIBCPP_CXX03_LANG + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); +#else + __node_holder __h = __construct_node(__args); +#endif + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __r = __h.release(); + __inserted = true; + } + return pair(iterator(__r), __inserted); +} + + +#ifndef _LIBCPP_CXX03_LANG +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args( + const_iterator __p, _Key const& __k, _Args&&... __args) +#else +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_key_args( + const_iterator __p, _Key const& __k, _Args& __args) +#endif +{ + __parent_pointer __parent; + __node_base_pointer __dummy; + __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __k); + __node_pointer __r = static_cast<__node_pointer>(__child); + if (__child == nullptr) + { +#ifndef _LIBCPP_CXX03_LANG + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); +#else + __node_holder __h = __construct_node(__args); +#endif + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __r = __h.release(); + } + return iterator(__r); +} + + +#ifndef _LIBCPP_CXX03_LANG + +template +template +typename __tree<_Tp, _Compare, _Allocator>::__node_holder +__tree<_Tp, _Compare, _Allocator>::__construct_node(_Args&& ...__args) +{ + static_assert(!__is_tree_value_type<_Args...>::value, + "Cannot construct from __value_type"); + __node_allocator& __na = __node_alloc(); + __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...); + __h.get_deleter().__value_constructed = true; + return __h; +} + + +template +template +pair::iterator, bool> +__tree<_Tp, _Compare, _Allocator>::__emplace_unique_impl(_Args&&... __args) +{ + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + __parent_pointer __parent; + __node_base_pointer& __child = __find_equal(__parent, __h->__value_); + __node_pointer __r = static_cast<__node_pointer>(__child); + bool __inserted = false; + if (__child == nullptr) + { + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __r = __h.release(); + __inserted = true; + } + return pair(iterator(__r), __inserted); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__emplace_hint_unique_impl(const_iterator __p, _Args&&... __args) +{ + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + __parent_pointer __parent; + __node_base_pointer __dummy; + __node_base_pointer& __child = __find_equal(__p, __parent, __dummy, __h->__value_); + __node_pointer __r = static_cast<__node_pointer>(__child); + if (__child == nullptr) + { + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + __r = __h.release(); + } + return iterator(__r); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__emplace_multi(_Args&&... __args) +{ + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__h->__value_)); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + return iterator(static_cast<__node_pointer>(__h.release())); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__emplace_hint_multi(const_iterator __p, + _Args&&... __args) +{ + __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__h->__value_)); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + return iterator(static_cast<__node_pointer>(__h.release())); +} + + +#else // _LIBCPP_CXX03_LANG + +template +typename __tree<_Tp, _Compare, _Allocator>::__node_holder +__tree<_Tp, _Compare, _Allocator>::__construct_node(const __container_value_type& __v) +{ + __node_allocator& __na = __node_alloc(); + __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); + __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v); + __h.get_deleter().__value_constructed = true; + return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 +} + +#endif // _LIBCPP_CXX03_LANG + +#ifdef _LIBCPP_CXX03_LANG +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__insert_multi(const __container_value_type& __v) +{ + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__v)); + __node_holder __h = __construct_node(__v); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + return iterator(__h.release()); +} + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__insert_multi(const_iterator __p, const __container_value_type& __v) +{ + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__v)); + __node_holder __h = __construct_node(__v); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__h.get())); + return iterator(__h.release()); +} +#endif + +template +pair::iterator, bool> +__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(__node_pointer __nd) +{ + __parent_pointer __parent; + __node_base_pointer& __child = __find_equal(__parent, __nd->__value_); + __node_pointer __r = static_cast<__node_pointer>(__child); + bool __inserted = false; + if (__child == nullptr) + { + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + __r = __nd; + __inserted = true; + } + return pair(iterator(__r), __inserted); +} + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__node_insert_unique(const_iterator __p, + __node_pointer __nd) +{ + __parent_pointer __parent; + __node_base_pointer __dummy; + __node_base_pointer& __child = __find_equal(__p, __parent, __nd->__value_); + __node_pointer __r = static_cast<__node_pointer>(__child); + if (__child == nullptr) + { + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + __r = __nd; + } + return iterator(__r); +} + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(__node_pointer __nd) +{ + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf_high(__parent, _NodeTypes::__get_key(__nd->__value_)); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + return iterator(__nd); +} + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, + __node_pointer __nd) +{ + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf(__p, __parent, _NodeTypes::__get_key(__nd->__value_)); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__nd)); + return iterator(__nd); +} + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p) +{ + __node_pointer __np = __p.__get_np(); + iterator __r(__p.__ptr_); + ++__r; + if (__begin_node() == __p.__ptr_) + __begin_node() = __r.__ptr_; + --size(); + __node_allocator& __na = __node_alloc(); + __tree_remove(__end_node()->__left_, + static_cast<__node_base_pointer>(__np)); + __node_traits::destroy(__na, _NodeTypes::__get_ptr( + const_cast<__node_value_type&>(*__p))); + __node_traits::deallocate(__na, __np, 1); + return __r; +} + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __f, const_iterator __l) +{ + while (__f != __l) + __f = erase(__f); + return iterator(__l.__ptr_); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::size_type +__tree<_Tp, _Compare, _Allocator>::__erase_unique(const _Key& __k) +{ + iterator __i = find(__k); + if (__i == end()) + return 0; + erase(__i); + return 1; +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::size_type +__tree<_Tp, _Compare, _Allocator>::__erase_multi(const _Key& __k) +{ + pair __p = __equal_range_multi(__k); + size_type __r = 0; + for (; __p.first != __p.second; ++__r) + __p.first = erase(__p.first); + return __r; +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) +{ + iterator __p = __lower_bound(__v, __root(), __end_node()); + if (__p != end() && !value_comp()(__v, *__p)) + return __p; + return end(); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::find(const _Key& __v) const +{ + const_iterator __p = __lower_bound(__v, __root(), __end_node()); + if (__p != end() && !value_comp()(__v, *__p)) + return __p; + return end(); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::size_type +__tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const +{ + __node_pointer __rt = __root(); + while (__rt != nullptr) + { + if (value_comp()(__k, __rt->__value_)) + { + __rt = static_cast<__node_pointer>(__rt->__left_); + } + else if (value_comp()(__rt->__value_, __k)) + __rt = static_cast<__node_pointer>(__rt->__right_); + else + return 1; + } + return 0; +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::size_type +__tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const +{ + __iter_pointer __result = __end_node(); + __node_pointer __rt = __root(); + while (__rt != nullptr) + { + if (value_comp()(__k, __rt->__value_)) + { + __result = static_cast<__iter_pointer>(__rt); + __rt = static_cast<__node_pointer>(__rt->__left_); + } + else if (value_comp()(__rt->__value_, __k)) + __rt = static_cast<__node_pointer>(__rt->__right_); + else + return _VSTD::distance( + __lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__rt)), + __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result) + ); + } + return 0; +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, + __node_pointer __root, + __iter_pointer __result) +{ + while (__root != nullptr) + { + if (!value_comp()(__root->__value_, __v)) + { + __result = static_cast<__iter_pointer>(__root); + __root = static_cast<__node_pointer>(__root->__left_); + } + else + __root = static_cast<__node_pointer>(__root->__right_); + } + return iterator(__result); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::__lower_bound(const _Key& __v, + __node_pointer __root, + __iter_pointer __result) const +{ + while (__root != nullptr) + { + if (!value_comp()(__root->__value_, __v)) + { + __result = static_cast<__iter_pointer>(__root); + __root = static_cast<__node_pointer>(__root->__left_); + } + else + __root = static_cast<__node_pointer>(__root->__right_); + } + return const_iterator(__result); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, + __node_pointer __root, + __iter_pointer __result) +{ + while (__root != nullptr) + { + if (value_comp()(__v, __root->__value_)) + { + __result = static_cast<__iter_pointer>(__root); + __root = static_cast<__node_pointer>(__root->__left_); + } + else + __root = static_cast<__node_pointer>(__root->__right_); + } + return iterator(__result); +} + +template +template +typename __tree<_Tp, _Compare, _Allocator>::const_iterator +__tree<_Tp, _Compare, _Allocator>::__upper_bound(const _Key& __v, + __node_pointer __root, + __iter_pointer __result) const +{ + while (__root != nullptr) + { + if (value_comp()(__v, __root->__value_)) + { + __result = static_cast<__iter_pointer>(__root); + __root = static_cast<__node_pointer>(__root->__left_); + } + else + __root = static_cast<__node_pointer>(__root->__right_); + } + return const_iterator(__result); +} + +template +template +pair::iterator, + typename __tree<_Tp, _Compare, _Allocator>::iterator> +__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) +{ + typedef pair _Pp; + __iter_pointer __result = __end_node(); + __node_pointer __rt = __root(); + while (__rt != nullptr) + { + if (value_comp()(__k, __rt->__value_)) + { + __result = static_cast<__iter_pointer>(__rt); + __rt = static_cast<__node_pointer>(__rt->__left_); + } + else if (value_comp()(__rt->__value_, __k)) + __rt = static_cast<__node_pointer>(__rt->__right_); + else + return _Pp(iterator(__rt), + iterator( + __rt->__right_ != nullptr ? + static_cast<__iter_pointer>(__tree_min(__rt->__right_)) + : __result)); + } + return _Pp(iterator(__result), iterator(__result)); +} + +template +template +pair::const_iterator, + typename __tree<_Tp, _Compare, _Allocator>::const_iterator> +__tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const +{ + typedef pair _Pp; + __iter_pointer __result = __end_node(); + __node_pointer __rt = __root(); + while (__rt != nullptr) + { + if (value_comp()(__k, __rt->__value_)) + { + __result = static_cast<__iter_pointer>(__rt); + __rt = static_cast<__node_pointer>(__rt->__left_); + } + else if (value_comp()(__rt->__value_, __k)) + __rt = static_cast<__node_pointer>(__rt->__right_); + else + return _Pp(const_iterator(__rt), + const_iterator( + __rt->__right_ != nullptr ? + static_cast<__iter_pointer>(__tree_min(__rt->__right_)) + : __result)); + } + return _Pp(const_iterator(__result), const_iterator(__result)); +} + +template +template +pair::iterator, + typename __tree<_Tp, _Compare, _Allocator>::iterator> +__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) +{ + typedef pair _Pp; + __iter_pointer __result = __end_node(); + __node_pointer __rt = __root(); + while (__rt != nullptr) + { + if (value_comp()(__k, __rt->__value_)) + { + __result = static_cast<__iter_pointer>(__rt); + __rt = static_cast<__node_pointer>(__rt->__left_); + } + else if (value_comp()(__rt->__value_, __k)) + __rt = static_cast<__node_pointer>(__rt->__right_); + else + return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__rt)), + __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)); + } + return _Pp(iterator(__result), iterator(__result)); +} + +template +template +pair::const_iterator, + typename __tree<_Tp, _Compare, _Allocator>::const_iterator> +__tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const +{ + typedef pair _Pp; + __iter_pointer __result = __end_node(); + __node_pointer __rt = __root(); + while (__rt != nullptr) + { + if (value_comp()(__k, __rt->__value_)) + { + __result = static_cast<__iter_pointer>(__rt); + __rt = static_cast<__node_pointer>(__rt->__left_); + } + else if (value_comp()(__rt->__value_, __k)) + __rt = static_cast<__node_pointer>(__rt->__right_); + else + return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__iter_pointer>(__rt)), + __upper_bound(__k, static_cast<__node_pointer>(__rt->__right_), __result)); + } + return _Pp(const_iterator(__result), const_iterator(__result)); +} + +template +typename __tree<_Tp, _Compare, _Allocator>::__node_holder +__tree<_Tp, _Compare, _Allocator>::remove(const_iterator __p) _NOEXCEPT +{ + __node_pointer __np = __p.__get_np(); + if (__begin_node() == __p.__ptr_) + { + if (__np->__right_ != nullptr) + __begin_node() = static_cast<__iter_pointer>(__np->__right_); + else + __begin_node() = static_cast<__iter_pointer>(__np->__parent_); + } + --size(); + __tree_remove(__end_node()->__left_, + static_cast<__node_base_pointer>(__np)); + return __node_holder(__np, _Dp(__node_alloc(), true)); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +void +swap(__tree<_Tp, _Compare, _Allocator>& __x, + __tree<_Tp, _Compare, _Allocator>& __y) + _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) +{ + __x.swap(__y); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___TREE diff --git a/sdk/tlibcxx/include/__tuple b/sdk/tlibcxx/include/__tuple new file mode 100644 index 00000000..cc9fbbeb --- /dev/null +++ b/sdk/tlibcxx/include/__tuple @@ -0,0 +1,438 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___TUPLE +#define _LIBCPP___TUPLE + +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class _LIBCPP_TYPE_VIS_ONLY tuple_size; + +template +class _LIBCPP_TYPE_VIS_ONLY tuple_size + : public tuple_size<_Tp> {}; + +template +class _LIBCPP_TYPE_VIS_ONLY tuple_size + : public tuple_size<_Tp> {}; + +template +class _LIBCPP_TYPE_VIS_ONLY tuple_size + : public tuple_size<_Tp> {}; + +template class _LIBCPP_TYPE_VIS_ONLY tuple_element; + +template +class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, const _Tp> +{ +public: + typedef typename add_const::type>::type type; +}; + +template +class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, volatile _Tp> +{ +public: + typedef typename add_volatile::type>::type type; +}; + +template +class _LIBCPP_TYPE_VIS_ONLY tuple_element<_Ip, const volatile _Tp> +{ +public: + typedef typename add_cv::type>::type type; +}; + +template struct __tuple_like : false_type {}; + +template struct __tuple_like : public __tuple_like<_Tp> {}; +template struct __tuple_like : public __tuple_like<_Tp> {}; +template struct __tuple_like : public __tuple_like<_Tp> {}; + +// tuple specializations + +#if !defined(_LIBCPP_HAS_NO_VARIADICS) + +template struct __tuple_indices {}; + +template +struct __integer_sequence { + template