37 changes: 3 additions & 34 deletions clang/utils/TableGen/ClangAttrEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1591,18 +1591,18 @@ writePrettyPrintFunction(const Record &R,
std::string Variety = Spellings[I].variety();

if (Variety == "GNU") {
Prefix = " __attribute__((";
Prefix = "__attribute__((";
Suffix = "))";
} else if (Variety == "CXX11" || Variety == "C23") {
Prefix = " [[";
Prefix = "[[";
Suffix = "]]";
std::string Namespace = Spellings[I].nameSpace();
if (!Namespace.empty()) {
Spelling += Namespace;
Spelling += "::";
}
} else if (Variety == "Declspec") {
Prefix = " __declspec(";
Prefix = "__declspec(";
Suffix = ")";
} else if (Variety == "Microsoft") {
Prefix = "[";
Expand Down Expand Up @@ -3316,37 +3316,6 @@ void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS) {
OS << "#undef PRAGMA_SPELLING_ATTR\n";
}

// Emits the enumeration list for attributes.
void EmitClangAttrPrintList(const std::string &FieldName, RecordKeeper &Records,
raw_ostream &OS) {
emitSourceFileHeader(
"List of attributes that can be print on the left side of a decl", OS,
Records);

AttrClassHierarchy Hierarchy(Records);

std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
std::vector<Record *> PragmaAttrs;
bool first = false;

for (auto *Attr : Attrs) {
if (!Attr->getValueAsBit("ASTNode"))
continue;

if (!Attr->getValueAsBit(FieldName))
continue;

if (!first) {
first = true;
OS << "#define CLANG_ATTR_LIST_" << FieldName;
}

OS << " \\\n case attr::" << Attr->getName() << ":";
}

OS << '\n';
}

// Emits the enumeration list for attributes.
void EmitClangAttrSubjectMatchRuleList(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader(
Expand Down
16 changes: 0 additions & 16 deletions clang/utils/TableGen/TableGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ enum ActionType {
GenClangAttrSubjectMatchRulesParserStringSwitches,
GenClangAttrImpl,
GenClangAttrList,
GenClangAttrCanPrintLeftList,
GenClangAttrMustPrintLeftList,
GenClangAttrDocTable,
GenClangAttrSubjectMatchRuleList,
GenClangAttrPCHRead,
Expand Down Expand Up @@ -134,14 +132,6 @@ cl::opt<ActionType> Action(
"Generate clang attribute implementations"),
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
"Generate a clang attribute list"),
clEnumValN(GenClangAttrCanPrintLeftList,
"gen-clang-attr-can-print-left-list",
"Generate list of attributes that can be printed on left "
"side of a decl"),
clEnumValN(GenClangAttrMustPrintLeftList,
"gen-clang-attr-must-print-left-list",
"Generate list of attributes that must be printed on left "
"side of a decl"),
clEnumValN(GenClangAttrDocTable, "gen-clang-attr-doc-table",
"Generate a table of attribute documentation"),
clEnumValN(GenClangAttrSubjectMatchRuleList,
Expand Down Expand Up @@ -345,12 +335,6 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenClangAttrList:
EmitClangAttrList(Records, OS);
break;
case GenClangAttrCanPrintLeftList:
EmitClangAttrPrintList("CanPrintOnLeft", Records, OS);
break;
case GenClangAttrMustPrintLeftList:
EmitClangAttrPrintList("PrintOnLeft", Records, OS);
break;
case GenClangAttrDocTable:
EmitClangAttrDocTable(Records, OS);
break;
Expand Down
2 changes: 0 additions & 2 deletions clang/utils/TableGen/TableGenBackends.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ void EmitClangAttrSubjectMatchRulesParserStringSwitches(
void EmitClangAttrClass(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrImpl(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrList(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrPrintList(const std::string &FieldName,
llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
void EmitClangAttrSubjectMatchRuleList(llvm::RecordKeeper &Records,
llvm::raw_ostream &OS);
void EmitClangAttrPCHRead(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
Expand Down
5 changes: 4 additions & 1 deletion clang/www/c_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,7 @@ <h2 id="c11">C11 implementation status</h2>
<tr>
<td>Conditional normative status for Annex G</td>
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1514.pdf">N1514</a></td>
<td class="unknown" align="center">Unknown</td>
<td class="full" align="center">Yes <a href="#annex-g">(1)</a></td>
</tr>
<tr>
<td>Creation of complex value</td>
Expand Down Expand Up @@ -606,6 +606,9 @@ <h2 id="c11">C11 implementation status</h2>
<td class="unknown" align="center">Unknown</td>
</tr>
</table>
<span id="annex-g">(1): Clang does not implement Annex G, so our conditional support
conforms by not defining the <code>__STDC_IEC_559_COMPLEX__</code> macro.
</span>
</details>

<h2 id="c17">C17 implementation status</h2>
Expand Down
12 changes: 2 additions & 10 deletions clang/www/cxx_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -544,16 +544,8 @@ <h2 id="cxx20">C++20 implementation status</h2>
</tr>
<tr> <!-- from Cologne -->
<td><a href="https://wg21.link/p0848r3">P0848R3</a></td>
<td rowspan="1" class="partial" align="center">
<details>
<summary>Clang 16 (Partial)</summary>
Because of other concepts implementation deficits, the __cpp_concepts macro is not yet set to 202002L.
Also, the related defect reports <a href="https://wg21.link/cwg1496">DR1496</a> and
<a href="https://wg21.link/cwg1734">DR1734</a> are not yet implemented. Accordingly, deleted
special member functions are treated as eligible even though they shouldn't be.
</details>
</td>
</tr>
<td rowspan="1" class="full" align="center">Clang 19</td>
</tr>
<tr>
<td><a href="https://wg21.link/p1616r1">P1616R1</a></td>
<td rowspan="2" class="full" align="center">Clang 10</td>
Expand Down
54 changes: 34 additions & 20 deletions compiler-rt/lib/memprof/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,47 @@ if(NOT WIN32)
list(APPEND MEMPROF_UNITTEST_LINK_FLAGS -pthread)
endif()

set(MEMPROF_UNITTEST_DEPS)
if (TARGET cxx-headers OR HAVE_LIBCXX)
list(APPEND MEMPROF_UNITTEST_DEPS cxx-headers)
endif()

set(MEMPROF_UNITTEST_LINK_LIBRARIES
${COMPILER_RT_UNWINDER_LINK_LIBS}
${SANITIZER_TEST_CXX_LIBRARIES})
list(APPEND MEMPROF_UNITTEST_LINK_LIBRARIES "dl")

if(COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST MEMPROF_SUPPORTED_ARCH)
# MemProf unit tests are only run on the host machine.
set(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH})
append_list_if(COMPILER_RT_HAS_LIBDL -ldl MEMPROF_UNITTEST_LINK_LIBRARIES)

add_executable(MemProfUnitTests
${MEMPROF_UNITTESTS}
${COMPILER_RT_GTEST_SOURCE}
${COMPILER_RT_GMOCK_SOURCE}
${MEMPROF_SOURCES}
# Adds memprof tests for each architecture.
macro(add_memprof_tests_for_arch arch)
set(MEMPROF_TEST_RUNTIME_OBJECTS
$<TARGET_OBJECTS:RTSanitizerCommon.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonCoverage.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizer.${arch}>
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizerInternal.${arch}>)
set_target_compile_flags(MemProfUnitTests ${MEMPROF_UNITTEST_CFLAGS})
set_target_link_flags(MemProfUnitTests ${MEMPROF_UNITTEST_LINK_FLAGS})
target_link_libraries(MemProfUnitTests ${MEMPROF_UNITTEST_LINK_LIBRARIES})

if (TARGET cxx-headers OR HAVE_LIBCXX)
add_dependencies(MemProfUnitTests cxx-headers)
endif()
$<TARGET_OBJECTS:RTSanitizerCommonSymbolizerInternal.${arch}>
)
set(MEMPROF_TEST_RUNTIME RTMemProfTest.${arch})
add_library(${MEMPROF_TEST_RUNTIME} STATIC ${MEMPROF_TEST_RUNTIME_OBJECTS})
set_target_properties(${MEMPROF_TEST_RUNTIME} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
FOLDER "Compiler-RT Runtime tests")
set(MEMPROF_TEST_OBJECTS)
generate_compiler_rt_tests(MEMPROF_TEST_OBJECTS
MemProfUnitTests "MemProf-${arch}-UnitTest" ${arch}
RUNTIME ${MEMPROF_TEST_RUNTIME}
DEPS ${MEMPROF_UNITTEST_DEPS}
SOURCES ${MEMPROF_UNITTESTS} ${MEMPROF_SOURCES} ${COMPILER_RT_GTEST_SOURCE}
COMPILE_DEPS ${MEMPROF_UNIT_TEST_HEADERS}
CFLAGS ${MEMPROF_UNITTEST_CFLAGS}
LINK_FLAGS ${MEMPROF_UNITTEST_LINK_FLAGS} ${MEMPROF_UNITTEST_LINK_LIBRARIES})
endmacro()

set_target_properties(MemProfUnitTests PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
# MemProf unit tests testsuite.
add_custom_target(MemProfUnitTests)
set_target_properties(MemProfUnitTests PROPERTIES FOLDER "Compiler-RT Tests")
if(COMPILER_RT_CAN_EXECUTE_TESTS AND COMPILER_RT_DEFAULT_TARGET_ARCH IN_LIST MEMPROF_SUPPORTED_ARCH)
# MemProf unit tests are only run on the host machine.
foreach(arch ${COMPILER_RT_DEFAULT_TARGET_ARCH})
add_memprof_tests_for_arch(${arch})
endforeach()
endif()
7 changes: 6 additions & 1 deletion compiler-rt/lib/scudo/standalone/allocator_config.def
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,14 @@ PRIMARY_REQUIRED(const s32, MaxReleaseToOsIntervalMs)
// PRIMARY_OPTIONAL(TYPE, NAME, DEFAULT)
//
// Indicates support for offsetting the start of a region by a random number of
// pages. Only used with primary64.
// pages. This is only used if `EnableContiguousRegions` is enabled.
PRIMARY_OPTIONAL(const bool, EnableRandomOffset, false)

// When `EnableContiguousRegions` is true, all regions will be be arranged in
// adjacency. This will reduce the fragmentation caused by region allocations
// but may require a huge amount of contiguous pages at initialization.
PRIMARY_OPTIONAL(const bool, EnableContiguousRegions, true)

// PRIMARY_OPTIONAL_TYPE(NAME, DEFAULT)
//
// Use condition variable to shorten the waiting time of refillment of
Expand Down
117 changes: 76 additions & 41 deletions compiler-rt/lib/scudo/standalone/primary64.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,40 +117,30 @@ template <typename Config> class SizeClassAllocator64 {
SmallerBlockReleasePageDelta =
PagesInGroup * (1 + MinSizeClass / 16U) / 100;

// Reserve the space required for the Primary.
CHECK(ReservedMemory.create(/*Addr=*/0U, PrimarySize,
"scudo:primary_reserve"));
PrimaryBase = ReservedMemory.getBase();
DCHECK_NE(PrimaryBase, 0U);

u32 Seed;
const u64 Time = getMonotonicTimeFast();
if (!getRandom(reinterpret_cast<void *>(&Seed), sizeof(Seed)))
Seed = static_cast<u32>(Time ^ (PrimaryBase >> 12));
Seed = static_cast<u32>(Time ^ (reinterpret_cast<uptr>(&Seed) >> 12));

for (uptr I = 0; I < NumClasses; I++) {
RegionInfo *Region = getRegionInfo(I);
for (uptr I = 0; I < NumClasses; I++)
getRegionInfo(I)->RandState = getRandomU32(&Seed);

// The actual start of a region is offset by a random number of pages
// when PrimaryEnableRandomOffset is set.
Region->RegionBeg = (PrimaryBase + (I << RegionSizeLog)) +
(Config::getEnableRandomOffset()
? ((getRandomModN(&Seed, 16) + 1) * PageSize)
: 0);
Region->RandState = getRandomU32(&Seed);
// Releasing small blocks is expensive, set a higher threshold to avoid
// frequent page releases.
if (isSmallBlock(getSizeByClassId(I)))
Region->TryReleaseThreshold = PageSize * SmallerBlockReleasePageDelta;
else
Region->TryReleaseThreshold = PageSize;
Region->ReleaseInfo.LastReleaseAtNs = Time;
if (Config::getEnableContiguousRegions()) {
ReservedMemoryT ReservedMemory = {};
// Reserve the space required for the Primary.
CHECK(ReservedMemory.create(/*Addr=*/0U, RegionSize * NumClasses,
"scudo:primary_reserve"));
const uptr PrimaryBase = ReservedMemory.getBase();

for (uptr I = 0; I < NumClasses; I++) {
MemMapT RegionMemMap = ReservedMemory.dispatch(
PrimaryBase + (I << RegionSizeLog), RegionSize);
RegionInfo *Region = getRegionInfo(I);

Region->MemMapInfo.MemMap = ReservedMemory.dispatch(
PrimaryBase + (I << RegionSizeLog), RegionSize);
CHECK(Region->MemMapInfo.MemMap.isAllocated());
initRegion(Region, I, RegionMemMap, Config::getEnableRandomOffset());
}
shuffle(RegionInfoArray, NumClasses, &Seed);
}
shuffle(RegionInfoArray, NumClasses, &Seed);

// The binding should be done after region shuffling so that it won't bind
// the FLLock from the wrong region.
Expand All @@ -160,14 +150,17 @@ template <typename Config> class SizeClassAllocator64 {
setOption(Option::ReleaseInterval, static_cast<sptr>(ReleaseToOsInterval));
}

void unmapTestOnly() NO_THREAD_SAFETY_ANALYSIS {
void unmapTestOnly() {
for (uptr I = 0; I < NumClasses; I++) {
RegionInfo *Region = getRegionInfo(I);
{
ScopedLock ML(Region->MMLock);
MemMapT MemMap = Region->MemMapInfo.MemMap;
if (MemMap.isAllocated())
MemMap.unmap(MemMap.getBase(), MemMap.getCapacity());
}
*Region = {};
}
if (PrimaryBase)
ReservedMemory.release();
PrimaryBase = 0U;
}

// When all blocks are freed, it has to be the same size as `AllocatedUser`.
Expand Down Expand Up @@ -251,9 +244,10 @@ template <typename Config> class SizeClassAllocator64 {
}

const bool RegionIsExhausted = Region->Exhausted;
if (!RegionIsExhausted)
if (!RegionIsExhausted) {
PopCount = populateFreeListAndPopBlocks(C, ClassId, Region, ToArray,
MaxBlockCount);
}
ReportRegionExhausted = !RegionIsExhausted && Region->Exhausted;
break;
}
Expand Down Expand Up @@ -514,7 +508,6 @@ template <typename Config> class SizeClassAllocator64 {
private:
static const uptr RegionSize = 1UL << RegionSizeLog;
static const uptr NumClasses = SizeClassMap::NumClasses;
static const uptr PrimarySize = RegionSize * NumClasses;

static const uptr MapSizeIncrement = Config::getMapSizeIncrement();
// Fill at most this number of batches from the newly map'd memory.
Expand Down Expand Up @@ -570,9 +563,14 @@ template <typename Config> class SizeClassAllocator64 {
}

uptr getRegionBaseByClassId(uptr ClassId) {
return roundDown(getRegionInfo(ClassId)->RegionBeg - PrimaryBase,
RegionSize) +
PrimaryBase;
RegionInfo *Region = getRegionInfo(ClassId);
Region->MMLock.assertHeld();

if (!Config::getEnableContiguousRegions() &&
!Region->MemMapInfo.MemMap.isAllocated()) {
return 0U;
}
return Region->MemMapInfo.MemMap.getBase();
}

static CompactPtrT compactPtrInternal(uptr Base, uptr Ptr) {
Expand Down Expand Up @@ -602,6 +600,30 @@ template <typename Config> class SizeClassAllocator64 {
return BlockSize > PageSize;
}

ALWAYS_INLINE void initRegion(RegionInfo *Region, uptr ClassId,
MemMapT MemMap, bool EnableRandomOffset)
REQUIRES(Region->MMLock) {
DCHECK(!Region->MemMapInfo.MemMap.isAllocated());
DCHECK(MemMap.isAllocated());

const uptr PageSize = getPageSizeCached();

Region->MemMapInfo.MemMap = MemMap;

Region->RegionBeg = MemMap.getBase();
if (EnableRandomOffset) {
Region->RegionBeg +=
(getRandomModN(&Region->RandState, 16) + 1) * PageSize;
}

// Releasing small blocks is expensive, set a higher threshold to avoid
// frequent page releases.
if (isSmallBlock(getSizeByClassId(ClassId)))
Region->TryReleaseThreshold = PageSize * SmallerBlockReleasePageDelta;
else
Region->TryReleaseThreshold = PageSize;
}

void pushBatchClassBlocks(RegionInfo *Region, CompactPtrT *Array, u32 Size)
REQUIRES(Region->FLLock) {
DCHECK_EQ(Region, getRegionInfo(SizeClassMap::BatchClassId));
Expand Down Expand Up @@ -989,9 +1011,26 @@ template <typename Config> class SizeClassAllocator64 {
CompactPtrT *ToArray,
const u16 MaxBlockCount)
REQUIRES(Region->MMLock) EXCLUDES(Region->FLLock) {
if (!Config::getEnableContiguousRegions() &&
!Region->MemMapInfo.MemMap.isAllocated()) {
ReservedMemoryT ReservedMemory;
if (UNLIKELY(!ReservedMemory.create(/*Addr=*/0U, RegionSize,
"scudo:primary_reserve",
MAP_ALLOWNOMEM))) {
Printf("Can't reserve pages for size class %zu.\n",
getSizeByClassId(ClassId));
Region->Exhausted = true;
return 0U;
}
initRegion(Region, ClassId,
ReservedMemory.dispatch(ReservedMemory.getBase(),
ReservedMemory.getCapacity()),
/*EnableRandomOffset=*/false);
}

DCHECK(Region->MemMapInfo.MemMap.isAllocated());
const uptr Size = getSizeByClassId(ClassId);
const u16 MaxCount = CacheT::getMaxCached(Size);

const uptr RegionBeg = Region->RegionBeg;
const uptr MappedUser = Region->MemMapInfo.MappedUser;
const uptr TotalUserBytes =
Expand Down Expand Up @@ -1683,10 +1722,6 @@ template <typename Config> class SizeClassAllocator64 {
Region->FLLockCV.notifyAll(Region->FLLock);
}

// TODO: `PrimaryBase` can be obtained from ReservedMemory. This needs to be
// deprecated.
uptr PrimaryBase = 0;
ReservedMemoryT ReservedMemory = {};
// The minimum size of pushed blocks that we will try to release the pages in
// that size class.
uptr SmallerBlockReleasePageDelta = 0;
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/scudo/standalone/tests/primary_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ template <typename SizeClassMapT> struct TestConfig3 {
static const scudo::s32 MaxReleaseToOsIntervalMs = INT32_MAX;
typedef scudo::uptr CompactPtrT;
static const scudo::uptr CompactPtrScale = 0;
static const bool EnableContiguousRegions = false;
static const bool EnableRandomOffset = true;
static const scudo::uptr MapSizeIncrement = 1UL << 18;
};
Expand Down
3 changes: 2 additions & 1 deletion flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1097,7 +1097,8 @@ struct ProcComponentDefStmt {
// R736 component-def-stmt -> data-component-def-stmt | proc-component-def-stmt
struct ComponentDefStmt {
UNION_CLASS_BOILERPLATE(ComponentDefStmt);
std::variant<DataComponentDefStmt, ProcComponentDefStmt, ErrorRecovery
std::variant<DataComponentDefStmt, ProcComponentDefStmt,
common::Indirection<CompilerDirective>, ErrorRecovery
// , TypeParamDefStmt -- PGI accidental extension, not enabled
>
u;
Expand Down
10 changes: 10 additions & 0 deletions flang/include/flang/Semantics/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ inline bool IsCUDADeviceContext(const Scope *scope) {
return false;
}

inline bool HasCUDAAttr(const Symbol &sym) {
if (const auto *details{
sym.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()}) {
if (details->cudaDataAttr()) {
return true;
}
}
return false;
}

const Scope *FindCUDADeviceContext(const Scope *);
std::optional<common::CUDADataAttr> GetCUDADataAttr(const Symbol *);

Expand Down
3 changes: 3 additions & 0 deletions flang/lib/Lower/Allocatable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,9 @@ class AllocateStmtHelper {
}

void lowerAllocation(const Allocation &alloc) {
if (Fortran::semantics::HasCUDAAttr(alloc.getSymbol()))
TODO(loc, "Allocation of variable with CUDA attributes");

fir::MutableBoxValue boxAddr =
genMutableBoxValue(converter, loc, alloc.getAllocObj());

Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Optimizer/Transforms/AddDebugFoundation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ void AddDebugFoundationPass::runOnOperation() {
mlir::LLVM::DIFileAttr fileAttr = getFileAttr(inputFilePath);
mlir::StringAttr producer = mlir::StringAttr::get(context, "Flang");
mlir::LLVM::DICompileUnitAttr cuAttr = mlir::LLVM::DICompileUnitAttr::get(
context, mlir::DistinctAttr::create(mlir::UnitAttr::get(context)),
mlir::DistinctAttr::create(mlir::UnitAttr::get(context)),
llvm::dwarf::getLanguage("DW_LANG_Fortran95"), fileAttr, producer,
/*isOptimized=*/false, mlir::LLVM::DIEmissionKind::LineTablesOnly);

Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Parser/Fortran-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,8 @@ TYPE_PARSER(construct<TypeParamDecl>(name, maybe("=" >> scalarIntConstantExpr)))
TYPE_PARSER(recovery(
withMessage("expected component definition"_err_en_US,
first(construct<ComponentDefStmt>(Parser<DataComponentDefStmt>{}),
construct<ComponentDefStmt>(Parser<ProcComponentDefStmt>{}))),
construct<ComponentDefStmt>(Parser<ProcComponentDefStmt>{}),
construct<ComponentDefStmt>(indirect(compilerDirective)))),
construct<ComponentDefStmt>(inStmtErrorRecovery)))

// R737 data-component-def-stmt ->
Expand Down
4 changes: 4 additions & 0 deletions flang/test/Parser/compiler-directives.f90
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ module m
!dir$ optimize : 1
!dir$ loop count (10000)
!dir$ loop count (1, 500, 5000, 10000)
type stuff
real(8), allocatable :: d(:)
!dir$ align : 1024 :: d
end type stuff
end
9 changes: 9 additions & 0 deletions libc/hdr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,12 @@ add_proxy_header_library(
libc.include.llvm-libc-macros.math_macros
libc.include.math
)

add_proxy_header_library(
fenv_macros
HDRS
fenv_macros.h
FULL_BUILD_DEPENDS
libc.include.llvm-libc-macros.fenv_macros
libc.incude.fenv
)
22 changes: 22 additions & 0 deletions libc/hdr/fenv_macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Definition of macros from fenv.h ----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_HDR_FENV_MACROS_H
#define LLVM_LIBC_HDR_FENV_MACROS_H

#ifdef LIBC_FULL_BUILD

#include "include/llvm-libc-macros/fenv-macros.h"

#else // Overlay mode

#include <fenv.h>

#endif // LLVM_LIBC_FULL_BUILD

#endif // LLVM_LIBC_HDR_FENV_MACROS_H
3 changes: 2 additions & 1 deletion libc/src/__support/FPUtil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_header_library(
FEnvImpl.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.hdr.math_macros
libc.src.__support.macros.attributes
libc.src.errno.errno
Expand All @@ -14,7 +15,7 @@ add_header_library(
HDRS
rounding_mode.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.macros.attributes
libc.src.__support.macros.properties.architectures
libc.src.__support.macros.sanitizer
Expand Down
1 change: 1 addition & 0 deletions libc/src/__support/FPUtil/aarch64/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <fenv.h>
#include <stdint.h>

#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/FPBits.h"

namespace LIBC_NAMESPACE {
Expand Down
1 change: 1 addition & 0 deletions libc/src/__support/FPUtil/aarch64/fenv_darwin_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <fenv.h>
#include <stdint.h>

#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/FPBits.h"

namespace LIBC_NAMESPACE {
Expand Down
2 changes: 1 addition & 1 deletion libc/src/__support/FPUtil/arm/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_ARM_FENVIMPL_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ARM_FENVIMPL_H

#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/macros/attributes.h" // For LIBC_INLINE

#include <fenv.h>
#include <stdint.h>

Expand Down
1 change: 0 additions & 1 deletion libc/src/__support/FPUtil/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ add_header_library(
sqrt.h
sqrt_80_bit_long_double.h
DEPENDS
libc.include.fenv
libc.src.__support.common
libc.src.__support.CPP.bit
libc.src.__support.CPP.type_traits
Expand Down
1 change: 1 addition & 0 deletions libc/src/__support/FPUtil/riscv/FEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_RISCV_FENVIMPL_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_RISCV_FENVIMPL_H

#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/macros/attributes.h" // For LIBC_INLINE_ASM
#include "src/__support/macros/config.h" // For LIBC_INLINE
Expand Down
3 changes: 1 addition & 2 deletions libc/src/__support/FPUtil/rounding_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_ROUNDING_MODE_H

#include "hdr/fenv_macros.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE

#include <fenv.h>

namespace LIBC_NAMESPACE::fputil {

// Quick free-standing test whether fegetround() == FE_UPWARD.
Expand Down
28 changes: 14 additions & 14 deletions libc/src/fenv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ add_entrypoint_object(
HDRS
fesetround.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -31,7 +31,7 @@ add_entrypoint_object(
HDRS
feclearexcept.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -44,7 +44,7 @@ add_entrypoint_object(
HDRS
feraiseexcept.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -57,7 +57,7 @@ add_entrypoint_object(
HDRS
fetestexcept.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -70,7 +70,7 @@ add_entrypoint_object(
HDRS
fegetenv.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -83,7 +83,7 @@ add_entrypoint_object(
HDRS
fesetenv.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -96,7 +96,7 @@ add_entrypoint_object(
HDRS
fegetexceptflag.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -109,7 +109,7 @@ add_entrypoint_object(
HDRS
fesetexcept.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -122,7 +122,7 @@ add_entrypoint_object(
HDRS
fesetexceptflag.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -135,7 +135,7 @@ add_entrypoint_object(
HDRS
feholdexcept.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -148,7 +148,7 @@ add_entrypoint_object(
HDRS
feupdateenv.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -161,7 +161,7 @@ add_entrypoint_object(
HDRS
feenableexcept.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -174,7 +174,7 @@ add_entrypoint_object(
HDRS
fedisableexcept.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand All @@ -187,7 +187,7 @@ add_entrypoint_object(
HDRS
fegetexcept.h
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.__support.FPUtil.fenv_impl
COMPILE_OPTIONS
-O2
Expand Down
1 change: 0 additions & 1 deletion libc/src/fenv/feholdexcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include "src/fenv/feholdexcept.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/common.h"

#include <fenv.h>

namespace LIBC_NAMESPACE {
Expand Down
1 change: 0 additions & 1 deletion libc/src/fenv/fesetexceptflag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include "src/fenv/fesetexceptflag.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/common.h"

#include <fenv.h>

namespace LIBC_NAMESPACE {
Expand Down
2 changes: 1 addition & 1 deletion libc/test/UnitTest/RoundingModeUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "src/__support/FPUtil/FEnvImpl.h"
#include "src/__support/FPUtil/rounding_mode.h"

#include <fenv.h>
#include "hdr/fenv_macros.h"

namespace LIBC_NAMESPACE {
namespace fputil {
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/__support/FPUtil/rounding_mode_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

#include <fenv.h>
#include "hdr/fenv_macros.h"

using LIBC_NAMESPACE::testing::mpfr::ForceRoundingMode;
using LIBC_NAMESPACE::testing::mpfr::RoundingMode;
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/fenv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ if (NOT (LLVM_USE_SANITIZER OR (${LIBC_TARGET_OS} STREQUAL "windows")
SRCS
feholdexcept_test.cpp
DEPENDS
libc.include.fenv
libc.hdr.fenv_macros
libc.src.fenv.feholdexcept
libc.src.__support.FPUtil.fenv_impl
LINK_LIBRARIES
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/fenv/enabled_exceptions_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "test/UnitTest/FPExceptMatcher.h"
#include "test/UnitTest/Test.h"

#include <fenv.h>
#include "hdr/fenv_macros.h"
#include <signal.h>

// This test enables an exception and verifies that raising that exception
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/fenv/exception_status_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include "src/__support/FPUtil/FEnvImpl.h"
#include "test/UnitTest/Test.h"

#include <fenv.h>
#include "hdr/fenv_macros.h"

TEST(LlvmLibcExceptionStatusTest, RaiseAndTest) {
// This test raises a set of exceptions and checks that the exception
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/fenv/feclearexcept_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "src/__support/FPUtil/FEnvImpl.h"
#include "test/UnitTest/Test.h"

#include <fenv.h>
#include "hdr/fenv_macros.h"
#include <stdint.h>

TEST(LlvmLibcFEnvTest, ClearTest) {
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/fenv/feenableexcept_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "test/UnitTest/Test.h"

#include <fenv.h>
#include "hdr/fenv_macros.h"

TEST(LlvmLibcFEnvTest, EnableTest) {
#if defined(LIBC_TARGET_ARCH_IS_ANY_ARM) || \
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/fenv/rounding_mode_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#include "test/UnitTest/Test.h"

#include <fenv.h>
#include "hdr/fenv_macros.h"

TEST(LlvmLibcRoundingModeTest, SetAndGet) {
struct ResetDefaultRoundingMode {
Expand Down
2 changes: 2 additions & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1271,6 +1271,7 @@ add_fp_unittest(
DEPENDS
libc.src.math.fmaf
libc.src.stdlib.rand
libc.src.stdlib.srand
libc.src.__support.FPUtil.fp_bits
FLAGS
FMA_OPT__ONLY
Expand All @@ -1286,6 +1287,7 @@ add_fp_unittest(
DEPENDS
libc.src.math.fma
libc.src.stdlib.rand
libc.src.stdlib.srand
libc.src.__support.FPUtil.fp_bits
)

Expand Down
3 changes: 3 additions & 0 deletions libc/test/src/math/FmaTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "src/__support/FPUtil/FPBits.h"
#include "src/stdlib/rand.h"
#include "src/stdlib/srand.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"
Expand Down Expand Up @@ -76,6 +77,7 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test {
void test_subnormal_range(Func func) {
constexpr StorageType COUNT = 100'001;
constexpr StorageType STEP = (MAX_SUBNORMAL - MIN_SUBNORMAL) / COUNT;
LIBC_NAMESPACE::srand(1);
for (StorageType v = MIN_SUBNORMAL, w = MAX_SUBNORMAL;
v <= MAX_SUBNORMAL && w >= MIN_SUBNORMAL; v += STEP, w -= STEP) {
T x = FPBits(get_random_bit_pattern()).get_val(), y = FPBits(v).get_val(),
Expand All @@ -89,6 +91,7 @@ class FmaTestTemplate : public LIBC_NAMESPACE::testing::Test {
void test_normal_range(Func func) {
constexpr StorageType COUNT = 100'001;
constexpr StorageType STEP = (MAX_NORMAL - MIN_NORMAL) / COUNT;
LIBC_NAMESPACE::srand(1);
for (StorageType v = MIN_NORMAL, w = MAX_NORMAL;
v <= MAX_NORMAL && w >= MIN_NORMAL; v += STEP, w -= STEP) {
T x = FPBits(v).get_val(), y = FPBits(w).get_val(),
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/math/RIntTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

#include "hdr/fenv_macros.h"
#include "hdr/math_macros.h"
#include <fenv.h>
#include <stdio.h>

namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/math/smoke/NextTowardTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
#ifndef LLVM_LIBC_TEST_SRC_MATH_NEXTTOWARDTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_NEXTTOWARDTEST_H

#include "hdr/fenv_macros.h"
#include "hdr/math_macros.h"
#include "src/__support/CPP/bit.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include <fenv.h>

#define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception) \
ASSERT_FP_EQ(result, expected); \
Expand Down
2 changes: 1 addition & 1 deletion libc/test/src/math/smoke/RIntTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

#include "hdr/fenv_macros.h"
#include "hdr/math_macros.h"
#include <fenv.h>
#include <stdio.h>

static constexpr int ROUNDING_MODES[4] = {FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO,
Expand Down
1 change: 0 additions & 1 deletion libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#include "test/UnitTest/FPMatcher.h"

#include "hdr/math_macros.h"
#include <fenv.h>
#include <memory>
#include <stdint.h>

Expand Down
4 changes: 1 addition & 3 deletions libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_associative_heterogeneous_erasure`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_bind_back`` *unimplemented*
``__cpp_lib_bind_back`` ``202202L``
---------------------------------------------------------- -----------------
``__cpp_lib_byteswap`` ``202110L``
---------------------------------------------------------- -----------------
Expand Down Expand Up @@ -398,8 +398,6 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_atomic_min_max`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_bind_back`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_bind_front`` ``202306L``
---------------------------------------------------------- -----------------
``__cpp_lib_bitset`` ``202306L``
Expand Down
8 changes: 7 additions & 1 deletion libcxx/docs/ReleaseNotes/19.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Improvements and New Features
resulting in a performance increase of up to 1400x.
- The ``std::mismatch`` algorithm has been optimized for integral types, which can lead up to 40x performance
improvements.

- The ``std::ranges::minmax`` algorithm has been optimized for integral types, resulting in a performance increase of
up to 100x.

Expand All @@ -64,6 +65,8 @@ Improvements and New Features
- The ``_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT`` macro has been added to make the declarations in ``<locale>``
available.

- The formatting library is updated to Unicode 15.1.0.

Deprecations and Removals
-------------------------

Expand Down Expand Up @@ -117,7 +120,10 @@ TODO

ABI Affecting Changes
---------------------
TODO

- The optional POSIX macro ``ENODATA`` has been deprecated in C++ and POSIX 2017. The
``random_device`` could throw a ``system_error`` with this value. It now
throws ``ENOMSG``.


Build System Changes
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/Status/Cxx23.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Paper Status
.. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented.
.. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but
clang doesn't issue a diagnostic for deprecated using template declarations.
.. [#note-P2387R3] P2387R3: ``bind_back`` only
.. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
.. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
.. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"`P1413R3 <https://wg21.link/P1413R3>`__","LWG","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","February 2022","|Complete| [#note-P1413R3]_",""
"`P2255R2 <https://wg21.link/P2255R2>`__","LWG","A type trait to detect reference binding to temporary","February 2022","",""
"`P2273R3 <https://wg21.link/P2273R3>`__","LWG","Making ``std::unique_ptr`` constexpr","February 2022","|Complete|","16.0"
"`P2387R3 <https://wg21.link/P2387R3>`__","LWG","Pipe support for user-defined range adaptors","February 2022","","","|ranges|"
"`P2387R3 <https://wg21.link/P2387R3>`__","LWG","Pipe support for user-defined range adaptors","February 2022","|Partial| [#note-P2387R3]_","","|ranges|"
"`P2440R1 <https://wg21.link/P2440R1>`__","LWG","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","February 2022","","","|ranges|"
"`P2441R2 <https://wg21.link/P2441R2>`__","LWG","``views::join_with``","February 2022","|In Progress|","","|ranges|"
"`P2442R1 <https://wg21.link/P2442R1>`__","LWG","Windowing range adaptors: ``views::chunk`` and ``views::slide``","February 2022","","","|ranges|"
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cIssues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"`4023 <https://wg21.link/LWG4023>`__","Preconditions of ``std::basic_streambuf::setg/setp``","Tokyo March 2024","","",""
"`4025 <https://wg21.link/LWG4025>`__","Move assignment operator of ``std::expected<cv void, E>`` should not be conditionally deleted","Tokyo March 2024","","",""
"`4030 <https://wg21.link/LWG4030>`__","Clarify whether arithmetic expressions in ``[numeric.sat.func]`` are mathematical or C++","Tokyo March 2024","|Nothing To Do|","",""
"`4031 <https://wg21.link/LWG4031>`__","``bad_expected_access<void>`` member functions should be ``noexcept``","Tokyo March 2024","","",""
"`4031 <https://wg21.link/LWG4031>`__","``bad_expected_access<void>`` member functions should be ``noexcept``","Tokyo March 2024","|Complete|","16.0",""
"`4035 <https://wg21.link/LWG4035>`__","``single_view`` should provide ``empty``","Tokyo March 2024","","","|ranges|"
"`4036 <https://wg21.link/LWG4036>`__","``__alignof_is_defined`` is only implicitly specified in C++ and not yet deprecated","Tokyo March 2024","","",""
"`4037 <https://wg21.link/LWG4037>`__","Static data members of ``ctype_base`` are not yet required to be usable in constant expressions","Tokyo March 2024","","",""
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ set(files
__format/formatter_pointer.h
__format/formatter_string.h
__format/formatter_tuple.h
__format/indic_conjunct_break_table.h
__format/parser_std_format_spec.h
__format/range_default_formatter.h
__format/range_formatter.h
Expand Down
12 changes: 6 additions & 6 deletions libcxx/include/__expected/bad_expected_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wweak-vtables")
template <>
class bad_expected_access<void> : public exception {
protected:
_LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) = default;
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access() noexcept = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access(const bad_expected_access&) noexcept = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access(bad_expected_access&&) noexcept = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(const bad_expected_access&) noexcept = default;
_LIBCPP_HIDE_FROM_ABI bad_expected_access& operator=(bad_expected_access&&) noexcept = default;
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~bad_expected_access() override = default;

public:
// The way this has been designed (by using a class template below) means that we'll already
Expand Down
11 changes: 6 additions & 5 deletions libcxx/include/__format/escaped_output_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ namespace __escaped_output_table {
/// - bits [0, 10] The size of the range, allowing 2048 elements.
/// - bits [11, 31] The lower bound code point of the range. The upper bound of
/// the range is lower bound + size.
_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[893] = {
_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[894] = {
0x00000020,
0x0003f821,
0x00056800,
Expand Down Expand Up @@ -464,14 +464,14 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[893] = {
0x0174d000,
0x0177a00b,
0x017eb019,
0x017fe004,
0x01800000,
0x01815005,
0x01820000,
0x0184b803,
0x01880004,
0x01898000,
0x018c7800,
0x018f200b,
0x018f200a,
0x0190f800,
0x05246802,
0x05263808,
Expand Down Expand Up @@ -1000,8 +1000,9 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[893] = {
0x15b9d005,
0x15c0f001,
0x1675100d,
0x175f0fff,
0x179f0c1e,
0x175f080e,
0x1772f7ff,
0x17b2f1a1,
0x17d0f5e1,
0x189a5804};

Expand Down
350 changes: 350 additions & 0 deletions libcxx/include/__format/indic_conjunct_break_table.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,350 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// WARNING, this entire header is generated by
// utils/generate_indic_conjunct_break_table.py
// DO NOT MODIFY!

// UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
//
// See Terms of Use <https://www.unicode.org/copyright.html>
// for definitions of Unicode Inc.'s Data Files and Software.
//
// NOTICE TO USER: Carefully read the following legal agreement.
// BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
// DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
// YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
// TERMS AND CONDITIONS OF THIS AGREEMENT.
// IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
// THE DATA FILES OR SOFTWARE.
//
// COPYRIGHT AND PERMISSION NOTICE
//
// Copyright (c) 1991-2022 Unicode, Inc. All rights reserved.
// Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of the Unicode data files and any associated documentation
// (the "Data Files") or Unicode software and any associated documentation
// (the "Software") to deal in the Data Files or Software
// without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, and/or sell copies of
// the Data Files or Software, and to permit persons to whom the Data Files
// or Software are furnished to do so, provided that either
// (a) this copyright and permission notice appear with all copies
// of the Data Files or Software, or
// (b) this copyright and permission notice appear in associated
// Documentation.
//
// THE DATA FILES AND SOFTWARE ARE 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 OF THIRD PARTY RIGHTS.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
// NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
// DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
// TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THE DATA FILES OR SOFTWARE.
//
// Except as contained in this notice, the name of a copyright holder
// shall not be used in advertising or otherwise to promote the sale,
// use or other dealings in these Data Files or Software without prior
// written authorization of the copyright holder.

#ifndef _LIBCPP___FORMAT_INDIC_CONJUNCT_BREAK_TABLE_H
#define _LIBCPP___FORMAT_INDIC_CONJUNCT_BREAK_TABLE_H

#include <__algorithm/ranges_upper_bound.h>
#include <__config>
#include <__iterator/access.h>
#include <cstddef>
#include <cstdint>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 20

namespace __indic_conjunct_break {

enum class __property : uint8_t {
// Values generated from the data files.
__Consonant,
__Extend,
__Linker,

// The code unit has none of above properties.
__none
};

/// The entries of the indic conjunct break property table.
///
/// The data is generated from
/// - https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt
///
/// The data has 3 values
/// - bits [0, 1] The property. One of the values generated from the datafiles
/// of \ref __property
/// - bits [2, 10] The size of the range.
/// - bits [11, 31] The lower bound code point of the range. The upper bound of
/// the range is lower bound + size.
///
/// The 9 bits for the size allow a maximum range of 512 elements. Some ranges
/// in the Unicode tables are larger. They are stored in multiple consecutive
/// ranges in the data table. An alternative would be to store the sizes in a
/// separate 16-bit value. The original MSVC STL code had such an approach, but
/// this approach uses less space for the data and is about 4% faster in the
/// following benchmark.
/// libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp
// clang-format off
_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[201] = {
0x00180139,
0x001a807d,
0x00241811,
0x002c88b1,
0x002df801,
0x002e0805,
0x002e2005,
0x002e3801,
0x00308029,
0x00325851,
0x00338001,
0x0036b019,
0x0036f815,
0x00373805,
0x0037500d,
0x00388801,
0x00398069,
0x003f5821,
0x003fe801,
0x0040b00d,
0x0040d821,
0x00412809,
0x00414811,
0x0042c809,
0x0044c01d,
0x0046505d,
0x00471871,
0x0048a890,
0x0049e001,
0x004a6802,
0x004a880d,
0x004ac01c,
0x004bc01c,
0x004ca84c,
0x004d5018,
0x004d9000,
0x004db00c,
0x004de001,
0x004e6802,
0x004ee004,
0x004ef800,
0x004f8004,
0x004ff001,
0x0051e001,
0x0054a84c,
0x00555018,
0x00559004,
0x0055a810,
0x0055e001,
0x00566802,
0x0057c800,
0x0058a84c,
0x00595018,
0x00599004,
0x0059a810,
0x0059e001,
0x005a6802,
0x005ae004,
0x005af800,
0x005b8800,
0x0060a84c,
0x0061503c,
0x0061e001,
0x00626802,
0x0062a805,
0x0062c008,
0x0065e001,
0x0068a894,
0x0069d805,
0x006a6802,
0x0071c009,
0x0072400d,
0x0075c009,
0x0076400d,
0x0078c005,
0x0079a801,
0x0079b801,
0x0079c801,
0x007b8805,
0x007ba001,
0x007bd00d,
0x007c0001,
0x007c1009,
0x007c3005,
0x007e3001,
0x0081b801,
0x0081c805,
0x00846801,
0x009ae809,
0x00b8a001,
0x00be9001,
0x00bee801,
0x00c54801,
0x00c9c809,
0x00d0b805,
0x00d30001,
0x00d3a81d,
0x00d3f801,
0x00d58035,
0x00d5f83d,
0x00d9a001,
0x00db5821,
0x00dd5801,
0x00df3001,
0x00e1b801,
0x00e68009,
0x00e6a031,
0x00e71019,
0x00e76801,
0x00e7a001,
0x00e7c005,
0x00ee00fd,
0x01006801,
0x01068031,
0x01070801,
0x0107282d,
0x01677809,
0x016bf801,
0x016f007d,
0x01815015,
0x0184c805,
0x05337801,
0x0533a025,
0x0534f005,
0x05378005,
0x05416001,
0x05470045,
0x05495809,
0x054d9801,
0x05558001,
0x05559009,
0x0555b805,
0x0555f005,
0x05560801,
0x0557b001,
0x055f6801,
0x07d8f001,
0x07f1003d,
0x080fe801,
0x08170001,
0x081bb011,
0x08506801,
0x08507801,
0x0851c009,
0x0851f801,
0x08572805,
0x0869200d,
0x08755805,
0x0877e809,
0x087a3029,
0x087c100d,
0x08838001,
0x0883f801,
0x0885d001,
0x08880009,
0x08899805,
0x088b9801,
0x088e5001,
0x0891b001,
0x08974805,
0x0899d805,
0x089b3019,
0x089b8011,
0x08a23001,
0x08a2f001,
0x08a61801,
0x08ae0001,
0x08b5b801,
0x08b95801,
0x08c1d001,
0x08c9f001,
0x08ca1801,
0x08d1a001,
0x08d23801,
0x08d4c801,
0x08ea1001,
0x08ea2005,
0x08ecb801,
0x08fa1001,
0x0b578011,
0x0b598019,
0x0de4f001,
0x0e8b2801,
0x0e8b3809,
0x0e8b7011,
0x0e8bd81d,
0x0e8c2819,
0x0e8d500d,
0x0e921009,
0x0f000019,
0x0f004041,
0x0f00d819,
0x0f011805,
0x0f013011,
0x0f047801,
0x0f098019,
0x0f157001,
0x0f17600d,
0x0f27600d,
0x0f468019,
0x0f4a2019};
// clang-format on

/// Returns the indic conjuct break property of a code point.
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __property __get_property(const char32_t __code_point) noexcept {
// The algorithm searches for the upper bound of the range and, when found,
// steps back one entry. This algorithm is used since the code point can be
// anywhere in the range. After a lower bound is found the next step is to
// compare whether the code unit is indeed in the range.
//
// Since the entry contains a code unit, size, and property the code point
// being sought needs to be adjusted. Just shifting the code point to the
// proper position doesn't work; suppose an entry has property 0, size 1,
// and lower bound 3. This results in the entry 0x1810.
// When searching for code point 3 it will search for 0x1800, find 0x1810
// and moves to the previous entry. Thus the lower bound value will never
// be found.
// The simple solution is to set the bits belonging to the property and
// size. Then the upper bound for code point 3 will return the entry after
// 0x1810. After moving to the previous entry the algorithm arrives at the
// correct entry.
ptrdiff_t __i = std::ranges::upper_bound(__entries, (__code_point << 11) | 0x7ffu) - __entries;
if (__i == 0)
return __property::__none;

--__i;
uint32_t __upper_bound = (__entries[__i] >> 11) + ((__entries[__i] >> 2) & 0b1'1111'1111);
if (__code_point <= __upper_bound)
return static_cast<__property>(__entries[__i] & 0b11);

return __property::__none;
}

} // namespace __indic_conjunct_break

#endif //_LIBCPP_STD_VER >= 20

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___FORMAT_INDIC_CONJUNCT_BREAK_TABLE_H
313 changes: 218 additions & 95 deletions libcxx/include/__format/unicode.h

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions libcxx/include/__format/width_estimation_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ namespace __width_estimation_table {
/// - bits [0, 13] The size of the range, allowing 16384 elements.
/// - bits [14, 31] The lower bound code point of the range. The upper bound of
/// the range is lower bound + size.
_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[108] = {
_LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[107] = {
0x0440005f /* 00001100 - 0000115f [ 96] */, //
0x08c68001 /* 0000231a - 0000231b [ 2] */, //
0x08ca4001 /* 00002329 - 0000232a [ 2] */, //
Expand Down Expand Up @@ -158,14 +158,13 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr uint32_t __entries[108] = {
0x0ba00019 /* 00002e80 - 00002e99 [ 26] */, //
0x0ba6c058 /* 00002e9b - 00002ef3 [ 89] */, //
0x0bc000d5 /* 00002f00 - 00002fd5 [ 214] */, //
0x0bfc000b /* 00002ff0 - 00002ffb [ 12] */, //
0x0c00003e /* 00003000 - 0000303e [ 63] */, //
0x0bfc004e /* 00002ff0 - 0000303e [ 79] */, //
0x0c104055 /* 00003041 - 00003096 [ 86] */, //
0x0c264066 /* 00003099 - 000030ff [ 103] */, //
0x0c41402a /* 00003105 - 0000312f [ 43] */, //
0x0c4c405d /* 00003131 - 0000318e [ 94] */, //
0x0c640053 /* 00003190 - 000031e3 [ 84] */, //
0x0c7c002e /* 000031f0 - 0000321e [ 47] */, //
0x0c7bc02f /* 000031ef - 0000321e [ 48] */, //
0x0c880027 /* 00003220 - 00003247 [ 40] */, //
0x0c943fff /* 00003250 - 0000724f [16384] */, //
0x1c94323c /* 00007250 - 0000a48c [12861] */, //
Expand Down
14 changes: 14 additions & 0 deletions libcxx/include/__functional/bind_back.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) n
std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...));
}

# if _LIBCPP_STD_VER >= 23
template <class _Fn, class... _Args>
_LIBCPP_HIDE_FROM_ABI constexpr auto bind_back(_Fn&& __f, _Args&&... __args) {
static_assert(is_constructible_v<decay_t<_Fn>, _Fn>, "bind_back requires decay_t<F> to be constructible from F");
static_assert(is_move_constructible_v<decay_t<_Fn>>, "bind_back requires decay_t<F> to be move constructible");
static_assert((is_constructible_v<decay_t<_Args>, _Args> && ...),
"bind_back requires all decay_t<Args> to be constructible from respective Args");
static_assert((is_move_constructible_v<decay_t<_Args>> && ...),
"bind_back requires all decay_t<Args> to be move constructible");
return __bind_back_t<decay_t<_Fn>, tuple<decay_t<_Args>...>>(
std::forward<_Fn>(__f), std::forward_as_tuple(std::forward<_Args>(__args)...));
}
# endif // _LIBCPP_STD_VER >= 23

#endif // _LIBCPP_STD_VER >= 20

_LIBCPP_END_NAMESPACE_STD
Expand Down
6 changes: 6 additions & 0 deletions libcxx/include/functional
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ binary_negate<Predicate> not2(const Predicate& pred);
template <class F>
constexpr unspecified not_fn(F&& f); // C++17, constexpr in C++20
// [func.bind.partial], function templates bind_front and bind_back
template<class F, class... Args>
constexpr unspecified bind_front(F&&, Args&&...); // C++20
template<class F, class... Args>
constexpr unspecified bind_back(F&&, Args&&...); // C++23
template<class T> struct is_bind_expression;
template<class T> struct is_placeholder;
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/libcxx.imp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@
{ include: [ "<__format/formatter_pointer.h>", "private", "<format>", "public" ] },
{ include: [ "<__format/formatter_string.h>", "private", "<format>", "public" ] },
{ include: [ "<__format/formatter_tuple.h>", "private", "<format>", "public" ] },
{ include: [ "<__format/indic_conjunct_break_table.h>", "private", "<format>", "public" ] },
{ include: [ "<__format/parser_std_format_spec.h>", "private", "<format>", "public" ] },
{ include: [ "<__format/range_default_formatter.h>", "private", "<format>", "public" ] },
{ include: [ "<__format/range_formatter.h>", "private", "<format>", "public" ] },
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -1339,12 +1339,14 @@ module std_private_format_formatter_output [system] { header "__f
module std_private_format_formatter_pointer [system] { header "__format/formatter_pointer.h" }
module std_private_format_formatter_string [system] { header "__format/formatter_string.h" }
module std_private_format_formatter_tuple [system] { header "__format/formatter_tuple.h" }
module std_private_format_indic_conjunct_break_table [system] { header "__format/indic_conjunct_break_table.h" }
module std_private_format_parser_std_format_spec [system] { header "__format/parser_std_format_spec.h" }
module std_private_format_range_default_formatter [system] { header "__format/range_default_formatter.h" }
module std_private_format_range_formatter [system] { header "__format/range_formatter.h" }
module std_private_format_unicode [system] {
header "__format/unicode.h"
export std_private_format_extended_grapheme_cluster_table
export std_private_format_indic_conjunct_break_table
}
module std_private_format_width_estimation_table [system] { header "__format/width_estimation_table.h" }
module std_private_format_write_escaped [system] { header "__format/write_escaped.h" }
Expand Down
7 changes: 2 additions & 5 deletions libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ __cpp_lib_atomic_shared_ptr 201711L <atomic>
__cpp_lib_atomic_value_initialization 201911L <atomic> <memory>
__cpp_lib_atomic_wait 201907L <atomic>
__cpp_lib_barrier 201907L <barrier>
__cpp_lib_bind_back 202306L <functional>
202202L // C++23
__cpp_lib_bind_back 202202L <functional>
__cpp_lib_bind_front 202306L <functional>
201907L // C++20
__cpp_lib_bit_cast 201806L <bit>
Expand Down Expand Up @@ -449,7 +448,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
# define __cpp_lib_adaptor_iterator_pair_constructor 202106L
# define __cpp_lib_allocate_at_least 202302L
// # define __cpp_lib_associative_heterogeneous_erasure 202110L
// # define __cpp_lib_bind_back 202202L
# define __cpp_lib_bind_back 202202L
# define __cpp_lib_byteswap 202110L
# define __cpp_lib_constexpr_bitset 202207L
# define __cpp_lib_constexpr_charconv 202207L
Expand Down Expand Up @@ -498,8 +497,6 @@ __cpp_lib_within_lifetime 202306L <type_traits>
#if _LIBCPP_STD_VER >= 26
// # define __cpp_lib_associative_heterogeneous_insertion 202306L
// # define __cpp_lib_atomic_min_max 202403L
# undef __cpp_lib_bind_back
// # define __cpp_lib_bind_back 202306L
# undef __cpp_lib_bind_front
# define __cpp_lib_bind_front 202306L
# define __cpp_lib_bitset 202306L
Expand Down
4 changes: 3 additions & 1 deletion libcxx/modules/std/functional.inc
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ export namespace std {
using std::not_fn;

// [func.bind.partial], function templates bind_front and bind_back
// using std::bind_back;
using std::bind_front;
#if _LIBCPP_STD_VER >= 23
using std::bind_back;
#endif

// [func.bind], bind
using std::is_bind_expression;
Expand Down
4 changes: 1 addition & 3 deletions libcxx/src/random.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,8 @@ unsigned random_device::operator()() {
char* p = reinterpret_cast<char*>(&r);
while (n > 0) {
ssize_t s = read(__f_, p, n);
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
if (s == 0)
__throw_system_error(ENODATA, "random_device got EOF"); // TODO ENODATA -> ENOMSG
_LIBCPP_SUPPRESS_DEPRECATED_POP
__throw_system_error(ENOMSG, "random_device got EOF");
if (s == -1) {
if (errno != EINTR)
__throw_system_error(errno, "random_device got an unexpected error");
Expand Down
6 changes: 5 additions & 1 deletion libcxx/src/tzdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,8 +717,12 @@ void __init_tzdb(tzdb& __tzdb, __tz::__rules_storage_type& __rules) {
std::__throw_runtime_error("tzdb: the path '/etc/localtime' is not a symlink");

filesystem::path __tz = filesystem::read_symlink(__path);
string __name = filesystem::relative(__tz, "/usr/share/zoneinfo/");
// The path may be a relative path, in that case convert it to an absolute
// path based on the proper initial directory.
if (__tz.is_relative())
__tz = filesystem::canonical("/etc" / __tz);

string __name = filesystem::relative(__tz, "/usr/share/zoneinfo/");
if (const time_zone* __result = tzdb.__locate_zone(__name))
return __result;

Expand Down
30 changes: 30 additions & 0 deletions libcxx/test/libcxx/fuzzing/format_no_args.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: no-exceptions

// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME

// XFAIL: availability-fp_to_chars-missing

#include <cstdint>
#include <format>
#include <string_view>

#include "fuzz.h"

extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, std::size_t size) {
try {
[[maybe_unused]] auto result = std::vformat(std::string_view{(const char*)(data), size}, std::make_format_args());
} catch (std::format_error const&) {
// If the fuzzing input isn't a valid thing we can format and we detect it, it's okay. We are looking for crashes.
return 0;
}
return 0;
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ static_assert(count_entries(cluster::__property::__LVT) == 10773);
static_assert(count_entries(cluster::__property::__ZWJ) == 1);
static_assert(count_entries(cluster::__property::__Extended_Pictographic) == 3537);

namespace inCB = std::__indic_conjunct_break;
constexpr int count_entries(inCB::__property property) {
return std::transform_reduce(
std::begin(inCB::__entries), std::end(inCB::__entries), 0, std::plus{}, [property](auto entry) {
if (static_cast<inCB::__property>(entry & 0b11) != property)
return 0;

return 1 + static_cast<int>((entry >> 2) & 0b1'1111'1111);
});
}

static_assert(count_entries(inCB::__property::__Linker) == 6);
static_assert(count_entries(inCB::__property::__Consonant) == 240);
static_assert(count_entries(inCB::__property::__Extend) == 884);

} // namespace

template <class Data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

/* Constant Value
__cpp_lib_bind_back 202202L [C++23]
202306L [C++26]
__cpp_lib_bind_front 201907L [C++20]
202306L [C++26]
__cpp_lib_boyer_moore_searcher 201603L [C++17]
Expand Down Expand Up @@ -337,17 +336,11 @@

#elif TEST_STD_VER == 23

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should be defined in c++23"
# endif
# if __cpp_lib_bind_back != 202202L
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should be defined in c++23"
# endif
# if __cpp_lib_bind_back != 202202L
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
# endif

# ifndef __cpp_lib_bind_front
Expand Down Expand Up @@ -447,17 +440,11 @@

#elif TEST_STD_VER > 23

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should be defined in c++26"
# endif
# if __cpp_lib_bind_back != 202306L
# error "__cpp_lib_bind_back should have the value 202306L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should be defined in c++26"
# endif
# if __cpp_lib_bind_back != 202202L
# error "__cpp_lib_bind_back should have the value 202202L in c++26"
# endif

# ifndef __cpp_lib_bind_front
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
__cpp_lib_atomic_wait 201907L [C++20]
__cpp_lib_barrier 201907L [C++20]
__cpp_lib_bind_back 202202L [C++23]
202306L [C++26]
__cpp_lib_bind_front 201907L [C++20]
202306L [C++26]
__cpp_lib_bit_cast 201806L [C++20]
Expand Down Expand Up @@ -4605,17 +4604,11 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should be defined in c++23"
# endif
# if __cpp_lib_bind_back != 202202L
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should be defined in c++23"
# endif
# if __cpp_lib_bind_back != 202202L
# error "__cpp_lib_bind_back should have the value 202202L in c++23"
# endif

# ifndef __cpp_lib_bind_front
Expand Down Expand Up @@ -6240,17 +6233,11 @@
# endif
# endif

# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should be defined in c++26"
# endif
# if __cpp_lib_bind_back != 202306L
# error "__cpp_lib_bind_back should have the value 202306L in c++26"
# endif
# else // _LIBCPP_VERSION
# ifdef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should not be defined because it is unimplemented in libc++!"
# endif
# ifndef __cpp_lib_bind_back
# error "__cpp_lib_bind_back should be defined in c++26"
# endif
# if __cpp_lib_bind_back != 202202L
# error "__cpp_lib_bind_back should have the value 202202L in c++26"
# endif

# ifndef __cpp_lib_bind_front
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,12 @@

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

// const char* what() const noexcept override;
// Make sure std::bad_expected_access<E> inherits from std::bad_expected_access<void>.

#include <expected>
#include <utility>
#include <type_traits>

template <class T>
concept WhatNoexcept =
requires(const T& t) {
{ t.what() } noexcept;
};
struct Foo {};

struct foo{};

static_assert(!WhatNoexcept<foo>);
static_assert(WhatNoexcept<std::bad_expected_access<int>>);
static_assert(WhatNoexcept<std::bad_expected_access<foo>>);
static_assert(std::is_base_of_v<std::bad_expected_access<void>, std::bad_expected_access<int>>);
static_assert(std::is_base_of_v<std::bad_expected_access<void>, std::bad_expected_access<Foo>>);
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//===----------------------------------------------------------------------===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

// template<>
// class bad_expected_access<void> : public exception {
// protected:
// bad_expected_access() noexcept;
// bad_expected_access(const bad_expected_access&) noexcept;
// bad_expected_access(bad_expected_access&&) noexcept;
// bad_expected_access& operator=(const bad_expected_access&) noexcept;
// bad_expected_access& operator=(bad_expected_access&&) noexcept;
// ~bad_expected_access();
//
// public:
// const char* what() const noexcept override;
// };

#include <cassert>
#include <exception>
#include <expected>
#include <type_traits>
#include <utility>

#include "test_macros.h"

struct Inherit : std::bad_expected_access<void> {};

int main(int, char**) {
// base class
static_assert(std::is_base_of_v<std::exception, std::bad_expected_access<void>>);

// default constructor
{
Inherit exc;
ASSERT_NOEXCEPT(Inherit());
}

// copy constructor
{
Inherit exc;
Inherit copy(exc);
ASSERT_NOEXCEPT(Inherit(exc));
}

// move constructor
{
Inherit exc;
Inherit copy(std::move(exc));
ASSERT_NOEXCEPT(Inherit(std::move(exc)));
}

// copy assignment
{
Inherit exc;
Inherit copy;
[[maybe_unused]] Inherit& result = (copy = exc);
ASSERT_NOEXCEPT(copy = exc);
}

// move assignment
{
Inherit exc;
Inherit copy;
[[maybe_unused]] Inherit& result = (copy = std::move(exc));
ASSERT_NOEXCEPT(copy = std::move(exc));
}

// what()
{
Inherit exc;
char const* what = exc.what();
assert(what != nullptr);
ASSERT_NOEXCEPT(exc.what());
}

return 0;
}
35 changes: 35 additions & 0 deletions libcxx/test/std/utilities/expected/expected.bad/what.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

// const char* what() const noexcept override;

#include <expected>
#include <cassert>
#include <utility>

#include "test_macros.h"

struct Foo {};

int main(int, char**) {
{
std::bad_expected_access<int> const exc(99);
char const* what = exc.what();
assert(what != nullptr);
ASSERT_NOEXCEPT(exc.what());
}
{
std::bad_expected_access<Foo> const exc(Foo{});
char const* what = exc.what();
assert(what != nullptr);
ASSERT_NOEXCEPT(exc.what());
}

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,381 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

// <functional>

// template<class F, class... Args>
// constexpr unspecified bind_back(F&& f, Args&&... args);

#include <functional>

#include <cassert>
#include <concepts>
#include <tuple>
#include <utility>

#include "callable_types.h"
#include "types.h"

constexpr void test_basic_bindings() {
{ // Bind arguments, call without arguments
{
auto f = std::bind_back(MakeTuple{});
assert(f() == std::make_tuple());
}
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{});
assert(f() == std::make_tuple(Elem<1>{}));
}
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
assert(f() == std::make_tuple(Elem<1>{}, Elem<2>{}));
}
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
assert(f() == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}));
}
}

{ // Bind no arguments, call with arguments
{
auto f = std::bind_back(MakeTuple{});
assert(f(Elem<1>{}) == std::make_tuple(Elem<1>{}));
}
{
auto f = std::bind_back(MakeTuple{});
assert(f(Elem<1>{}, Elem<2>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}));
}
{
auto f = std::bind_back(MakeTuple{});
assert(f(Elem<1>{}, Elem<2>{}, Elem<3>{}) == std::make_tuple(Elem<1>{}, Elem<2>{}, Elem<3>{}));
}
}

{ // Bind arguments, call with arguments
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{});
assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}));
}
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}, Elem<2>{}));
}
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
assert(f(Elem<10>{}) == std::make_tuple(Elem<10>{}, Elem<1>{}, Elem<2>{}, Elem<3>{}));
}

{
auto f = std::bind_back(MakeTuple{}, Elem<1>{});
assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}));
}
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{});
assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}, Elem<2>{}));
}
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
assert(f(Elem<10>{}, Elem<11>{}) == std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<1>{}, Elem<2>{}, Elem<3>{}));
}
{
auto f = std::bind_back(MakeTuple{}, Elem<1>{}, Elem<2>{}, Elem<3>{});
assert(f(Elem<10>{}, Elem<11>{}, Elem<12>{}) ==
std::make_tuple(Elem<10>{}, Elem<11>{}, Elem<12>{}, Elem<1>{}, Elem<2>{}, Elem<3>{}));
}
}

{ // Basic tests with fundamental types
int n = 2;
int m = 1;
int sum = 0;
auto add = [](int x, int y) { return x + y; };
auto add_n = [](int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f; };
auto add_ref = [&](int x, int y) -> int& { return sum = x + y; };
auto add_rref = [&](int x, int y) -> int&& { return std::move(sum = x + y); };

auto a = std::bind_back(add, m, n);
assert(a() == 3);

auto b = std::bind_back(add_n, m, n, m, m, m, m);
assert(b() == 7);

auto c = std::bind_back(add_n, n, m);
assert(c(1, 1, 1, 1) == 7);

auto d = std::bind_back(add_ref, n, m);
std::same_as<int&> decltype(auto) dresult(d());
assert(dresult == 3);

auto e = std::bind_back(add_rref, n, m);
std::same_as<int&&> decltype(auto) eresult(e());
assert(eresult == 3);

auto f = std::bind_back(add, n);
assert(f(3) == 5);

auto g = std::bind_back(add, n, 1);
assert(g() == 3);

auto h = std::bind_back(add_n, 1, 1, 1);
assert(h(2, 2, 2) == 9);

auto i = std::bind_back(add_ref, n);
std::same_as<int&> decltype(auto) iresult(i(5));
assert(iresult == 7);

auto j = std::bind_back(add_rref, m);
std::same_as<int&&> decltype(auto) jresult(j(4));
assert(jresult == 5);
}
}

constexpr void test_edge_cases() {
{ // Make sure we don't treat std::reference_wrapper specially.
auto sub = [](std::reference_wrapper<int> a, std::reference_wrapper<int> b) { return a.get() - b.get(); };

int i = 1;
int j = 2;
auto f = std::bind_back(sub, std::ref(i));
assert(f(std::ref(j)) == 1);
}

{ // Make sure we can call a function that's a pointer to a member function.
struct MemberFunction {
constexpr int foo(int x, int y) { return x * y; }
};

MemberFunction value;
auto fn = std::bind_back(&MemberFunction::foo, 2, 3);
assert(fn(value) == 6);
}

{ // Make sure we can call a function that's a pointer to a member object.
struct MemberObject {
int obj;
};

MemberObject value{.obj = 3};
auto fn = std::bind_back(&MemberObject::obj);
assert(fn(value) == 3);
}
}

constexpr void test_passing_arguments() {
{ // Make sure that we copy the bound arguments into the unspecified-type.
auto add = [](int x, int y) { return x + y; };
int n = 2;
auto f = std::bind_back(add, n, 1);
n = 100;
assert(f() == 3);
}

{ // Make sure we pass the bound arguments to the function object
// with the right value category.
{
auto was_copied = [](CopyMoveInfo info) { return info.copy_kind == CopyMoveInfo::copy; };
CopyMoveInfo info;
auto f = std::bind_back(was_copied, info);
assert(f());
}

{
auto was_moved = [](CopyMoveInfo info) { return info.copy_kind == CopyMoveInfo::move; };
CopyMoveInfo info;
auto f = std::bind_back(was_moved, info);
assert(std::move(f)());
}
}
}

constexpr void test_function_objects() {
{ // Make sure we call the correctly cv-ref qualified operator()
// based on the value category of the bind_back unspecified-type.
struct X {
constexpr int operator()() & { return 1; }
constexpr int operator()() const& { return 2; }
constexpr int operator()() && { return 3; }
constexpr int operator()() const&& { return 4; }
};

auto f = std::bind_back(X{});
using F = decltype(f);
assert(static_cast<F&>(f)() == 1);
assert(static_cast<const F&>(f)() == 2);
assert(static_cast<F&&>(f)() == 3);
assert(static_cast<const F&&>(f)() == 4);
}

// Make sure the `bind_back` unspecified-type does not model invocable
// when the call would select a differently-qualified operator().
//
// For example, if the call to `operator()() &` is ill-formed, the call to the unspecified-type
// should be ill-formed and not fall back to the `operator()() const&` overload.
{ // Make sure we delete the & overload when the underlying call isn't valid.
{
struct X {
void operator()() & = delete;
void operator()() const&;
void operator()() &&;
void operator()() const&&;
};

using F = decltype(std::bind_back(X{}));
static_assert(!std::invocable<F&>);
static_assert(std::invocable<const F&>);
static_assert(std::invocable<F>);
static_assert(std::invocable<const F>);
}

// There's no way to make sure we delete the const& overload when the underlying call isn't valid,
// so we can't check this one.

{ // Make sure we delete the && overload when the underlying call isn't valid.
struct X {
void operator()() &;
void operator()() const&;
void operator()() && = delete;
void operator()() const&&;
};

using F = decltype(std::bind_back(X{}));
static_assert(std::invocable<F&>);
static_assert(std::invocable<const F&>);
static_assert(!std::invocable<F>);
static_assert(std::invocable<const F>);
}

{ // Make sure we delete the const&& overload when the underlying call isn't valid.
struct X {
void operator()() &;
void operator()() const&;
void operator()() &&;
void operator()() const&& = delete;
};

using F = decltype(std::bind_back(X{}));
static_assert(std::invocable<F&>);
static_assert(std::invocable<const F&>);
static_assert(std::invocable<F>);
static_assert(!std::invocable<const F>);
}
}

{ // Extra value category tests
struct X {};

{
struct Y {
void operator()(X&&) const&;
void operator()(X&&) && = delete;
};

using F = decltype(std::bind_back(Y{}));
static_assert(std::invocable<F&, X>);
static_assert(!std::invocable<F, X>);
}

{
struct Y {
void operator()(const X&) const;
void operator()(X&&) const = delete;
};

using F = decltype(std::bind_back(Y{}, X{}));
static_assert(std::invocable<F&>);
static_assert(!std::invocable<F>);
}
}
}

constexpr void test_return_type() {
{ // Test properties of the constructor of the unspecified-type returned by bind_back.
{ // Test move constructor when function is move only.
MoveOnlyCallable<bool> value(true);
auto f = std::bind_back(std::move(value), 1);
assert(f());
assert(f(1, 2, 3));

auto f1 = std::move(f);
assert(!f());
assert(f1());
assert(f1(1, 2, 3));

using F = decltype(f);
static_assert(std::is_move_constructible<F>::value);
static_assert(!std::is_copy_constructible<F>::value);
static_assert(!std::is_move_assignable<F>::value);
static_assert(!std::is_copy_assignable<F>::value);
}

{ // Test move constructor when function is copyable but not assignable.
CopyCallable<bool> value(true);
auto f = std::bind_back(value, 1);
assert(f());
assert(f(1, 2, 3));

auto f1 = std::move(f);
assert(!f());
assert(f1());
assert(f1(1, 2, 3));

auto f2 = std::bind_back(std::move(value), 1);
assert(f1());
assert(f2());
assert(f2(1, 2, 3));

using F = decltype(f);
static_assert(std::is_move_constructible<F>::value);
static_assert(std::is_copy_constructible<F>::value);
static_assert(!std::is_move_assignable<F>::value);
static_assert(!std::is_copy_assignable<F>::value);
}

{ // Test constructors when function is copy assignable.
using F = decltype(std::bind_back(std::declval<CopyAssignableWrapper&>(), 1));
static_assert(std::is_move_constructible<F>::value);
static_assert(std::is_copy_constructible<F>::value);
static_assert(std::is_move_assignable<F>::value);
static_assert(std::is_copy_assignable<F>::value);
}

{ // Test constructors when function is move assignable only.
using F = decltype(std::bind_back(std::declval<MoveAssignableWrapper>(), 1));
static_assert(std::is_move_constructible<F>::value);
static_assert(!std::is_copy_constructible<F>::value);
static_assert(std::is_move_assignable<F>::value);
static_assert(!std::is_copy_assignable<F>::value);
}
}

{ // Make sure bind_back's unspecified type's operator() is SFINAE-friendly.
using F = decltype(std::bind_back(std::declval<int (*)(int, int)>(), 1));
static_assert(!std::is_invocable<F>::value);
static_assert(std::is_invocable<F, int>::value);
static_assert(!std::is_invocable<F, void*>::value);
static_assert(!std::is_invocable<F, int, int>::value);
}
}

constexpr bool test() {
test_basic_bindings();
test_edge_cases();
test_passing_arguments();
test_function_objects();
test_return_type();

return true;
}

int main(int, char**) {
test();
static_assert(test());

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20

// <functional>

// template<class F, class... Args>
// constexpr unspecified bind_back(F&& f, Args&&... args);

#include <functional>

#include "types.h"

constexpr int pass(int n) { return n; }

void test() {
{ // Test calling constexpr function from non-constexpr `bind_back` result
auto f1 = std::bind_back(pass, 1);
static_assert(f1() == 1); // expected-error {{static assertion expression is not an integral constant expression}}
}

{ // Test calling `bind_back` with template function
auto f1 = std::bind_back(do_nothing, 2);
// expected-error@-1 {{no matching function for call to 'bind_back'}}
}

{ // Mandates: is_constructible_v<decay_t<F>, F>
struct F {
F() = default;
F(const F&) = default;
F(F&) = delete;

void operator()() {}
};

F f;
auto f1 = std::bind_back(f);
// expected-error-re@*:* {{static assertion failed{{.*}}bind_back requires decay_t<F> to be constructible from F}}
}

{ // Mandates: is_move_constructible_v<decay_t<F>>
struct F {
F() = default;
F(const F&) = default;
F(F&&) = delete;

void operator()() {}
};

F f;
auto f1 = std::bind_back(f);
// expected-error-re@*:* {{static assertion failed{{.*}}bind_back requires decay_t<F> to be move constructible}}
}

{ // Mandates: (is_constructible_v<decay_t<Args>, Args> && ...)
struct Arg {
Arg() = default;
Arg(const Arg&) = default;
Arg(Arg&) = delete;
};

Arg x;
auto f = std::bind_back([](const Arg&) {}, x);
// expected-error-re@*:* {{static assertion failed{{.*}}bind_back requires all decay_t<Args> to be constructible from respective Args}}
// expected-error@*:* {{no matching constructor for initialization}}
}

{ // Mandates: (is_move_constructible_v<decay_t<Args>> && ...)
struct Arg {
Arg() = default;
Arg(const Arg&) = default;
Arg(Arg&&) = delete;
};

Arg x;
auto f = std::bind_back([](Arg&) {}, x);
// expected-error-re@*:* {{static assertion failed{{.*}}bind_back requires all decay_t<Args> to be move constructible}}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef TEST_STD_UTILITIES_FUNCTION_OBJECTS_FUNC_BIND_PARTIAL_TYPES_H
#define TEST_STD_UTILITIES_FUNCTION_OBJECTS_FUNC_BIND_PARTIAL_TYPES_H

#include <tuple>
#include <utility>

struct MakeTuple {
template <class... Args>
constexpr auto operator()(Args&&... args) const {
return std::make_tuple(std::forward<Args>(args)...);
}
};

template <int X>
struct Elem {
template <int Y>
constexpr bool operator==(const Elem<Y>&) const {
return X == Y;
}
};

struct CopyMoveInfo {
enum { none, copy, move } copy_kind;

constexpr CopyMoveInfo() : copy_kind(none) {}
constexpr CopyMoveInfo(const CopyMoveInfo&) : copy_kind(copy) {}
constexpr CopyMoveInfo(CopyMoveInfo&&) : copy_kind(move) {}
};

template <class T>
T do_nothing(T t) {
return t;
}

#endif // TEST_STD_UTILITIES_FUNCTION_OBJECTS_FUNC_BIND_PARTIAL_TYPES_H
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <functional>
#include <cassert>
#include <concepts>
#include <tuple>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -142,12 +143,13 @@ constexpr bool test() {

// Basic tests with fundamental types
{
int n = 2;
int m = 1;
auto add = [](int x, int y) { return x + y; };
auto addN = [](int a, int b, int c, int d, int e, int f) {
return a + b + c + d + e + f;
};
int n = 2;
int m = 1;
int sum = 0;
auto add = [](int x, int y) { return x + y; };
auto addN = [](int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f; };
auto add_ref = [&](int x, int y) -> int& { return sum = x + y; };
auto add_rref = [&](int x, int y) -> int&& { return std::move(sum = x + y); };

auto a = std::bind_front(add, m, n);
assert(a() == 3);
Expand All @@ -158,6 +160,14 @@ constexpr bool test() {
auto c = std::bind_front(addN, n, m);
assert(c(1, 1, 1, 1) == 7);

auto d = std::bind_front(add_ref, n, m);
std::same_as<int&> decltype(auto) dresult(d());
assert(dresult == 3);

auto e = std::bind_front(add_rref, n, m);
std::same_as<int&&> decltype(auto) eresult(e());
assert(eresult == 3);

auto f = std::bind_front(add, n);
assert(f(3) == 5);

Expand All @@ -166,6 +176,14 @@ constexpr bool test() {

auto h = std::bind_front(addN, 1, 1, 1);
assert(h(2, 2, 2) == 9);

auto i = std::bind_front(add_ref, n);
std::same_as<int&> decltype(auto) iresult(i(5));
assert(iresult == 7);

auto j = std::bind_front(add_rref, m);
std::same_as<int&&> decltype(auto) jresult(j(4));
assert(jresult == 5);
}

// Make sure we don't treat std::reference_wrapper specially.
Expand Down
8 changes: 8 additions & 0 deletions libcxx/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ add_custom_target(libcxx-generate-width-estimation-table
"${LIBCXX_SOURCE_DIR}/include/__format/width_estimation_table.h"
COMMENT "Generate the width estimation header")

add_custom_target(libcxx-indic-conjunct-break-table
COMMAND
"${Python3_EXECUTABLE}"
"${LIBCXX_SOURCE_DIR}/utils/generate_indic_conjunct_break_table.py"
"${LIBCXX_SOURCE_DIR}/include/__format/indic_conjunct_break_table.h"
COMMENT "Generate the Indic Conjunct Break header")

add_custom_target(libcxx-generate-iwyu-mapping
COMMAND
"${Python3_EXECUTABLE}"
Expand All @@ -63,5 +70,6 @@ add_custom_target(libcxx-generate-files
libcxx-generate-extended-grapheme-cluster-tests
libcxx-generate-escaped-output-table
libcxx-generate-width-estimation-table
libcxx-indic-conjunct-break-table
libcxx-generate-iwyu-mapping
COMMENT "Create all the auto-generated files in libc++ and its tests.")
Loading