Merge llvm-project release/16.x llvmorg-16.0.1-0-gcd89023f7979

This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-16.0.1-0-gcd89023f7979 (aka 16.0.1 release).

PR:		271047
MFC after:	1 month
This commit is contained in:
Dimitry Andric 2023-04-17 19:14:23 +02:00
commit 1ac55f4cb0
227 changed files with 5343 additions and 2409 deletions

View File

@ -34,7 +34,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 62
#define CINDEX_VERSION_MINOR 63
#define CINDEX_VERSION_ENCODE(major, minor) (((major)*10000) + ((minor)*1))

View File

@ -1052,7 +1052,7 @@ def err_lambda_template_parameter_list_empty : Error<
// C++2b static lambdas
def err_static_lambda: ExtWarn<
"static lambdas are a C++2b extension">, InGroup<CXX2b>;
def warn_cxx20_compat_static_lambda: ExtWarn<
def warn_cxx20_compat_static_lambda : Warning<
"static lambdas are incompatible with C++ standards before C++2b">,
InGroup<CXXPre2bCompat>, DefaultIgnore;
def err_static_mutable_lambda : Error<
@ -1607,11 +1607,6 @@ def err_import_in_wrong_fragment : Error<
def err_export_empty : Error<"export declaration cannot be empty">;
}
def ext_offsetof_member_designator : Extension<
"using %select{a member access expression|an array subscript expression}0 "
"within '%select{__builtin_offsetof|offsetof}1' is a Clang extension">,
InGroup<GNUOffsetofExtensions>;
let CategoryName = "Generics Issue" in {
def err_objc_expected_type_parameter : Error<

View File

@ -9138,8 +9138,9 @@ def err_operator_overload_static : Error<
def err_operator_overload_default_arg : Error<
"parameter of overloaded %0 cannot have a default argument">;
def ext_subscript_overload : ExtWarn<
"overloaded %0 with %select{no|a defaulted|more than one}1 parameter is a C++2b extension">, InGroup<CXXPre2bCompat>, DefaultIgnore;
def ext_subscript_overload : Warning<
"overloaded %0 with %select{no|a defaulted|more than one}1 parameter is a "
"C++2b extension">, InGroup<CXXPre2bCompat>, DefaultIgnore;
def error_subscript_overload : Error<
"overloaded %0 cannot have %select{no|a defaulted|more than one}1 parameter before C++2b">;

View File

@ -1249,16 +1249,37 @@ def SVZIP1_BF16 : SInst<"svzip1[_{d}]", "ddd", "b", MergeNone, "aarch64_sve
def SVZIP2_BF16 : SInst<"svzip2[_{d}]", "ddd", "b", MergeNone, "aarch64_sve_zip2">;
}
def SVREV_B : SInst<"svrev_{d}", "PP", "PcPsPiPl", MergeNone, "aarch64_sve_rev">;
def SVSEL_B : SInst<"svsel[_b]", "PPPP", "Pc", MergeNone, "aarch64_sve_sel">;
def SVTRN1_B : SInst<"svtrn1_{d}", "PPP", "PcPsPiPl", MergeNone, "aarch64_sve_trn1">;
def SVTRN2_B : SInst<"svtrn2_{d}", "PPP", "PcPsPiPl", MergeNone, "aarch64_sve_trn2">;
def SVPUNPKHI : SInst<"svunpkhi[_b]", "PP", "Pc", MergeNone, "aarch64_sve_punpkhi">;
def SVPUNPKLO : SInst<"svunpklo[_b]", "PP", "Pc", MergeNone, "aarch64_sve_punpklo">;
def SVUZP1_B : SInst<"svuzp1_{d}", "PPP", "PcPsPiPl", MergeNone, "aarch64_sve_uzp1">;
def SVUZP2_B : SInst<"svuzp2_{d}", "PPP", "PcPsPiPl", MergeNone, "aarch64_sve_uzp2">;
def SVZIP1_B : SInst<"svzip1_{d}", "PPP", "PcPsPiPl", MergeNone, "aarch64_sve_zip1">;
def SVZIP2_B : SInst<"svzip2_{d}", "PPP", "PcPsPiPl", MergeNone, "aarch64_sve_zip2">;
def SVREV_B8 : SInst<"svrev_b8", "PP", "Pc", MergeNone, "aarch64_sve_rev">;
def SVREV_B16 : SInst<"svrev_b16", "PP", "Pc", MergeNone, "aarch64_sve_rev_b16", [IsOverloadNone]>;
def SVREV_B32 : SInst<"svrev_b32", "PP", "Pc", MergeNone, "aarch64_sve_rev_b32", [IsOverloadNone]>;
def SVREV_B64 : SInst<"svrev_b64", "PP", "Pc", MergeNone, "aarch64_sve_rev_b64", [IsOverloadNone]>;
def SVSEL_B : SInst<"svsel[_b]", "PPPP", "Pc", MergeNone, "aarch64_sve_sel">;
def SVTRN1_B8 : SInst<"svtrn1_b8", "PPP", "Pc", MergeNone, "aarch64_sve_trn1">;
def SVTRN1_B16 : SInst<"svtrn1_b16", "PPP", "Pc", MergeNone, "aarch64_sve_trn1_b16", [IsOverloadNone]>;
def SVTRN1_B32 : SInst<"svtrn1_b32", "PPP", "Pc", MergeNone, "aarch64_sve_trn1_b32", [IsOverloadNone]>;
def SVTRN1_B64 : SInst<"svtrn1_b64", "PPP", "Pc", MergeNone, "aarch64_sve_trn1_b64", [IsOverloadNone]>;
def SVTRN2_B8 : SInst<"svtrn2_b8", "PPP", "Pc", MergeNone, "aarch64_sve_trn2">;
def SVTRN2_B16 : SInst<"svtrn2_b16", "PPP", "Pc", MergeNone, "aarch64_sve_trn2_b16", [IsOverloadNone]>;
def SVTRN2_B32 : SInst<"svtrn2_b32", "PPP", "Pc", MergeNone, "aarch64_sve_trn2_b32", [IsOverloadNone]>;
def SVTRN2_B64 : SInst<"svtrn2_b64", "PPP", "Pc", MergeNone, "aarch64_sve_trn2_b64", [IsOverloadNone]>;
def SVPUNPKHI : SInst<"svunpkhi[_b]", "PP", "Pc", MergeNone, "aarch64_sve_punpkhi">;
def SVPUNPKLO : SInst<"svunpklo[_b]", "PP", "Pc", MergeNone, "aarch64_sve_punpklo">;
def SVUZP1_B8 : SInst<"svuzp1_b8", "PPP", "Pc", MergeNone, "aarch64_sve_uzp1">;
def SVUZP1_B16 : SInst<"svuzp1_b16", "PPP", "Pc", MergeNone, "aarch64_sve_uzp1_b16", [IsOverloadNone]>;
def SVUZP1_B32 : SInst<"svuzp1_b32", "PPP", "Pc", MergeNone, "aarch64_sve_uzp1_b32", [IsOverloadNone]>;
def SVUZP1_B64 : SInst<"svuzp1_b64", "PPP", "Pc", MergeNone, "aarch64_sve_uzp1_b64", [IsOverloadNone]>;
def SVUZP2_B8 : SInst<"svuzp2_b8", "PPP", "Pc", MergeNone, "aarch64_sve_uzp2">;
def SVUZP2_B16 : SInst<"svuzp2_b16", "PPP", "Pc", MergeNone, "aarch64_sve_uzp2_b16", [IsOverloadNone]>;
def SVUZP2_B32 : SInst<"svuzp2_b32", "PPP", "Pc", MergeNone, "aarch64_sve_uzp2_b32", [IsOverloadNone]>;
def SVUZP2_B64 : SInst<"svuzp2_b64", "PPP", "Pc", MergeNone, "aarch64_sve_uzp2_b64", [IsOverloadNone]>;
def SVZIP1_B8 : SInst<"svzip1_b8", "PPP", "Pc", MergeNone, "aarch64_sve_zip1">;
def SVZIP1_B16 : SInst<"svzip1_b16", "PPP", "Pc", MergeNone, "aarch64_sve_zip1_b16", [IsOverloadNone]>;
def SVZIP1_B32 : SInst<"svzip1_b32", "PPP", "Pc", MergeNone, "aarch64_sve_zip1_b32", [IsOverloadNone]>;
def SVZIP1_B64 : SInst<"svzip1_b64", "PPP", "Pc", MergeNone, "aarch64_sve_zip1_b64", [IsOverloadNone]>;
def SVZIP2_B : SInst<"svzip2_b8", "PPP", "Pc", MergeNone, "aarch64_sve_zip2">;
def SVZIP2_B16 : SInst<"svzip2_b16", "PPP", "Pc", MergeNone, "aarch64_sve_zip2_b16", [IsOverloadNone]>;
def SVZIP2_B32 : SInst<"svzip2_b32", "PPP", "Pc", MergeNone, "aarch64_sve_zip2_b32", [IsOverloadNone]>;
def SVZIP2_B64 : SInst<"svzip2_b64", "PPP", "Pc", MergeNone, "aarch64_sve_zip2_b64", [IsOverloadNone]>;
////////////////////////////////////////////////////////////////////////////////
// Predicate creation

View File

@ -1539,7 +1539,7 @@ enum RVV_CSR {
};
static __inline__ __attribute__((__always_inline__, __nodebug__))
unsigned long vread_csr(enum RVV_CSR __csr) {
unsigned long __riscv_vread_csr(enum RVV_CSR __csr) {
unsigned long __rv = 0;
switch (__csr) {
case RVV_VSTART:
@ -1559,7 +1559,7 @@ unsigned long vread_csr(enum RVV_CSR __csr) {
}
static __inline__ __attribute__((__always_inline__, __nodebug__))
void vwrite_csr(enum RVV_CSR __csr, unsigned long __value) {
void __riscv_vwrite_csr(enum RVV_CSR __csr, unsigned long __value) {
switch (__csr) {
case RVV_VSTART:
__asm__ __volatile__ ("csrw\tvstart, %z0" : : "rJ"(__value) : "memory");
@ -1580,7 +1580,7 @@ def vread_vwrite_csr: RVVHeader;
let HeaderCode =
[{
#define vlenb() __builtin_rvv_vlenb()
#define __riscv_vlenb() __builtin_rvv_vlenb()
}] in
def vlenb_macro: RVVHeader;
@ -1611,62 +1611,62 @@ let HasBuiltinAlias = false, HasVL = false, HasMasked = false,
// and LMUL.
let HeaderCode =
[{
#define vsetvl_e8mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 6)
#define vsetvl_e8mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 7)
#define vsetvl_e8m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 0)
#define vsetvl_e8m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 1)
#define vsetvl_e8m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 2)
#define vsetvl_e8m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 3)
#define __riscv_vsetvl_e8mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 6)
#define __riscv_vsetvl_e8mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 7)
#define __riscv_vsetvl_e8m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 0)
#define __riscv_vsetvl_e8m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 1)
#define __riscv_vsetvl_e8m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 2)
#define __riscv_vsetvl_e8m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 3)
#define vsetvl_e16mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 7)
#define vsetvl_e16m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 0)
#define vsetvl_e16m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 1)
#define vsetvl_e16m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 2)
#define vsetvl_e16m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 3)
#define __riscv_vsetvl_e16mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 7)
#define __riscv_vsetvl_e16m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 0)
#define __riscv_vsetvl_e16m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 1)
#define __riscv_vsetvl_e16m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 2)
#define __riscv_vsetvl_e16m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 3)
#define vsetvl_e32m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 0)
#define vsetvl_e32m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 1)
#define vsetvl_e32m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 2)
#define vsetvl_e32m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 3)
#define __riscv_vsetvl_e32m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 0)
#define __riscv_vsetvl_e32m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 1)
#define __riscv_vsetvl_e32m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 2)
#define __riscv_vsetvl_e32m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 3)
#if __riscv_v_elen >= 64
#define vsetvl_e8mf8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 5)
#define vsetvl_e16mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 6)
#define vsetvl_e32mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 7)
#define __riscv_vsetvl_e8mf8(avl) __builtin_rvv_vsetvli((size_t)(avl), 0, 5)
#define __riscv_vsetvl_e16mf4(avl) __builtin_rvv_vsetvli((size_t)(avl), 1, 6)
#define __riscv_vsetvl_e32mf2(avl) __builtin_rvv_vsetvli((size_t)(avl), 2, 7)
#define vsetvl_e64m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 0)
#define vsetvl_e64m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 1)
#define vsetvl_e64m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 2)
#define vsetvl_e64m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 3)
#define __riscv_vsetvl_e64m1(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 0)
#define __riscv_vsetvl_e64m2(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 1)
#define __riscv_vsetvl_e64m4(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 2)
#define __riscv_vsetvl_e64m8(avl) __builtin_rvv_vsetvli((size_t)(avl), 3, 3)
#endif
#define vsetvlmax_e8mf4() __builtin_rvv_vsetvlimax(0, 6)
#define vsetvlmax_e8mf2() __builtin_rvv_vsetvlimax(0, 7)
#define vsetvlmax_e8m1() __builtin_rvv_vsetvlimax(0, 0)
#define vsetvlmax_e8m2() __builtin_rvv_vsetvlimax(0, 1)
#define vsetvlmax_e8m4() __builtin_rvv_vsetvlimax(0, 2)
#define vsetvlmax_e8m8() __builtin_rvv_vsetvlimax(0, 3)
#define __riscv_vsetvlmax_e8mf4() __builtin_rvv_vsetvlimax(0, 6)
#define __riscv_vsetvlmax_e8mf2() __builtin_rvv_vsetvlimax(0, 7)
#define __riscv_vsetvlmax_e8m1() __builtin_rvv_vsetvlimax(0, 0)
#define __riscv_vsetvlmax_e8m2() __builtin_rvv_vsetvlimax(0, 1)
#define __riscv_vsetvlmax_e8m4() __builtin_rvv_vsetvlimax(0, 2)
#define __riscv_vsetvlmax_e8m8() __builtin_rvv_vsetvlimax(0, 3)
#define vsetvlmax_e16mf2() __builtin_rvv_vsetvlimax(1, 7)
#define vsetvlmax_e16m1() __builtin_rvv_vsetvlimax(1, 0)
#define vsetvlmax_e16m2() __builtin_rvv_vsetvlimax(1, 1)
#define vsetvlmax_e16m4() __builtin_rvv_vsetvlimax(1, 2)
#define vsetvlmax_e16m8() __builtin_rvv_vsetvlimax(1, 3)
#define __riscv_vsetvlmax_e16mf2() __builtin_rvv_vsetvlimax(1, 7)
#define __riscv_vsetvlmax_e16m1() __builtin_rvv_vsetvlimax(1, 0)
#define __riscv_vsetvlmax_e16m2() __builtin_rvv_vsetvlimax(1, 1)
#define __riscv_vsetvlmax_e16m4() __builtin_rvv_vsetvlimax(1, 2)
#define __riscv_vsetvlmax_e16m8() __builtin_rvv_vsetvlimax(1, 3)
#define vsetvlmax_e32m1() __builtin_rvv_vsetvlimax(2, 0)
#define vsetvlmax_e32m2() __builtin_rvv_vsetvlimax(2, 1)
#define vsetvlmax_e32m4() __builtin_rvv_vsetvlimax(2, 2)
#define vsetvlmax_e32m8() __builtin_rvv_vsetvlimax(2, 3)
#define __riscv_vsetvlmax_e32m1() __builtin_rvv_vsetvlimax(2, 0)
#define __riscv_vsetvlmax_e32m2() __builtin_rvv_vsetvlimax(2, 1)
#define __riscv_vsetvlmax_e32m4() __builtin_rvv_vsetvlimax(2, 2)
#define __riscv_vsetvlmax_e32m8() __builtin_rvv_vsetvlimax(2, 3)
#if __riscv_v_elen >= 64
#define vsetvlmax_e8mf8() __builtin_rvv_vsetvlimax(0, 5)
#define vsetvlmax_e16mf4() __builtin_rvv_vsetvlimax(1, 6)
#define vsetvlmax_e32mf2() __builtin_rvv_vsetvlimax(2, 7)
#define __riscv_vsetvlmax_e8mf8() __builtin_rvv_vsetvlimax(0, 5)
#define __riscv_vsetvlmax_e16mf4() __builtin_rvv_vsetvlimax(1, 6)
#define __riscv_vsetvlmax_e32mf2() __builtin_rvv_vsetvlimax(2, 7)
#define vsetvlmax_e64m1() __builtin_rvv_vsetvlimax(3, 0)
#define vsetvlmax_e64m2() __builtin_rvv_vsetvlimax(3, 1)
#define vsetvlmax_e64m4() __builtin_rvv_vsetvlimax(3, 2)
#define vsetvlmax_e64m8() __builtin_rvv_vsetvlimax(3, 3)
#define __riscv_vsetvlmax_e64m1() __builtin_rvv_vsetvlimax(3, 0)
#define __riscv_vsetvlmax_e64m2() __builtin_rvv_vsetvlimax(3, 1)
#define __riscv_vsetvlmax_e64m4() __builtin_rvv_vsetvlimax(3, 2)
#define __riscv_vsetvlmax_e64m8() __builtin_rvv_vsetvlimax(3, 3)
#endif
}] in

View File

@ -4559,6 +4559,8 @@ def mnvs : Flag<["-"], "mnvs">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Enable generation of new-value stores">;
def mno_nvs : Flag<["-"], "mno-nvs">, Group<m_hexagon_Features_Group>,
Flags<[CC1Option]>, HelpText<"Disable generation of new-value stores">;
def mcabac: Flag<["-"], "mcabac">, Group<m_hexagon_Features_Group>,
HelpText<"Enable CABAC instructions">;
// SPARC feature flags
def mfpu : Flag<["-"], "mfpu">, Group<m_sparc_Features_Group>;

View File

@ -2500,6 +2500,10 @@ struct FormatStyle {
/// Decimal: 3
/// Hex: -1
/// \endcode
///
/// You can also specify a minimum number of digits (``BinaryMinDigits``,
/// ``DecimalMinDigits``, and ``HexMinDigits``) the integer literal must
/// have in order for the separators to be inserted.
struct IntegerLiteralSeparatorStyle {
/// Format separators in binary literals.
/// \code{.text}
@ -2509,6 +2513,14 @@ struct FormatStyle {
/// /* 4: */ b = 0b1001'1110'1101;
/// \endcode
int8_t Binary;
/// Format separators in binary literals with a minimum number of digits.
/// \code{.text}
/// // Binary: 3
/// // BinaryMinDigits: 7
/// b1 = 0b101101;
/// b2 = 0b1'101'101;
/// \endcode
int8_t BinaryMinDigits;
/// Format separators in decimal literals.
/// \code{.text}
/// /* -1: */ d = 18446744073709550592ull;
@ -2516,6 +2528,14 @@ struct FormatStyle {
/// /* 3: */ d = 18'446'744'073'709'550'592ull;
/// \endcode
int8_t Decimal;
/// Format separators in decimal literals with a minimum number of digits.
/// \code{.text}
/// // Decimal: 3
/// // DecimalMinDigits: 5
/// d1 = 2023;
/// d2 = 10'000;
/// \endcode
int8_t DecimalMinDigits;
/// Format separators in hexadecimal literals.
/// \code{.text}
/// /* -1: */ h = 0xDEADBEEFDEADBEEFuz;
@ -2523,6 +2543,20 @@ struct FormatStyle {
/// /* 2: */ h = 0xDE'AD'BE'EF'DE'AD'BE'EFuz;
/// \endcode
int8_t Hex;
/// Format separators in hexadecimal literals with a minimum number of
/// digits.
/// \code{.text}
/// // Hex: 2
/// // HexMinDigits: 6
/// h1 = 0xABCDE;
/// h2 = 0xAB'CD'EF;
/// \endcode
int8_t HexMinDigits;
bool operator==(const IntegerLiteralSeparatorStyle &R) const {
return Binary == R.Binary && BinaryMinDigits == R.BinaryMinDigits &&
Decimal == R.Decimal && DecimalMinDigits == R.DecimalMinDigits &&
Hex == R.Hex && HexMinDigits == R.HexMinDigits;
}
};
/// Format integer literal separators (``'`` for C++ and ``_`` for C#, Java,
@ -4212,10 +4246,7 @@ struct FormatStyle {
IndentWrappedFunctionNames == R.IndentWrappedFunctionNames &&
InsertBraces == R.InsertBraces &&
InsertNewlineAtEOF == R.InsertNewlineAtEOF &&
IntegerLiteralSeparator.Binary == R.IntegerLiteralSeparator.Binary &&
IntegerLiteralSeparator.Decimal ==
R.IntegerLiteralSeparator.Decimal &&
IntegerLiteralSeparator.Hex == R.IntegerLiteralSeparator.Hex &&
IntegerLiteralSeparator == R.IntegerLiteralSeparator &&
JavaImportGroups == R.JavaImportGroups &&
JavaScriptQuotes == R.JavaScriptQuotes &&
JavaScriptWrapImports == R.JavaScriptWrapImports &&

View File

@ -193,11 +193,6 @@ class Preprocessor {
LangOptions::FPEvalMethodKind CurrentFPEvalMethod =
LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine;
// Keeps the value of the last evaluation method before a
// `pragma float_control (precise,off) is applied.
LangOptions::FPEvalMethodKind LastFPEvalMethod =
LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine;
// The most recent pragma location where the floating point evaluation
// method was modified. This is used to determine whether the
// 'pragma clang fp eval_method' was used whithin the current scope.
@ -313,6 +308,9 @@ class Preprocessor {
/// The import path for named module that we're currently processing.
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> NamedModuleImportPath;
/// Whether the import is an `@import` or a standard c++ modules import.
bool IsAtImport = false;
/// Whether the last token we lexed was an '@'.
bool LastTokenWasAt = false;
@ -456,6 +454,144 @@ class Preprocessor {
TrackGMF TrackGMFState = TrackGMF::BeforeGMFIntroducer;
/// Track the status of the c++20 module decl.
///
/// module-declaration:
/// 'export'[opt] 'module' module-name module-partition[opt]
/// attribute-specifier-seq[opt] ';'
///
/// module-name:
/// module-name-qualifier[opt] identifier
///
/// module-partition:
/// ':' module-name-qualifier[opt] identifier
///
/// module-name-qualifier:
/// identifier '.'
/// module-name-qualifier identifier '.'
///
/// Transition state:
///
/// NotAModuleDecl --- export ---> FoundExport
/// NotAModuleDecl --- module ---> ImplementationCandidate
/// FoundExport --- module ---> InterfaceCandidate
/// ImplementationCandidate --- Identifier ---> ImplementationCandidate
/// ImplementationCandidate --- period ---> ImplementationCandidate
/// ImplementationCandidate --- colon ---> ImplementationCandidate
/// InterfaceCandidate --- Identifier ---> InterfaceCandidate
/// InterfaceCandidate --- period ---> InterfaceCandidate
/// InterfaceCandidate --- colon ---> InterfaceCandidate
/// ImplementationCandidate --- Semi ---> NamedModuleImplementation
/// NamedModuleInterface --- Semi ---> NamedModuleInterface
/// NamedModuleImplementation --- Anything ---> NamedModuleImplementation
/// NamedModuleInterface --- Anything ---> NamedModuleInterface
///
/// FIXME: We haven't handle attribute-specifier-seq here. It may not be bad
/// soon since we don't support any module attributes yet.
class ModuleDeclSeq {
enum ModuleDeclState : int {
NotAModuleDecl,
FoundExport,
InterfaceCandidate,
ImplementationCandidate,
NamedModuleInterface,
NamedModuleImplementation,
};
public:
ModuleDeclSeq() : State(NotAModuleDecl) {}
void handleExport() {
if (State == NotAModuleDecl)
State = FoundExport;
else if (!isNamedModule())
reset();
}
void handleModule() {
if (State == FoundExport)
State = InterfaceCandidate;
else if (State == NotAModuleDecl)
State = ImplementationCandidate;
else if (!isNamedModule())
reset();
}
void handleIdentifier(IdentifierInfo *Identifier) {
if (isModuleCandidate() && Identifier)
Name += Identifier->getName().str();
else if (!isNamedModule())
reset();
}
void handleColon() {
if (isModuleCandidate())
Name += ":";
else if (!isNamedModule())
reset();
}
void handlePeriod() {
if (isModuleCandidate())
Name += ".";
else if (!isNamedModule())
reset();
}
void handleSemi() {
if (!Name.empty() && isModuleCandidate()) {
if (State == InterfaceCandidate)
State = NamedModuleInterface;
else if (State == ImplementationCandidate)
State = NamedModuleImplementation;
else
llvm_unreachable("Unimaged ModuleDeclState.");
} else if (!isNamedModule())
reset();
}
void handleMisc() {
if (!isNamedModule())
reset();
}
bool isModuleCandidate() const {
return State == InterfaceCandidate || State == ImplementationCandidate;
}
bool isNamedModule() const {
return State == NamedModuleInterface ||
State == NamedModuleImplementation;
}
bool isNamedInterface() const { return State == NamedModuleInterface; }
bool isImplementationUnit() const {
return State == NamedModuleImplementation && !getName().contains(':');
}
StringRef getName() const {
assert(isNamedModule() && "Can't get name from a non named module");
return Name;
}
StringRef getPrimaryName() const {
assert(isNamedModule() && "Can't get name from a non named module");
return getName().split(':').first;
}
void reset() {
Name.clear();
State = NotAModuleDecl;
}
private:
ModuleDeclState State;
std::string Name;
};
ModuleDeclSeq ModuleDeclState;
/// Whether the module import expects an identifier next. Otherwise,
/// it expects a '.' or ';'.
bool ModuleImportExpectsIdentifier = false;
@ -2194,14 +2330,6 @@ class Preprocessor {
return LastFPEvalPragmaLocation;
}
LangOptions::FPEvalMethodKind getLastFPEvalMethod() const {
return LastFPEvalMethod;
}
void setLastFPEvalMethod(LangOptions::FPEvalMethodKind Val) {
LastFPEvalMethod = Val;
}
void setCurrentFPEvalMethod(SourceLocation PragmaLoc,
LangOptions::FPEvalMethodKind Val) {
assert(Val != LangOptions::FEM_UnsetOnCommandLine &&
@ -2225,6 +2353,36 @@ class Preprocessor {
/// Retrieves the module whose implementation we're current compiling, if any.
Module *getCurrentModuleImplementation();
/// If we are preprocessing a named module.
bool isInNamedModule() const { return ModuleDeclState.isNamedModule(); }
/// If we are proprocessing a named interface unit.
/// Note that a module implementation partition is not considered as an
/// named interface unit here although it is importable
/// to ease the parsing.
bool isInNamedInterfaceUnit() const {
return ModuleDeclState.isNamedInterface();
}
/// Get the named module name we're preprocessing.
/// Requires we're preprocessing a named module.
StringRef getNamedModuleName() const { return ModuleDeclState.getName(); }
/// If we are implementing an implementation module unit.
/// Note that the module implementation partition is not considered as an
/// implementation unit.
bool isInImplementationUnit() const {
return ModuleDeclState.isImplementationUnit();
}
/// If we're importing a standard C++20 Named Modules.
bool isInImportingCXXNamedModules() const {
// NamedModuleImportPath will be non-empty only if we're importing
// Standard C++ named modules.
return !NamedModuleImportPath.empty() && getLangOpts().CPlusPlusModules &&
!IsAtImport;
}
/// Allocate a new MacroInfo object with the provided SourceLocation.
MacroInfo *AllocateMacroInfo(SourceLocation L);

View File

@ -506,16 +506,8 @@ class DeclSpec {
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
return TypeRep;
}
// Returns the underlying decl, if any.
Decl *getRepAsDecl() const {
auto *D = getRepAsFoundDecl();
if (const auto *Using = dyn_cast_or_null<UsingShadowDecl>(D))
return Using->getTargetDecl();
return D;
}
// Returns the originally found decl, if any.
Decl *getRepAsFoundDecl() const {
assert(isDeclRep((TST)TypeSpecType) && "DeclSpec does not store a decl");
assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl");
return DeclRep;
}
Expr *getRepAsExpr() const {

View File

@ -238,11 +238,9 @@ namespace threadSafety {
// FIXME: No way to easily map from TemplateTypeParmTypes to
// TemplateTypeParmDecls, so we have this horrible PointerUnion.
using UnexpandedParameterPack = std::pair<
llvm::PointerUnion<
const TemplateTypeParmType *, const SubstTemplateTypeParmPackType *,
const SubstNonTypeTemplateParmPackExpr *, const NamedDecl *>,
SourceLocation>;
typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType *, NamedDecl *>,
SourceLocation>
UnexpandedParameterPack;
/// Describes whether we've seen any nullability information for the given
/// file.
@ -3330,9 +3328,7 @@ class Sema final {
SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
bool IsTypeSpecifier, bool IsTemplateParamOrArg,
OffsetOfKind OOK,
UsingShadowDecl*& FoundUsingShadow,
SkipBodyInfo *SkipBody = nullptr);
OffsetOfKind OOK, SkipBodyInfo *SkipBody = nullptr);
DeclResult ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
unsigned TagSpec, SourceLocation TagLoc,
@ -7284,24 +7280,34 @@ class Sema final {
private:
// The current stack of constraint satisfactions, so we can exit-early.
llvm::SmallVector<llvm::FoldingSetNodeID, 10> SatisfactionStack;
using SatisfactionStackEntryTy =
std::pair<const NamedDecl *, llvm::FoldingSetNodeID>;
llvm::SmallVector<SatisfactionStackEntryTy, 10>
SatisfactionStack;
public:
void PushSatisfactionStackEntry(const llvm::FoldingSetNodeID &ID) {
SatisfactionStack.push_back(ID);
void PushSatisfactionStackEntry(const NamedDecl *D,
const llvm::FoldingSetNodeID &ID) {
const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
SatisfactionStack.emplace_back(Can, ID);
}
void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); }
bool SatisfactionStackContains(const llvm::FoldingSetNodeID &ID) const {
return llvm::find(SatisfactionStack, ID) != SatisfactionStack.end();
bool SatisfactionStackContains(const NamedDecl *D,
const llvm::FoldingSetNodeID &ID) const {
const NamedDecl *Can = cast<NamedDecl>(D->getCanonicalDecl());
return llvm::find(SatisfactionStack,
SatisfactionStackEntryTy{Can, ID}) !=
SatisfactionStack.end();
}
// Resets the current SatisfactionStack for cases where we are instantiating
// constraints as a 'side effect' of normal instantiation in a way that is not
// indicative of recursive definition.
class SatisfactionStackResetRAII {
llvm::SmallVector<llvm::FoldingSetNodeID, 10> BackupSatisfactionStack;
llvm::SmallVector<SatisfactionStackEntryTy, 10>
BackupSatisfactionStack;
Sema &SemaRef;
public:
@ -7314,8 +7320,8 @@ class Sema final {
}
};
void
SwapSatisfactionStack(llvm::SmallVectorImpl<llvm::FoldingSetNodeID> &NewSS) {
void SwapSatisfactionStack(
llvm::SmallVectorImpl<SatisfactionStackEntryTy> &NewSS) {
SatisfactionStack.swap(NewSS);
}

View File

@ -62,7 +62,7 @@ inline InheritableAttr *getDLLAttr(Decl *D) {
}
/// Retrieve the depth and index of a template parameter.
inline std::pair<unsigned, unsigned> getDepthAndIndex(const NamedDecl *ND) {
inline std::pair<unsigned, unsigned> getDepthAndIndex(NamedDecl *ND) {
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
return std::make_pair(TTP->getDepth(), TTP->getIndex());
@ -79,7 +79,7 @@ getDepthAndIndex(UnexpandedParameterPack UPP) {
if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>())
return std::make_pair(TTP->getDepth(), TTP->getIndex());
return getDepthAndIndex(UPP.first.get<const NamedDecl *>());
return getDepthAndIndex(UPP.first.get<NamedDecl *>());
}
class TypoCorrectionConsumer : public VisibleDeclConsumer {

View File

@ -454,7 +454,9 @@ class SMTConv {
llvm::SMTExprRef OperandExp =
getSymExpr(Solver, Ctx, USE->getOperand(), &OperandTy, hasComparison);
llvm::SMTExprRef UnaryExp =
fromUnOp(Solver, USE->getOpcode(), OperandExp);
OperandTy->isRealFloatingType()
? fromFloatUnOp(Solver, USE->getOpcode(), OperandExp)
: fromUnOp(Solver, USE->getOpcode(), OperandExp);
// Currently, without the `support-symbolic-integer-casts=true` option,
// we do not emit `SymbolCast`s for implicit casts.

View File

@ -92,25 +92,24 @@ enum class TypeModifier : uint8_t {
LLVM_MARK_AS_BITMASK_ENUM(LMUL1),
};
struct Policy {
bool IsUnspecified = false;
class Policy {
public:
enum PolicyType {
Undisturbed,
Agnostic,
};
PolicyType TailPolicy = Agnostic;
PolicyType MaskPolicy = Agnostic;
bool HasTailPolicy, HasMaskPolicy;
Policy(bool HasTailPolicy, bool HasMaskPolicy)
: IsUnspecified(true), HasTailPolicy(HasTailPolicy),
HasMaskPolicy(HasMaskPolicy) {}
Policy(PolicyType TailPolicy, bool HasTailPolicy, bool HasMaskPolicy)
: TailPolicy(TailPolicy), HasTailPolicy(HasTailPolicy),
HasMaskPolicy(HasMaskPolicy) {}
Policy(PolicyType TailPolicy, PolicyType MaskPolicy, bool HasTailPolicy,
bool HasMaskPolicy)
: TailPolicy(TailPolicy), MaskPolicy(MaskPolicy),
HasTailPolicy(HasTailPolicy), HasMaskPolicy(HasMaskPolicy) {}
private:
// The default assumption for an RVV instruction is TAMA, as an undisturbed
// policy generally will affect the performance of an out-of-order core.
const PolicyType TailPolicy = Agnostic;
const PolicyType MaskPolicy = Agnostic;
public:
Policy() = default;
Policy(PolicyType TailPolicy) : TailPolicy(TailPolicy) {}
Policy(PolicyType TailPolicy, PolicyType MaskPolicy)
: TailPolicy(TailPolicy), MaskPolicy(MaskPolicy) {}
bool isTAMAPolicy() const {
return TailPolicy == Agnostic && MaskPolicy == Agnostic;
@ -136,17 +135,8 @@ struct Policy {
bool isMUPolicy() const { return MaskPolicy == Undisturbed; }
bool hasTailPolicy() const { return HasTailPolicy; }
bool hasMaskPolicy() const { return HasMaskPolicy; }
bool isUnspecified() const { return IsUnspecified; }
bool operator==(const Policy &Other) const {
return IsUnspecified == Other.IsUnspecified &&
TailPolicy == Other.TailPolicy && MaskPolicy == Other.MaskPolicy &&
HasTailPolicy == Other.HasTailPolicy &&
HasMaskPolicy == Other.HasMaskPolicy;
return TailPolicy == Other.TailPolicy && MaskPolicy == Other.MaskPolicy;
}
bool operator!=(const Policy &Other) const { return !(*this == Other); }
@ -422,7 +412,6 @@ class RVVIntrinsic {
return IntrinsicTypes;
}
Policy getPolicyAttrs() const {
assert(PolicyAttrs.IsUnspecified == false);
return PolicyAttrs;
}
unsigned getPolicyAttrsBits() const {
@ -431,8 +420,6 @@ class RVVIntrinsic {
// The 1st bit simulates the `vma` of RVV
// int PolicyAttrs = 0;
assert(PolicyAttrs.IsUnspecified == false);
if (PolicyAttrs.isTUMAPolicy())
return 2;
if (PolicyAttrs.isTAMAPolicy())
@ -459,8 +446,7 @@ class RVVIntrinsic {
unsigned NF, PolicyScheme DefaultScheme,
Policy PolicyAttrs);
static llvm::SmallVector<Policy>
getSupportedUnMaskedPolicies(bool HasTailPolicy, bool HasMaskPolicy);
static llvm::SmallVector<Policy> getSupportedUnMaskedPolicies();
static llvm::SmallVector<Policy>
getSupportedMaskedPolicies(bool HasTailPolicy, bool HasMaskPolicy);

View File

@ -35,9 +35,13 @@ enum class ScanningOutputFormat {
/// intermodule dependency information.
Make,
/// This outputs the full module dependency graph suitable for use for
/// This outputs the full clang module dependency graph suitable for use for
/// explicitly building modules.
Full,
/// This outputs the dependency graph for standard c++ modules in P1689R5
/// format.
P1689,
};
/// The dependency scanning service contains shared configuration and state that

View File

@ -67,6 +67,12 @@ struct FullDependenciesResult {
std::vector<ModuleDeps> DiscoveredModules;
};
struct P1689Rule {
std::string PrimaryOutput;
std::optional<P1689ModuleInfo> Provides;
std::vector<P1689ModuleInfo> Requires;
};
/// The high-level implementation of the dependency discovery tool that runs on
/// an individual worker thread.
class DependencyScanningTool {
@ -87,9 +93,24 @@ class DependencyScanningTool {
getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD,
std::optional<StringRef> ModuleName = std::nullopt);
/// Collect the full module dependency graph for the input, ignoring any
/// modules which have already been seen. If \p ModuleName isn't empty, this
/// function returns the full dependency information of module \p ModuleName.
/// Collect the module dependency in P1689 format for C++20 named modules.
///
/// \param MakeformatOutput The output parameter for dependency information
/// in make format if the command line requires to generate make-format
/// dependency information by `-MD -MF <dep_file>`.
///
/// \param MakeformatOutputPath The output parameter for the path to
/// \param MakeformatOutput.
///
/// \returns A \c StringError with the diagnostic output if clang errors
/// occurred, P1689 dependency format rules otherwise.
llvm::Expected<P1689Rule>
getP1689ModuleDependencyFile(
const clang::tooling::CompileCommand &Command, StringRef CWD,
std::string &MakeformatOutput, std::string &MakeformatOutputPath);
/// Given a Clang driver command-line for a translation unit, gather the
/// modular dependencies and return the information needed for explicit build.
///
/// \param AlreadySeen This stores modules which have previously been
/// reported. Use the same instance for all calls to this

View File

@ -41,7 +41,11 @@ class DependencyConsumer {
public:
virtual ~DependencyConsumer() {}
virtual void handleBuildCommand(Command Cmd) = 0;
virtual void handleProvidedAndRequiredStdCXXModules(
std::optional<P1689ModuleInfo> Provided,
std::vector<P1689ModuleInfo> Requires) {}
virtual void handleBuildCommand(Command Cmd) {}
virtual void
handleDependencyOutputOpts(const DependencyOutputOptions &Opts) = 0;

View File

@ -62,6 +62,27 @@ struct ModuleID {
}
};
/// P1689ModuleInfo - Represents the needed information of standard C++20
/// modules for P1689 format.
struct P1689ModuleInfo {
/// The name of the module. This may include `:` for partitions.
std::string ModuleName;
/// Optional. The source path to the module.
std::string SourcePath;
/// If this module is a standard c++ interface unit.
bool IsStdCXXModuleInterface = true;
enum class ModuleType {
NamedCXXModule
// To be supported
// AngleHeaderUnit,
// QuoteHeaderUnit
};
ModuleType Type = ModuleType::NamedCXXModule;
};
/// An output from a module compilation, such as the path of the module file.
enum class ModuleOutputKind {
/// The module file (.pcm). Required.
@ -181,7 +202,7 @@ class ModuleDepCollector final : public DependencyCollector {
ModuleDepCollector(std::unique_ptr<DependencyOutputOptions> Opts,
CompilerInstance &ScanInstance, DependencyConsumer &C,
CompilerInvocation OriginalCI, bool OptimizeArgs,
bool EagerLoadModules);
bool EagerLoadModules, bool IsStdModuleP1689Format);
void attachToPreprocessor(Preprocessor &PP) override;
void attachToASTReader(ASTReader &R) override;
@ -219,6 +240,12 @@ class ModuleDepCollector final : public DependencyCollector {
bool OptimizeArgs;
/// Whether to set up command-lines to load PCM files eagerly.
bool EagerLoadModules;
/// If we're generating dependency output in P1689 format
/// for standard C++ modules.
bool IsStdModuleP1689Format;
std::optional<P1689ModuleInfo> ProvidedStdCXXModule;
std::vector<P1689ModuleInfo> RequiredStdCXXModules;
/// Checks whether the module is known as being prebuilt.
bool isPrebuiltModule(const Module *M);

View File

@ -10916,7 +10916,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
for (unsigned I = OldElts; I < N; ++I)
Value->getArrayInitializedElt(I) = Filler;
if (HasTrivialConstructor && N == FinalSize) {
if (HasTrivialConstructor && N == FinalSize && FinalSize != 1) {
// If we have a trivial constructor, only evaluate it once and copy
// the result into all the array elements.
APValue &FirstResult = Value->getArrayInitializedElt(0);

View File

@ -2487,11 +2487,13 @@ bool QualType::isTrivialType(const ASTContext &Context) const {
return true;
if (const auto *RT = CanonicalType->getAs<RecordType>()) {
if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
// C++11 [class]p6:
// A trivial class is a class that has a default constructor,
// has no non-trivial default constructors, and is trivially
// copyable.
return ClassDecl->hasDefaultConstructor() &&
// C++20 [class]p6:
// A trivial class is a class that is trivially copyable, and
// has one or more eligible default constructors such that each is
// trivial.
// FIXME: We should merge this definition of triviality into
// CXXRecordDecl::isTrivial. Currently it computes the wrong thing.
return ClassDecl->hasTrivialDefaultConstructor() &&
!ClassDecl->hasNonTrivialDefaultConstructor() &&
ClassDecl->isTriviallyCopyable();
}

View File

@ -687,9 +687,13 @@ void AArch64TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
if (ArchInfo == llvm::AArch64::INVALID)
return; // Not an architecure, nothing more to do.
// Disabling an architecture feature does not affect dependent features
if (!Enabled)
return;
for (const auto *OtherArch : llvm::AArch64::ArchInfos)
if (ArchInfo.implies(*OtherArch))
Features[OtherArch->getSubArch()] = Enabled;
Features[OtherArch->getSubArch()] = true;
// Set any features implied by the architecture
uint64_t Extensions =

View File

@ -254,6 +254,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
HW_FP(0) {
bool IsFreeBSD = Triple.isOSFreeBSD();
bool IsOpenBSD = Triple.isOSOpenBSD();
bool IsNetBSD = Triple.isOSNetBSD();
@ -321,7 +322,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
default:
if (IsNetBSD)
setABI("apcs-gnu");
else if (IsOpenBSD)
else if (IsFreeBSD || IsOpenBSD)
setABI("aapcs-linux");
else
setABI("aapcs");

View File

@ -426,12 +426,12 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo {
} else if ((Triple.getArch() == llvm::Triple::ppc64le)) {
DataLayout = "e-m:e-i64:64-n32:64";
ABI = "elfv2";
} else if (Triple.isOSFreeBSD() && (Triple.getOSMajorVersion() == 0 || Triple.getOSMajorVersion() >= 13)) {
DataLayout = "E-m:e-i64:64-n32:64";
ABI = "elfv2";
} else {
DataLayout = "E-m:e-i64:64-n32:64";
ABI = "elfv1";
if (Triple.isPPC64ELFv2ABI())
ABI = "elfv2";
else
ABI = "elfv1";
}
if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) {

View File

@ -197,8 +197,8 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts,
if (ISAInfo->hasExtension("zve32x")) {
Builder.defineMacro("__riscv_vector");
// Currently we support the v0.10 RISC-V V intrinsics.
Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(0, 10)));
// Currently we support the v0.11 RISC-V V intrinsics.
Builder.defineMacro("__riscv_v_intrinsic", Twine(getVersionValue(0, 11)));
}
}

View File

@ -795,13 +795,13 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasHRESET)
Builder.defineMacro("__HRESET__");
if (HasAMXTILE)
Builder.defineMacro("__AMXTILE__");
Builder.defineMacro("__AMX_TILE__");
if (HasAMXINT8)
Builder.defineMacro("__AMXINT8__");
Builder.defineMacro("__AMX_INT8__");
if (HasAMXBF16)
Builder.defineMacro("__AMXBF16__");
Builder.defineMacro("__AMX_BF16__");
if (HasAMXFP16)
Builder.defineMacro("__AMXFP16__");
Builder.defineMacro("__AMX_FP16__");
if (HasCMPCCXADD)
Builder.defineMacro("__CMPCCXADD__");
if (HasRAOINT)

View File

@ -379,9 +379,8 @@ class CGCXXABI {
/// zero if no specific type is applicable, e.g. if the ABI expects the "this"
/// parameter to point to some artificial offset in a complete object due to
/// vbases being reordered.
virtual const CXXRecordDecl *
getThisArgumentTypeForMethod(const CXXMethodDecl *MD) {
return MD->getParent();
virtual const CXXRecordDecl *getThisArgumentTypeForMethod(GlobalDecl GD) {
return cast<CXXMethodDecl>(GD.getDecl())->getParent();
}
/// Perform ABI-specific "this" argument adjustment required prior to

View File

@ -322,7 +322,9 @@ CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) {
SmallVector<CanQualType, 16> argTypes;
SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos;
argTypes.push_back(DeriveThisType(MD->getParent(), MD));
const CXXRecordDecl *ThisType = TheCXXABI.getThisArgumentTypeForMethod(GD);
argTypes.push_back(DeriveThisType(ThisType, MD));
bool PassParams = true;

View File

@ -33,10 +33,12 @@ struct MemberCallInfo {
}
static MemberCallInfo
commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, GlobalDecl GD,
llvm::Value *This, llvm::Value *ImplicitParam,
QualType ImplicitParamTy, const CallExpr *CE,
CallArgList &Args, CallArgList *RtlArgs) {
auto *MD = cast<CXXMethodDecl>(GD.getDecl());
assert(CE == nullptr || isa<CXXMemberCallExpr>(CE) ||
isa<CXXOperatorCallExpr>(CE));
assert(MD->isInstance() &&
@ -44,7 +46,7 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD,
// Push the this ptr.
const CXXRecordDecl *RD =
CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD);
CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(GD);
Args.add(RValue::get(This), CGF.getTypes().DeriveThisType(RD, MD));
// If there is an implicit parameter (e.g. VTT), emit it.
@ -110,7 +112,7 @@ RValue CodeGenFunction::EmitCXXDestructorCall(
}
CallArgList Args;
commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam,
commonEmitCXXMemberOrOperatorCall(*this, Dtor, This, ImplicitParam,
ImplicitParamTy, CE, Args, nullptr);
return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee,
ReturnValueSlot(), Args, nullptr, CE && CE == MustTailCall,
@ -285,7 +287,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
assert(ReturnValue.isNull() && "Constructor shouldn't have return value");
CallArgList Args;
commonEmitCXXMemberOrOperatorCall(
*this, Ctor, This.getPointer(*this), /*ImplicitParam=*/nullptr,
*this, {Ctor, Ctor_Complete}, This.getPointer(*this),
/*ImplicitParam=*/nullptr,
/*ImplicitParamTy=*/QualType(), CE, Args, nullptr);
EmitCXXConstructorCall(Ctor, Ctor_Complete, /*ForVirtualBase=*/false,

View File

@ -235,11 +235,24 @@ class MicrosoftCXXABI : public CGCXXABI {
void EmitCXXDestructors(const CXXDestructorDecl *D) override;
const CXXRecordDecl *
getThisArgumentTypeForMethod(const CXXMethodDecl *MD) override {
if (MD->isVirtual() && !isa<CXXDestructorDecl>(MD)) {
const CXXRecordDecl *getThisArgumentTypeForMethod(GlobalDecl GD) override {
auto *MD = cast<CXXMethodDecl>(GD.getDecl());
if (MD->isVirtual()) {
GlobalDecl LookupGD = GD;
if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
// Complete dtors take a pointer to the complete object,
// thus don't need adjustment.
if (GD.getDtorType() == Dtor_Complete)
return MD->getParent();
// There's only Dtor_Deleting in vftable but it shares the this
// adjustment with the base one, so look up the deleting one instead.
LookupGD = GlobalDecl(DD, Dtor_Deleting);
}
MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
// The vbases might be ordered differently in the final overrider object
// and the complete object, so the "this" argument may sometimes point to
// memory that has no particular type (e.g. past the complete object).

View File

@ -2381,9 +2381,7 @@ class X86_64ABIInfo : public ABIInfo {
return false;
const llvm::Triple &Triple = getTarget().getTriple();
if (Triple.isOSDarwin() || Triple.isPS())
return false;
if (Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 10)
if (Triple.isOSDarwin() || Triple.isPS() || Triple.isOSFreeBSD())
return false;
return true;
}
@ -7418,18 +7416,28 @@ class SystemZABIInfo : public ABIInfo {
};
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
ASTContext &Ctx;
const SystemZABIInfo &getABIInfo() const {
return static_cast<const SystemZABIInfo&>(TargetCodeGenInfo::getABIInfo());
}
// These are used for speeding up the search for a visible vector ABI.
mutable bool HasVisibleVecABIFlag = false;
mutable std::set<const Type *> SeenTypes;
// Returns true (the first time) if Ty is or found to make use of a vector
// type (e.g. as a function argument).
bool isVectorTypeBased(const Type *Ty) const;
// Returns true (the first time) if Ty is, or is found to include, a vector
// type that exposes the vector ABI. This is any vector >=16 bytes which
// with vector support are aligned to only 8 bytes. When IsParam is true,
// the type belongs to a value as passed between functions. If it is a
// vector <=16 bytes it will be passed in a vector register (if supported).
bool isVectorTypeBased(const Type *Ty, bool IsParam) const;
public:
SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
: TargetCodeGenInfo(
std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)) {
std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)),
Ctx(CGT.getContext()) {
SwiftInfo =
std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
}
@ -7439,9 +7447,9 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
// indicating a visible vector ABI is added. Eventually this will result in
// a GNU attribute indicating the vector ABI of the module. Ty is the type
// of a variable or function parameter that is globally visible.
void handleExternallyVisibleObjABI(const Type *Ty,
CodeGen::CodeGenModule &M) const {
if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty)) {
void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M,
bool IsParam) const {
if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) {
M.getModule().addModuleFlag(llvm::Module::Warning,
"s390x-visible-vector-ABI", 1);
HasVisibleVecABIFlag = true;
@ -7457,11 +7465,13 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
// variable or function.
if (const auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->isExternallyVisible())
handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M);
handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M,
/*IsParam*/false);
}
else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isExternallyVisible())
handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M);
handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M,
/*IsParam*/false);
}
}
@ -7571,17 +7581,18 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {
// If this is a C++ record, check the bases first.
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
for (const auto &I : CXXRD->bases()) {
QualType Base = I.getType();
if (CXXRD->hasDefinition())
for (const auto &I : CXXRD->bases()) {
QualType Base = I.getType();
// Empty bases don't affect things either way.
if (isEmptyRecord(getContext(), Base, true))
continue;
// Empty bases don't affect things either way.
if (isEmptyRecord(getContext(), Base, true))
continue;
if (!Found.isNull())
return Ty;
Found = GetSingleElementType(Base);
}
if (!Found.isNull())
return Ty;
Found = GetSingleElementType(Base);
}
// Check the fields.
for (const auto *FD : RD->fields()) {
@ -7635,7 +7646,8 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
bool IsVector = false;
CharUnits UnpaddedSize;
CharUnits DirectAlign;
SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM());
SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(),
/*IsParam*/true);
if (IsIndirect) {
DirectTy = llvm::PointerType::getUnqual(DirectTy);
UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8);
@ -7843,35 +7855,57 @@ void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const {
// Check if a vararg vector argument is passed, in which case the
// vector ABI becomes visible as the va_list could be passed on to
// other functions.
SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM());
SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(),
/*IsParam*/true);
}
}
bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty) const {
while (Ty->isPointerType() || Ty->isArrayType())
Ty = Ty->getPointeeOrArrayElementType();
bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty,
bool IsParam) const {
if (!SeenTypes.insert(Ty).second)
return false;
if (Ty->isVectorType())
return true;
if (IsParam) {
// A narrow (<16 bytes) vector will as a parameter also expose the ABI as
// it will be passed in a vector register. A wide (>16 bytes) vector will
// be passed via "hidden" pointer where any extra alignment is not
// required (per GCC).
const Type *SingleEltTy =
getABIInfo().GetSingleElementType(QualType(Ty, 0)).getTypePtr();
bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() &&
Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty);
if (Ty->isVectorType() || SingleVecEltStruct)
return Ctx.getTypeSize(Ty) / 8 <= 16;
}
// Assume pointers are dereferenced.
while (Ty->isPointerType() || Ty->isArrayType())
Ty = Ty->getPointeeOrArrayElementType();
// Vectors >= 16 bytes expose the ABI through alignment requirements.
if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16)
return true;
if (const auto *RecordTy = Ty->getAs<RecordType>()) {
const RecordDecl *RD = RecordTy->getDecl();
if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
if (CXXRD->hasDefinition())
for (const auto &I : CXXRD->bases())
if (isVectorTypeBased(I.getType().getTypePtr()))
if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false))
return true;
for (const auto *FD : RD->fields())
if (isVectorTypeBased(FD->getType().getTypePtr()))
if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false))
return true;
}
if (const auto *FT = Ty->getAs<FunctionType>())
if (isVectorTypeBased(FT->getReturnType().getTypePtr()))
if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true))
return true;
if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>())
for (auto ParamType : Proto->getParamTypes())
if (isVectorTypeBased(ParamType.getTypePtr()))
if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true))
return true;
return false;
}

View File

@ -1873,14 +1873,12 @@ int Driver::ExecuteCompilation(
C.CleanupFileMap(C.getFailureResultFiles(), JA, true);
}
#if LLVM_ON_UNIX
// llvm/lib/Support/Unix/Signals.inc will exit with a special return code
// llvm/lib/Support/*/Signals.inc will exit with a special return code
// for SIGPIPE. Do not print diagnostics for this case.
if (CommandRes == EX_IOERR) {
Res = CommandRes;
continue;
}
#endif
// Print extra information about abnormal failures, if possible.
//

View File

@ -19,6 +19,7 @@
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/TargetParser.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
#include <memory>
@ -545,7 +546,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
if ((Kinds & SanitizerKind::ShadowCallStack) &&
((TC.getTriple().isAArch64() &&
!llvm::AArch64::isX18ReservedByDefault(TC.getTriple())) ||
TC.getTriple().isRISCV()) &&
(TC.getTriple().isRISCV() &&
!llvm::RISCV::isX18ReservedByDefault(TC.getTriple()))) &&
!Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {
D.Diag(diag::err_drv_argument_only_allowed_with)
<< lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)

View File

@ -34,53 +34,60 @@ static std::string getPPCGenericTargetCPU(const llvm::Triple &T) {
return "ppc";
}
/// getPPCTargetCPU - Get the (LLVM) name of the PowerPC cpu we are targeting.
std::string ppc::getPPCTargetCPU(const ArgList &Args, const llvm::Triple &T) {
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
StringRef CPUName = A->getValue();
static std::string normalizeCPUName(StringRef CPUName, const llvm::Triple &T) {
// Clang/LLVM does not actually support code generation
// for the 405 CPU. However, there are uses of this CPU ID
// in projects that previously used GCC and rely on Clang
// accepting it. Clang has always ignored it and passed the
// generic CPU ID to the back end.
if (CPUName == "generic" || CPUName == "405")
return getPPCGenericTargetCPU(T);
// Clang/LLVM does not actually support code generation
// for the 405 CPU. However, there are uses of this CPU ID
// in projects that previously used GCC and rely on Clang
// accepting it. Clang has always ignored it and passed the
// generic CPU ID to the back end.
if (CPUName == "generic" || CPUName == "405")
if (CPUName == "native") {
std::string CPU = std::string(llvm::sys::getHostCPUName());
if (!CPU.empty() && CPU != "generic")
return CPU;
else
return getPPCGenericTargetCPU(T);
if (CPUName == "native") {
std::string CPU = std::string(llvm::sys::getHostCPUName());
if (!CPU.empty() && CPU != "generic")
return CPU;
else
return getPPCGenericTargetCPU(T);
}
return llvm::StringSwitch<const char *>(CPUName)
.Case("common", "generic")
.Case("440fp", "440")
.Case("630", "pwr3")
.Case("G3", "g3")
.Case("G4", "g4")
.Case("G4+", "g4+")
.Case("8548", "e500")
.Case("G5", "g5")
.Case("power3", "pwr3")
.Case("power4", "pwr4")
.Case("power5", "pwr5")
.Case("power5x", "pwr5x")
.Case("power6", "pwr6")
.Case("power6x", "pwr6x")
.Case("power7", "pwr7")
.Case("power8", "pwr8")
.Case("power9", "pwr9")
.Case("power10", "pwr10")
.Case("future", "future")
.Case("powerpc", "ppc")
.Case("powerpc64", "ppc64")
.Case("powerpc64le", "ppc64le")
.Default(CPUName.data());
}
return llvm::StringSwitch<const char *>(CPUName)
.Case("common", "generic")
.Case("440fp", "440")
.Case("630", "pwr3")
.Case("G3", "g3")
.Case("G4", "g4")
.Case("G4+", "g4+")
.Case("8548", "e500")
.Case("G5", "g5")
.Case("power3", "pwr3")
.Case("power4", "pwr4")
.Case("power5", "pwr5")
.Case("power5x", "pwr5x")
.Case("power6", "pwr6")
.Case("power6x", "pwr6x")
.Case("power7", "pwr7")
.Case("power8", "pwr8")
.Case("power9", "pwr9")
.Case("power10", "pwr10")
.Case("future", "future")
.Case("powerpc", "ppc")
.Case("powerpc64", "ppc64")
.Case("powerpc64le", "ppc64le")
.Default(CPUName.data());
}
/// Get the (LLVM) name of the PowerPC cpu we are tuning for.
std::string ppc::getPPCTuneCPU(const ArgList &Args, const llvm::Triple &T) {
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ))
return normalizeCPUName(A->getValue(), T);
return getPPCGenericTargetCPU(T);
}
/// Get the (LLVM) name of the PowerPC cpu we are targeting.
std::string ppc::getPPCTargetCPU(const ArgList &Args, const llvm::Triple &T) {
if (Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ))
return normalizeCPUName(A->getValue(), T);
return getPPCGenericTargetCPU(T);
}

View File

@ -37,6 +37,8 @@ FloatABI getPPCFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
std::string getPPCTargetCPU(const llvm::opt::ArgList &Args,
const llvm::Triple &T);
std::string getPPCTuneCPU(const llvm::opt::ArgList &Args,
const llvm::Triple &T);
const char *getPPCAsmModeForCPU(StringRef Name);
ReadGOTPtrMode getPPCReadGOTPtrMode(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

View File

@ -1989,22 +1989,19 @@ void Clang::AddMIPSTargetArgs(const ArgList &Args,
void Clang::AddPPCTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
const llvm::Triple &T = getToolChain().getTriple();
if (const Arg *A = Args.getLastArg(options::OPT_mtune_EQ)) {
CmdArgs.push_back("-tune-cpu");
if (strcmp(A->getValue(), "native") == 0)
CmdArgs.push_back(Args.MakeArgString(llvm::sys::getHostCPUName()));
else
CmdArgs.push_back(A->getValue());
std::string CPU = ppc::getPPCTuneCPU(Args, T);
CmdArgs.push_back(Args.MakeArgString(CPU));
}
// Select the ABI to use.
const char *ABIName = nullptr;
const llvm::Triple &T = getToolChain().getTriple();
if (T.isOSBinFormatELF()) {
switch (getToolChain().getArch()) {
case llvm::Triple::ppc64: {
if ((T.isOSFreeBSD() && T.getOSMajorVersion() >= 13) ||
T.isOSOpenBSD() || T.isMusl())
if (T.isPPC64ELFv2ABI())
ABIName = "elfv2";
else
ABIName = "elfv1";

View File

@ -443,24 +443,19 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("--gpu-name");
CmdArgs.push_back(Args.MakeArgString(CudaArchToString(gpu_arch)));
CmdArgs.push_back("--output-file");
const char *OutputFileName = Args.MakeArgString(TC.getInputFilename(Output));
std::string OutputFileName = TC.getInputFilename(Output);
// If we are invoking `nvlink` internally we need to output a `.cubin` file.
// Checking if the output is a temporary is the cleanest way to determine
// this. Putting this logic in `getInputFilename` isn't an option because it
// relies on the compilation.
// FIXME: This should hopefully be removed if NVIDIA updates their tooling.
if (Output.isFilename() &&
llvm::find(C.getTempFiles(), Output.getFilename()) !=
C.getTempFiles().end()) {
if (!C.getInputArgs().getLastArg(options::OPT_c)) {
SmallString<256> Filename(Output.getFilename());
llvm::sys::path::replace_extension(Filename, "cubin");
OutputFileName = Args.MakeArgString(Filename);
OutputFileName = Filename.str();
}
if (Output.isFilename() && OutputFileName != Output.getFilename())
C.addTempFile(OutputFileName);
C.addTempFile(Args.MakeArgString(OutputFileName));
CmdArgs.push_back(OutputFileName);
CmdArgs.push_back(Args.MakeArgString(OutputFileName));
for (const auto &II : Inputs)
CmdArgs.push_back(Args.MakeArgString(II.getFilename()));

View File

@ -85,16 +85,7 @@ void freebsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back("-mfpu=softvfp");
switch (getToolChain().getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
CmdArgs.push_back("-meabi=5");
break;
default:
CmdArgs.push_back("-matpcs");
}
CmdArgs.push_back("-meabi=5");
break;
}
case llvm::Triple::sparc:
@ -176,10 +167,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("/libexec/ld-elf.so.1");
}
const llvm::Triple &T = ToolChain.getTriple();
if (T.getOSMajorVersion() >= 9) {
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || T.isX86())
CmdArgs.push_back("--hash-style=both");
}
if (Arch == llvm::Triple::arm || Arch == llvm::Triple::sparc || T.isX86())
CmdArgs.push_back("--hash-style=both");
CmdArgs.push_back("--enable-new-dtags");
}
@ -396,17 +385,11 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple &Triple,
getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
ToolChain::CXXStdlibType FreeBSD::GetDefaultCXXStdlibType() const {
unsigned Major = getTriple().getOSMajorVersion();
if (Major >= 10 || Major == 0)
return ToolChain::CST_Libcxx;
return ToolChain::CST_Libstdcxx;
}
unsigned FreeBSD::GetDefaultDwarfVersion() const {
if (getTriple().getOSMajorVersion() < 12)
return 2;
return 4;
unsigned Major = getTriple().getOSMajorVersion();
if (Major >= 12 || Major == 0)
return 4;
return 2;
}
void FreeBSD::AddClangSystemIncludeArgs(
@ -449,30 +432,14 @@ void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
concat(getDriver().SysRoot, "/usr/include/c++/v1"));
}
void FreeBSD::addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/c++/4.2"),
"", "", DriverArgs, CC1Args);
}
void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
CXXStdlibType Type = GetCXXStdlibType(Args);
unsigned Major = getTriple().getOSMajorVersion();
bool Profiling = Args.hasArg(options::OPT_pg) && Major != 0 && Major < 14;
switch (Type) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
break;
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back(Profiling ? "-lstdc++_p" : "-lstdc++");
break;
}
CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
}
void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs,
@ -491,21 +458,6 @@ Tool *FreeBSD::buildAssembler() const {
Tool *FreeBSD::buildLinker() const { return new tools::freebsd::Linker(*this); }
llvm::ExceptionHandling FreeBSD::GetExceptionModel(const ArgList &Args) const {
// FreeBSD uses SjLj exceptions on ARM oabi.
switch (getTriple().getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::EABI:
return llvm::ExceptionHandling::None;
default:
if (getTriple().getArch() == llvm::Triple::arm ||
getTriple().getArch() == llvm::Triple::thumb)
return llvm::ExceptionHandling::SjLj;
return llvm::ExceptionHandling::None;
}
}
bool FreeBSD::HasNativeLLVMSupport() const { return true; }
ToolChain::UnwindTableLevel
@ -550,8 +502,9 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const {
void FreeBSD::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
unsigned Major = getTriple().getOSMajorVersion();
if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
options::OPT_fno_use_init_array,
getTriple().getOSMajorVersion() >= 12))
(Major >= 12 || Major == 0)))
CC1Args.push_back("-fno-use-init-array");
}

View File

@ -61,12 +61,16 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
CXXStdlibType GetDefaultCXXStdlibType() const override;
RuntimeLibType GetDefaultRuntimeLibType() const override {
return ToolChain::RLT_CompilerRT;
}
CXXStdlibType GetDefaultCXXStdlibType() const override {
return ToolChain::CST_Libcxx;
}
void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
@ -74,8 +78,6 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
llvm::ExceptionHandling
GetExceptionModel(const llvm::opt::ArgList &Args) const override;
UnwindTableLevel
getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
bool isPIEDefault(const llvm::opt::ArgList &Args) const override;

View File

@ -447,13 +447,13 @@ SanitizerMask Fuchsia::getDefaultSanitizers() const {
SanitizerMask Res;
switch (getTriple().getArch()) {
case llvm::Triple::aarch64:
case llvm::Triple::riscv64:
Res |= SanitizerKind::ShadowCallStack;
break;
case llvm::Triple::x86_64:
Res |= SanitizerKind::SafeStack;
break;
default:
// TODO: Enable SafeStack on RISC-V once tested.
break;
}
return Res;

View File

@ -200,6 +200,16 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
// Add asan_dynamic as the first import lib before other libs. This allows
// asan to be initialized as early as possible to increase its instrumentation
// coverage to include other user DLLs which has not been built with asan.
if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
// MinGW always links against a shared MSVCRT.
CmdArgs.push_back(
TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared));
}
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));

View File

@ -348,8 +348,11 @@ struct ScalarEnumerationTraits<FormatStyle::IndentExternBlockStyle> {
template <> struct MappingTraits<FormatStyle::IntegerLiteralSeparatorStyle> {
static void mapping(IO &IO, FormatStyle::IntegerLiteralSeparatorStyle &Base) {
IO.mapOptional("Binary", Base.Binary);
IO.mapOptional("BinaryMinDigits", Base.BinaryMinDigits);
IO.mapOptional("Decimal", Base.Decimal);
IO.mapOptional("DecimalMinDigits", Base.DecimalMinDigits);
IO.mapOptional("Hex", Base.Hex);
IO.mapOptional("HexMinDigits", Base.HexMinDigits);
}
};
@ -1392,7 +1395,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.InsertBraces = false;
LLVMStyle.InsertNewlineAtEOF = false;
LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None;
LLVMStyle.IntegerLiteralSeparator = {/*Binary=*/0, /*Decimal=*/0, /*Hex=*/0};
LLVMStyle.IntegerLiteralSeparator = {
/*Binary=*/0, /*BinaryMinDigits=*/0,
/*Decimal=*/0, /*DecimalMinDigits=*/0,
/*Hex=*/0, /*HexMinDigits=*/0};
LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
LLVMStyle.JavaScriptWrapImports = true;
LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;

View File

@ -69,6 +69,12 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
if (SkipBinary && SkipDecimal && SkipHex)
return {};
const auto BinaryMinDigits =
std::max((int)Option.BinaryMinDigits, Binary + 1);
const auto DecimalMinDigits =
std::max((int)Option.DecimalMinDigits, Decimal + 1);
const auto HexMinDigits = std::max((int)Option.HexMinDigits, Hex + 1);
const auto &SourceMgr = Env.getSourceManager();
AffectedRangeManager AffectedRangeMgr(SourceMgr, Env.getCharRanges());
@ -106,17 +112,18 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
(IsBase16 && SkipHex) || B == Base::Other) {
continue;
}
if (Style.isCpp()) {
if (const auto Pos = Text.find_first_of("_i"); Pos != StringRef::npos) {
Text = Text.substr(0, Pos);
Length = Pos;
}
}
if ((IsBase10 && Text.find_last_of(".eEfFdDmM") != StringRef::npos) ||
(IsBase16 && Text.find_last_of(".pP") != StringRef::npos)) {
continue;
}
if (((IsBase2 && Binary < 0) || (IsBase10 && Decimal < 0) ||
(IsBase16 && Hex < 0)) &&
Text.find(Separator) == StringRef::npos) {
continue;
}
const auto Start = Text[0] == '0' ? 2 : 0;
auto End = Text.find_first_of("uUlLzZn");
auto End = Text.find_first_of("uUlLzZn", Start);
if (End == StringRef::npos)
End = Length;
if (Start > 0 || End < Length) {
@ -124,16 +131,30 @@ IntegerLiteralSeparatorFixer::process(const Environment &Env,
Text = Text.substr(Start, Length);
}
auto DigitsPerGroup = Decimal;
if (IsBase2)
auto MinDigits = DecimalMinDigits;
if (IsBase2) {
DigitsPerGroup = Binary;
else if (IsBase16)
MinDigits = BinaryMinDigits;
} else if (IsBase16) {
DigitsPerGroup = Hex;
if (DigitsPerGroup > 0 && checkSeparator(Text, DigitsPerGroup))
MinDigits = HexMinDigits;
}
const auto SeparatorCount = Text.count(Separator);
const int DigitCount = Length - SeparatorCount;
const bool RemoveSeparator = DigitsPerGroup < 0 || DigitCount < MinDigits;
if (RemoveSeparator && SeparatorCount == 0)
continue;
if (!RemoveSeparator && SeparatorCount > 0 &&
checkSeparator(Text, DigitsPerGroup)) {
continue;
}
const auto &Formatted =
format(Text, DigitsPerGroup, DigitCount, RemoveSeparator);
assert(Formatted != Text);
if (Start > 0)
Location = Location.getLocWithOffset(Start);
cantFail(Result.add(tooling::Replacement(SourceMgr, Location, Length,
format(Text, DigitsPerGroup))));
cantFail(Result.add(
tooling::Replacement(SourceMgr, Location, Length, Formatted)));
}
return {Result, 0};
@ -150,9 +171,9 @@ bool IntegerLiteralSeparatorFixer::checkSeparator(
return false;
I = 0;
} else {
++I;
if (I == DigitsPerGroup)
return false;
++I;
}
}
@ -160,23 +181,20 @@ bool IntegerLiteralSeparatorFixer::checkSeparator(
}
std::string IntegerLiteralSeparatorFixer::format(const StringRef IntegerLiteral,
int DigitsPerGroup) const {
int DigitsPerGroup,
int DigitCount,
bool RemoveSeparator) const {
assert(DigitsPerGroup != 0);
std::string Formatted;
if (DigitsPerGroup < 0) {
if (RemoveSeparator) {
for (auto C : IntegerLiteral)
if (C != Separator)
Formatted.push_back(C);
return Formatted;
}
int DigitCount = 0;
for (auto C : IntegerLiteral)
if (C != Separator)
++DigitCount;
int Remainder = DigitCount % DigitsPerGroup;
int I = 0;

View File

@ -27,7 +27,8 @@ class IntegerLiteralSeparatorFixer {
private:
bool checkSeparator(const StringRef IntegerLiteral, int DigitsPerGroup) const;
std::string format(const StringRef IntegerLiteral, int DigitsPerGroup) const;
std::string format(const StringRef IntegerLiteral, int DigitsPerGroup,
int DigitCount, bool RemoveSeparator) const;
char Separator;
};

View File

@ -280,8 +280,11 @@ const FormatToken *LeftRightQualifierAlignmentFixer::analyzeRight(
// The case `const Foo &&` -> `Foo const &&`
// The case `const std::Foo &&` -> `std::Foo const &&`
// The case `const std::Foo<T> &&` -> `std::Foo<T> const &&`
while (Next && Next->isOneOf(tok::identifier, tok::coloncolon))
// However, `const Bar::*` remains the same.
while (Next && Next->isOneOf(tok::identifier, tok::coloncolon) &&
!Next->startsSequence(tok::coloncolon, tok::star)) {
Next = Next->Next;
}
if (Next && Next->is(TT_TemplateOpener)) {
Next = Next->MatchingParen;
// Move to the end of any template class members e.g.

View File

@ -3833,6 +3833,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true;
if (Style.isCpp()) {
// Space between UDL and dot: auto b = 4s .count();
if (Right.is(tok::period) && Left.is(tok::numeric_constant))
return true;
// Space between import <iostream>.
// or import .....;
if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))

View File

@ -2739,16 +2739,17 @@ void UnwrappedLineParser::handleAttributes() {
// Handle AttributeMacro, e.g. `if (x) UNLIKELY`.
if (FormatTok->is(TT_AttributeMacro))
nextToken();
handleCppAttributes();
if (FormatTok->is(tok::l_square))
handleCppAttributes();
}
bool UnwrappedLineParser::handleCppAttributes() {
// Handle [[likely]] / [[unlikely]] attributes.
if (FormatTok->is(tok::l_square) && tryToParseSimpleAttribute()) {
parseSquare();
return true;
}
return false;
assert(FormatTok->is(tok::l_square));
if (!tryToParseSimpleAttribute())
return false;
parseSquare();
return true;
}
/// Returns whether \c Tok begins a block.
@ -3855,7 +3856,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
// An [[attribute]] can be before the identifier.
while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
tok::kw___attribute, tok::kw___declspec,
tok::kw_alignas, tok::l_square, tok::r_square) ||
tok::kw_alignas, tok::l_square) ||
((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
FormatTok->isOneOf(tok::period, tok::comma))) {
if (Style.isJavaScript() &&
@ -3869,21 +3870,15 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
continue;
}
}
if (FormatTok->is(tok::l_square) && handleCppAttributes())
continue;
bool IsNonMacroIdentifier =
FormatTok->is(tok::identifier) &&
FormatTok->TokenText != FormatTok->TokenText.upper();
nextToken();
// We can have macros or attributes in between 'class' and the class name.
if (!IsNonMacroIdentifier) {
if (FormatTok->is(tok::l_paren)) {
parseParens();
} else if (FormatTok->is(TT_AttributeSquare)) {
parseSquare();
// Consume the closing TT_AttributeSquare.
if (FormatTok->Next && FormatTok->is(TT_AttributeSquare))
nextToken();
}
}
// We can have macros in between 'class' and the class name.
if (!IsNonMacroIdentifier && FormatTok->is(tok::l_paren))
parseParens();
}
// Note that parsing away template declarations here leads to incorrectly

View File

@ -1983,14 +1983,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Module = PP->getHeaderSearchInfo().lookupModule(
ModuleName, ImportLoc, /*AllowSearch*/ true,
/*AllowExtraModuleMapSearch*/ !IsInclusionDirective);
/// FIXME: perhaps we should (a) look for a module using the module name
// to file map (PrebuiltModuleFiles) and (b) diagnose if still not found?
//if (Module == nullptr) {
// getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
// << ModuleName;
// DisableGeneratingGlobalModuleIndex = true;
// return ModuleLoadResult();
//}
MM.cacheModuleLoad(*Path[0].first, Module);
} else {
ModuleLoadResult Result = findOrCompileModuleAndReadAST(

View File

@ -524,7 +524,7 @@ _storebe_i64(void * __P, long long __D) {
#include <invpcidintrin.h>
#endif
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
defined(__AMXFP16__)
defined(__AMX_FP16__)
#include <amxfp16intrin.h>
#endif
@ -534,7 +534,7 @@ _storebe_i64(void * __P, long long __D) {
#endif
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
defined(__AMXTILE__) || defined(__AMXINT8__) || defined(__AMXBF16__)
defined(__AMX_TILE__) || defined(__AMX_INT8__) || defined(__AMX_BF16__)
#include <amxintrin.h>
#endif

View File

@ -1145,7 +1145,7 @@ static __inline__ int __DEFAULT_FN_ATTRS _mm_testnzc_si128(__m128i __M,
/// A 128-bit integer vector containing the bits to be tested.
/// \returns TRUE if the bits specified in the operand are all set to 1; FALSE
/// otherwise.
#define _mm_test_all_ones(V) _mm_testc_si128((V), _mm_cmpeq_epi32((V), (V)))
#define _mm_test_all_ones(V) _mm_testc_si128((V), _mm_set1_epi32(-1))
/// Tests whether the specified bits in a 128-bit integer vector are
/// neither all zeros nor all ones.

View File

@ -1637,35 +1637,14 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Tok.setKind(tok::string_literal);
} else if (II == Ident__FLT_EVAL_METHOD__) {
// __FLT_EVAL_METHOD__ is set to the default value.
if (getTUFPEvalMethod() ==
LangOptions::FPEvalMethodKind::FEM_Indeterminable) {
// This is possible if `AllowFPReassoc` or `AllowReciprocal` is enabled.
// These modes can be triggered via the command line option `-ffast-math`
// or via a `pragam float_control`.
// __FLT_EVAL_METHOD__ expands to -1.
// The `minus` operator is the next token we read from the stream.
auto Toks = std::make_unique<Token[]>(1);
OS << "-";
Tok.setKind(tok::minus);
// Push the token `1` to the stream.
Token NumberToken;
NumberToken.startToken();
NumberToken.setKind(tok::numeric_constant);
NumberToken.setLiteralData("1");
NumberToken.setLength(1);
Toks[0] = NumberToken;
EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion*/ false,
/*IsReinject*/ false);
} else {
OS << getTUFPEvalMethod();
// __FLT_EVAL_METHOD__ expands to a simple numeric value.
Tok.setKind(tok::numeric_constant);
if (getLastFPEvalPragmaLocation().isValid()) {
// The program is ill-formed. The value of __FLT_EVAL_METHOD__ is
// altered by the pragma.
Diag(Tok, diag::err_illegal_use_of_flt_eval_macro);
Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here);
}
OS << getTUFPEvalMethod();
// __FLT_EVAL_METHOD__ expands to a simple numeric value.
Tok.setKind(tok::numeric_constant);
if (getLastFPEvalPragmaLocation().isValid()) {
// The program is ill-formed. The value of __FLT_EVAL_METHOD__ is altered
// by the pragma.
Diag(Tok, diag::err_illegal_use_of_flt_eval_macro);
Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here);
}
} else if (II == Ident__COUNTER__) {
// __COUNTER__ expands to a simple numeric value.

View File

@ -207,11 +207,6 @@ void Preprocessor::Initialize(const TargetInfo &Target,
else
// Set initial value of __FLT_EVAL_METHOD__ from the command line.
setCurrentFPEvalMethod(SourceLocation(), getLangOpts().getFPEvalMethod());
// When `-ffast-math` option is enabled, it triggers several driver math
// options to be enabled. Among those, only one the following two modes
// affect the eval-method: reciprocal or reassociate.
if (getLangOpts().AllowFPReassoc || getLangOpts().AllowRecip)
setCurrentFPEvalMethod(SourceLocation(), LangOptions::FEM_Indeterminable);
}
void Preprocessor::InitializeForModelFile() {
@ -873,6 +868,7 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) {
CurLexerKind != CLK_CachingLexer) {
ModuleImportLoc = Identifier.getLocation();
NamedModuleImportPath.clear();
IsAtImport = true;
ModuleImportExpectsIdentifier = true;
CurLexerKind = CLK_LexAfterModuleImport;
}
@ -940,6 +936,7 @@ void Preprocessor::Lex(Token &Result) {
case tok::semi:
TrackGMFState.handleSemi();
StdCXXImportSeqState.handleSemi();
ModuleDeclState.handleSemi();
break;
case tok::header_name:
case tok::annot_header_unit:
@ -948,6 +945,13 @@ void Preprocessor::Lex(Token &Result) {
case tok::kw_export:
TrackGMFState.handleExport();
StdCXXImportSeqState.handleExport();
ModuleDeclState.handleExport();
break;
case tok::colon:
ModuleDeclState.handleColon();
break;
case tok::period:
ModuleDeclState.handlePeriod();
break;
case tok::identifier:
if (Result.getIdentifierInfo()->isModulesImport()) {
@ -956,18 +960,25 @@ void Preprocessor::Lex(Token &Result) {
if (StdCXXImportSeqState.afterImportSeq()) {
ModuleImportLoc = Result.getLocation();
NamedModuleImportPath.clear();
IsAtImport = false;
ModuleImportExpectsIdentifier = true;
CurLexerKind = CLK_LexAfterModuleImport;
}
break;
} else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) {
TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq());
ModuleDeclState.handleModule();
break;
} else {
ModuleDeclState.handleIdentifier(Result.getIdentifierInfo());
if (ModuleDeclState.isModuleCandidate())
break;
}
[[fallthrough]];
default:
TrackGMFState.handleMisc();
StdCXXImportSeqState.handleMisc();
ModuleDeclState.handleMisc();
break;
}
}
@ -1151,6 +1162,15 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
if (NamedModuleImportPath.empty() && getLangOpts().CPlusPlusModules) {
if (LexHeaderName(Result))
return true;
if (Result.is(tok::colon) && ModuleDeclState.isNamedModule()) {
std::string Name = ModuleDeclState.getPrimaryName().str();
Name += ":";
NamedModuleImportPath.push_back(
{getIdentifierInfo(Name), Result.getLocation()});
CurLexerKind = CLK_LexAfterModuleImport;
return true;
}
} else {
Lex(Result);
}
@ -1164,9 +1184,10 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
/*DisableMacroExpansion*/ true, /*IsReinject*/ false);
};
bool ImportingHeader = Result.is(tok::header_name);
// Check for a header-name.
SmallVector<Token, 32> Suffix;
if (Result.is(tok::header_name)) {
if (ImportingHeader) {
// Enter the header-name token into the token stream; a Lex action cannot
// both return a token and cache tokens (doing so would corrupt the token
// cache if the call to Lex comes from CachingLex / PeekAhead).
@ -1244,8 +1265,8 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
if (ModuleImportExpectsIdentifier && Result.getKind() == tok::identifier) {
// We expected to see an identifier here, and we did; continue handling
// identifiers.
NamedModuleImportPath.push_back(std::make_pair(Result.getIdentifierInfo(),
Result.getLocation()));
NamedModuleImportPath.push_back(
std::make_pair(Result.getIdentifierInfo(), Result.getLocation()));
ModuleImportExpectsIdentifier = false;
CurLexerKind = CLK_LexAfterModuleImport;
return true;
@ -1285,7 +1306,8 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
std::string FlatModuleName;
if (getLangOpts().ModulesTS || getLangOpts().CPlusPlusModules) {
for (auto &Piece : NamedModuleImportPath) {
if (!FlatModuleName.empty())
// If the FlatModuleName ends with colon, it implies it is a partition.
if (!FlatModuleName.empty() && FlatModuleName.back() != ':')
FlatModuleName += ".";
FlatModuleName += Piece.first->getName();
}
@ -1296,7 +1318,8 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
}
Module *Imported = nullptr;
if (getLangOpts().Modules) {
// We don't/shouldn't load the standard c++20 modules when preprocessing.
if (getLangOpts().Modules && !isInImportingCXXNamedModules()) {
Imported = TheModuleLoader.loadModule(ModuleImportLoc,
NamedModuleImportPath,
Module::Hidden,
@ -1304,6 +1327,7 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) {
if (Imported)
makeModuleVisible(Imported, SemiLoc);
}
if (Callbacks)
Callbacks->moduleImport(ModuleImportLoc, NamedModuleImportPath, Imported);

View File

@ -1020,8 +1020,16 @@ static void updateConsecutiveMacroArgTokens(SourceManager &SM,
SourceLocation Limit =
SM.getComposedLoc(BeginFID, SM.getFileIDSize(BeginFID));
Partition = All.take_while([&](const Token &T) {
return T.getLocation() >= BeginLoc && T.getLocation() < Limit &&
NearLast(T.getLocation());
// NOTE: the Limit is included! The lexer recovery only ever inserts a
// single token past the end of the FileID, specifically the ) when a
// macro-arg containing a comma should be guarded by parentheses.
//
// It is safe to include the Limit here because SourceManager allocates
// FileSize + 1 for each SLocEntry.
//
// See https://github.com/llvm/llvm-project/issues/60722.
return T.getLocation() >= BeginLoc && T.getLocation() <= Limit
&& NearLast(T.getLocation());
});
}
assert(!Partition.empty());

View File

@ -4965,7 +4965,6 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
bool IsDependent = false;
const char *PrevSpec = nullptr;
unsigned DiagID;
UsingShadowDecl* FoundUsing = nullptr;
Decl *TagDecl =
Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS,
Name, NameLoc, attrs, AS, DS.getModulePrivateSpecLoc(),
@ -4974,7 +4973,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
BaseType, DSC == DeclSpecContext::DSC_type_specifier,
DSC == DeclSpecContext::DSC_template_param ||
DSC == DeclSpecContext::DSC_template_type_arg,
OffsetOfState, FoundUsing, &SkipBody).get();
OffsetOfState, &SkipBody).get();
if (SkipBody.ShouldSkip) {
assert(TUK == Sema::TUK_Definition && "can only skip a definition");
@ -4984,8 +4983,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
T.skipToEnd();
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,
DiagID, FoundUsing ? FoundUsing : TagDecl, Owned,
NameLoc.isValid() ? NameLoc : StartLoc,
PrevSpec, DiagID, TagDecl, Owned,
Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
return;
@ -5039,8 +5038,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,
DiagID, FoundUsing ? FoundUsing : TagDecl, Owned,
NameLoc.isValid() ? NameLoc : StartLoc,
PrevSpec, DiagID, TagDecl, Owned,
Actions.getASTContext().getPrintingPolicy()))
Diag(StartLoc, DiagID) << PrevSpec;
}

View File

@ -1934,7 +1934,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Create the tag portion of the class or class template.
DeclResult TagOrTempResult = true; // invalid
TypeResult TypeResult = true; // invalid
UsingShadowDecl *FoundUsing = nullptr;
bool Owned = false;
Sema::SkipBodyInfo SkipBody;
@ -2075,7 +2074,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
DSC == DeclSpecContext::DSC_type_specifier,
DSC == DeclSpecContext::DSC_template_param ||
DSC == DeclSpecContext::DSC_template_type_arg,
OffsetOfState, FoundUsing, &SkipBody);
OffsetOfState, &SkipBody);
// If ActOnTag said the type was dependent, try again with the
// less common call.
@ -2134,7 +2133,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
} else if (!TagOrTempResult.isInvalid()) {
Result = DS.SetTypeSpecType(
TagType, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,
DiagID, FoundUsing ? FoundUsing : TagOrTempResult.get(), Owned, Policy);
DiagID, TagOrTempResult.get(), Owned, Policy);
} else {
DS.SetTypeSpecError();
return;

View File

@ -2629,12 +2629,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
enum class Kind { MemberAccess, ArraySubscript };
auto DiagExt = [&](SourceLocation Loc, Kind K) {
Diag(Loc, diag::ext_offsetof_member_designator)
<< (K == Kind::ArraySubscript) << (OOK == Sema::OOK_Macro);
};
// FIXME: This loop leaks the index expressions on error.
while (true) {
if (Tok.is(tok::period)) {
@ -2648,7 +2642,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return ExprError();
}
DiagExt(Comps.back().LocStart, Kind::MemberAccess);
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
Comps.back().LocEnd = ConsumeToken();
} else if (Tok.is(tok::l_square)) {
@ -2666,7 +2659,6 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren, StopAtSemi);
return Res;
}
DiagExt(Comps.back().LocStart, Kind::ArraySubscript);
Comps.back().U.E = Res.get();
ST.consumeClose();

View File

@ -565,13 +565,6 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
case PFC_Precise:
NewFPFeatures.setFPPreciseEnabled(true);
FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
if (PP.getCurrentFPEvalMethod() ==
LangOptions::FPEvalMethodKind::FEM_Indeterminable &&
PP.getLastFPEvalPragmaLocation().isValid())
// A preceding `pragma float_control(precise,off)` has changed
// the value of the evaluation method.
// Set it back to its old value.
PP.setCurrentFPEvalMethod(SourceLocation(), PP.getLastFPEvalMethod());
break;
case PFC_NoPrecise:
if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict)
@ -581,10 +574,6 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
else
NewFPFeatures.setFPPreciseEnabled(false);
FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
PP.setLastFPEvalMethod(PP.getCurrentFPEvalMethod());
// `AllowFPReassoc` or `AllowReciprocal` option is enabled.
PP.setCurrentFPEvalMethod(
Loc, LangOptions::FPEvalMethodKind::FEM_Indeterminable);
break;
case PFC_Except:
if (!isPreciseFPEnabled())
@ -608,12 +597,6 @@ void Sema::ActOnPragmaFloatControl(SourceLocation Loc,
}
FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures);
NewFPFeatures = FpPragmaStack.CurrentValue;
if (CurFPFeatures.getAllowFPReassociate() ||
CurFPFeatures.getAllowReciprocal())
// Since we are popping the pragma, we don't want to be passing
// a location here.
PP.setCurrentFPEvalMethod(SourceLocation(),
CurFPFeatures.getFPEvalMethod());
break;
}
CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts());

View File

@ -150,11 +150,19 @@ bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
namespace {
struct SatisfactionStackRAII {
Sema &SemaRef;
SatisfactionStackRAII(Sema &SemaRef, llvm::FoldingSetNodeID FSNID)
bool Inserted = false;
SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
llvm::FoldingSetNodeID FSNID)
: SemaRef(SemaRef) {
SemaRef.PushSatisfactionStackEntry(FSNID);
if (ND) {
SemaRef.PushSatisfactionStackEntry(ND, FSNID);
Inserted = true;
}
}
~SatisfactionStackRAII() {
if (Inserted)
SemaRef.PopSatisfactionStackEntry();
}
~SatisfactionStackRAII() { SemaRef.PopSatisfactionStackEntry(); }
};
} // namespace
@ -273,7 +281,8 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
}
static bool
DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const Expr *E,
DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
const NamedDecl *Templ, const Expr *E,
const MultiLevelTemplateArgumentList &MLTAL) {
E->Profile(ID, S.Context, /*Canonical=*/true);
for (const auto &List : MLTAL)
@ -286,7 +295,7 @@ DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const Expr *E,
// expression, or when trying to determine the constexpr-ness of special
// members. Otherwise we could just use the
// Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
if (S.SatisfactionStackContains(ID)) {
if (S.SatisfactionStackContains(Templ, ID)) {
S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
<< const_cast<Expr *>(E) << E->getSourceRange();
return true;
@ -317,13 +326,14 @@ static ExprResult calculateConstraintSatisfaction(
return ExprError();
llvm::FoldingSetNodeID ID;
if (DiagRecursiveConstraintEval(S, ID, AtomicExpr, MLTAL)) {
if (Template &&
DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
Satisfaction.IsSatisfied = false;
Satisfaction.ContainsErrors = true;
return ExprEmpty();
}
SatisfactionStackRAII StackRAII(S, ID);
SatisfactionStackRAII StackRAII(S, Template, ID);
// We do not want error diagnostics escaping here.
Sema::SFINAETrap Trap(S);
@ -1132,8 +1142,7 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N,
Sema::InstantiatingTemplate Inst(
S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
ArgsAsWritten->arguments().front().getSourceRange());
if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
return true;

View File

@ -1562,7 +1562,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
const auto *OpDeleteType =
OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
if (OpDeleteType->getNumParams() > DeleteArgs.size() &&
S.getASTContext().hasSameType(
S.getASTContext().hasSameUnqualifiedType(
OpDeleteType->getParamType(DeleteArgs.size()), FrameSize->getType()))
DeleteArgs.push_back(FrameSize);
@ -1579,7 +1579,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
// So we are not forced to pass alignment to the deallocation function.
if (S.getLangOpts().CoroAlignedAllocation &&
OpDeleteType->getNumParams() > DeleteArgs.size() &&
S.getASTContext().hasSameType(
S.getASTContext().hasSameUnqualifiedType(
OpDeleteType->getParamType(DeleteArgs.size()),
FrameAlignment->getType()))
DeleteArgs.push_back(FrameAlignment);

View File

@ -13088,9 +13088,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// C++ [module.import/6] external definitions are not permitted in header
// units.
if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
VDecl->isThisDeclarationADefinition() &&
!VDecl->isInvalidDecl() && VDecl->isThisDeclarationADefinition() &&
VDecl->getFormalLinkage() == Linkage::ExternalLinkage &&
!VDecl->isInline()) {
!VDecl->isInline() && !VDecl->isTemplated() &&
!isa<VarTemplateSpecializationDecl>(VDecl)) {
Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit);
VDecl->setInvalidDecl();
}
@ -15259,9 +15260,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
// FIXME: Consider an alternate location for the test where the inlined()
// state is complete.
if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
!FD->isInvalidDecl() && !FD->isInlined() &&
BodyKind != FnBodyKind::Delete && BodyKind != FnBodyKind::Default &&
FD->getFormalLinkage() == Linkage::ExternalLinkage &&
!FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete &&
BodyKind != FnBodyKind::Default && !FD->isInlined()) {
!FD->isTemplated() && !FD->isTemplateInstantiation()) {
assert(FD->isThisDeclarationADefinition());
Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);
FD->setInvalidDecl();
@ -16616,8 +16618,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
bool &IsDependent, SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
bool IsTypeSpecifier, bool IsTemplateParamOrArg,
OffsetOfKind OOK, UsingShadowDecl *&FoundUsingShadow,
SkipBodyInfo *SkipBody) {
OffsetOfKind OOK, SkipBodyInfo *SkipBody) {
// If this is not a definition, it must have a name.
IdentifierInfo *OrigName = Name;
assert((Name != nullptr || TUK == TUK_Definition) &&
@ -17052,7 +17053,6 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
// redefinition if either context is within the other.
if (auto *Shadow = dyn_cast<UsingShadowDecl>(DirectPrevDecl)) {
auto *OldTag = dyn_cast<TagDecl>(PrevDecl);
FoundUsingShadow = Shadow;
if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend &&
isDeclInScope(Shadow, SearchDC, S, isMemberSpecialization) &&
!(OldTag && isAcceptableTagRedeclContext(
@ -18871,10 +18871,24 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
ProcessDeclAttributeList(S, Record, Attrs);
// Check to see if a FieldDecl is a pointer to a function.
auto IsFunctionPointer = [&](const Decl *D) {
auto IsFunctionPointerOrForwardDecl = [&](const Decl *D) {
const FieldDecl *FD = dyn_cast<FieldDecl>(D);
if (!FD)
if (!FD) {
// Check whether this is a forward declaration that was inserted by
// Clang. This happens when a non-forward declared / defined type is
// used, e.g.:
//
// struct foo {
// struct bar *(*f)();
// struct bar *(*g)();
// };
//
// "struct bar" shows up in the decl AST as a "RecordDecl" with an
// incomplete definition.
if (const auto *TD = dyn_cast<TagDecl>(D))
return !TD->isCompleteDefinition();
return false;
}
QualType FieldType = FD->getType().getDesugaredType(Context);
if (isa<PointerType>(FieldType)) {
QualType PointeeType = cast<PointerType>(FieldType)->getPointeeType();
@ -18888,7 +18902,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
if (!getLangOpts().CPlusPlus &&
(Record->hasAttr<RandomizeLayoutAttr>() ||
(!Record->hasAttr<NoRandomizeLayoutAttr>() &&
llvm::all_of(Record->decls(), IsFunctionPointer))) &&
llvm::all_of(Record->decls(), IsFunctionPointerOrForwardDecl))) &&
!Record->isUnion() && !getLangOpts().RandstructSeed.empty() &&
!Record->isRandomized()) {
SmallVector<Decl *, 32> NewDeclOrdering;

View File

@ -16977,7 +16977,6 @@ DeclResult Sema::ActOnTemplatedFriendTag(
if (SS.isEmpty()) {
bool Owned = false;
bool IsDependent = false;
UsingShadowDecl* FoundUsing = nullptr;
return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, Attr,
AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
@ -16986,7 +16985,7 @@ DeclResult Sema::ActOnTemplatedFriendTag(
/*ScopedEnumUsesClassTag=*/false,
/*UnderlyingType=*/TypeResult(),
/*IsTypeSpecifier=*/false,
/*IsTemplateParamOrArg=*/false, /*OOK=*/OOK_Outside, FoundUsing);
/*IsTemplateParamOrArg=*/false, /*OOK=*/OOK_Outside);
}
NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);

View File

@ -1483,13 +1483,14 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
// Otherwise, if the type contains a placeholder type, it is replaced by the
// type determined by placeholder type deduction.
DeducedType *Deduced = Ty->getContainedDeducedType();
if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) {
if (Deduced && !Deduced->isDeduced() &&
isa<DeducedTemplateSpecializationType>(Deduced)) {
Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity,
Kind, Exprs);
if (Ty.isNull())
return ExprError();
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
} else if (Deduced) {
} else if (Deduced && !Deduced->isDeduced()) {
MultiExprArg Inits = Exprs;
if (ListInitialization) {
auto *ILE = cast<InitListExpr>(Exprs[0]);
@ -2016,7 +2017,8 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
// C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for.
auto *Deduced = AllocType->getContainedDeducedType();
if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) {
if (Deduced && !Deduced->isDeduced() &&
isa<DeducedTemplateSpecializationType>(Deduced)) {
if (ArraySize)
return ExprError(
Diag(*ArraySize ? (*ArraySize)->getExprLoc() : TypeRange.getBegin(),
@ -2030,7 +2032,7 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
AllocTypeInfo, Entity, Kind, Exprs);
if (AllocType.isNull())
return ExprError();
} else if (Deduced) {
} else if (Deduced && !Deduced->isDeduced()) {
MultiExprArg Inits = Exprs;
bool Braced = (initStyle == CXXNewExpr::ListInit);
if (Braced) {

View File

@ -337,20 +337,29 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, SourceLocation ModuleLoc,
}
case ModuleDeclKind::Implementation: {
std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc(
PP.getIdentifierInfo(ModuleName), Path[0].second);
// C++20 A module-declaration that contains neither an export-
// keyword nor a module-partition implicitly imports the primary
// module interface unit of the module as if by a module-import-
// declaration.
std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc(
PP.getIdentifierInfo(ModuleName), Path[0].second);
// The module loader will assume we're trying to import the module that
// we're building if `LangOpts.CurrentModule` equals to 'ModuleName'.
// Change the value for `LangOpts.CurrentModule` temporarily to make the
// module loader work properly.
const_cast<LangOptions&>(getLangOpts()).CurrentModule = "";
Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
Module::AllVisible,
/*IsInclusionDirective=*/false);
const_cast<LangOptions&>(getLangOpts()).CurrentModule = ModuleName;
if (!Mod) {
Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
// Create an empty module interface unit for error recovery.
Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName);
}
} break;
case ModuleDeclKind::PartitionImplementation:

View File

@ -192,7 +192,7 @@ void RISCVIntrinsicManagerImpl::InitIntrinsicList() {
PolicyScheme MaskedPolicyScheme =
static_cast<PolicyScheme>(Record.MaskedPolicyScheme);
const Policy DefaultPolicy(Record.HasTailPolicy, Record.HasMaskPolicy);
const Policy DefaultPolicy;
llvm::SmallVector<PrototypeDescriptor> ProtoSeq =
RVVIntrinsic::computeBuiltinTypes(BasicProtoSeq, /*IsMasked=*/false,
@ -208,8 +208,7 @@ void RISCVIntrinsicManagerImpl::InitIntrinsicList() {
bool UnMaskedHasPolicy = UnMaskedPolicyScheme != PolicyScheme::SchemeNone;
bool MaskedHasPolicy = MaskedPolicyScheme != PolicyScheme::SchemeNone;
SmallVector<Policy> SupportedUnMaskedPolicies =
RVVIntrinsic::getSupportedUnMaskedPolicies(Record.HasTailPolicy,
Record.HasMaskPolicy);
RVVIntrinsic::getSupportedUnMaskedPolicies();
SmallVector<Policy> SupportedMaskedPolicies =
RVVIntrinsic::getSupportedMaskedPolicies(Record.HasTailPolicy,
Record.HasMaskPolicy);

View File

@ -2540,8 +2540,6 @@ struct ConvertConstructorToDeductionGuideTransform {
TInfo->getType(), TInfo, LocEnd, Ctor);
Guide->setImplicit();
Guide->setParams(Params);
if (Ctor && Ctor->getTrailingRequiresClause())
Guide->setTrailingRequiresClause(Ctor->getTrailingRequiresClause());
for (auto *Param : Params)
Param->setDeclContext(Guide);
@ -10181,14 +10179,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
bool Owned = false;
bool IsDependent = false;
UsingShadowDecl* FoundUsing = nullptr;
Decl *TagD =
ActOnTag(S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name, NameLoc, Attr,
AS_none, /*ModulePrivateLoc=*/SourceLocation(),
Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name,
NameLoc, Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(), Owned, IsDependent, SourceLocation(),
false, TypeResult(), /*IsTypeSpecifier*/ false,
/*IsTemplateParamOrArg*/ false, /*OOK=*/OOK_Outside, FoundUsing)
.get();
/*IsTemplateParamOrArg*/ false, /*OOK=*/OOK_Outside).get();
assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
if (!TagD)

View File

@ -756,11 +756,8 @@ class PackDeductionScope {
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
UnexpandedParameterPack U = Unexpanded[I];
if (U.first.is<const SubstTemplateTypeParmPackType *>() ||
U.first.is<const SubstNonTypeTemplateParmPackExpr *>())
continue;
auto [Depth, Index] = getDepthAndIndex(U);
unsigned Depth, Index;
std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
if (Depth == Info.getDeducedDepth())
AddPack(Index);
}

View File

@ -89,23 +89,6 @@ namespace {
return true;
}
bool
VisitSubstTemplateTypeParmPackTypeLoc(SubstTemplateTypeParmPackTypeLoc TL) {
Unexpanded.push_back({TL.getTypePtr(), TL.getNameLoc()});
return true;
}
bool VisitSubstTemplateTypeParmPackType(SubstTemplateTypeParmPackType *T) {
Unexpanded.push_back({T, SourceLocation()});
return true;
}
bool
VisitSubstNonTypeTemplateParmPackExpr(SubstNonTypeTemplateParmPackExpr *E) {
Unexpanded.push_back({E, E->getParameterPackLocation()});
return true;
}
/// Record occurrences of function and non-type template
/// parameter packs in an expression.
bool VisitDeclRefExpr(DeclRefExpr *E) {
@ -324,8 +307,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
auto *TTPD = dyn_cast<TemplateTypeParmDecl>(LocalPack);
return TTPD && TTPD->getTypeForDecl() == TTPT;
}
return declaresSameEntity(Pack.first.get<const NamedDecl *>(),
LocalPack);
return declaresSameEntity(Pack.first.get<NamedDecl *>(), LocalPack);
};
if (llvm::any_of(LSI->LocalPacks, DeclaresThisPack))
LambdaParamPackReferences.push_back(Pack);
@ -377,7 +359,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>())
Name = TTP->getIdentifier();
else
Name = Unexpanded[I].first.get<const NamedDecl *>()->getIdentifier();
Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier();
if (Name && NamesKnown.insert(Name).second)
Names.push_back(Name);
@ -440,7 +422,7 @@ bool Sema::DiagnoseUnexpandedParameterPackInRequiresExpr(RequiresExpr *RE) {
llvm::SmallPtrSet<NamedDecl*, 8> ParmSet(Parms.begin(), Parms.end());
SmallVector<UnexpandedParameterPack, 2> UnexpandedParms;
for (auto Parm : Unexpanded)
if (ParmSet.contains(Parm.first.dyn_cast<const NamedDecl *>()))
if (ParmSet.contains(Parm.first.dyn_cast<NamedDecl *>()))
UnexpandedParms.push_back(Parm);
if (UnexpandedParms.empty())
return false;
@ -692,95 +674,109 @@ bool Sema::CheckParameterPacksForExpansion(
bool &RetainExpansion, std::optional<unsigned> &NumExpansions) {
ShouldExpand = true;
RetainExpansion = false;
std::pair<const IdentifierInfo *, SourceLocation> FirstPack;
std::optional<std::pair<unsigned, SourceLocation>> PartialExpansion;
std::optional<unsigned> CurNumExpansions;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;
std::optional<unsigned> NumPartialExpansions;
SourceLocation PartiallySubstitutedPackLoc;
for (auto [P, Loc] : Unexpanded) {
for (UnexpandedParameterPack ParmPack : Unexpanded) {
// Compute the depth and index for this parameter pack.
std::optional<std::pair<unsigned, unsigned>> Pos;
unsigned Depth = 0, Index = 0;
IdentifierInfo *Name;
bool IsVarDeclPack = false;
if (const TemplateTypeParmType *TTP =
ParmPack.first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth();
Index = TTP->getIndex();
Name = TTP->getIdentifier();
} else {
NamedDecl *ND = ParmPack.first.get<NamedDecl *>();
if (isa<VarDecl>(ND))
IsVarDeclPack = true;
else
std::tie(Depth, Index) = getDepthAndIndex(ND);
Name = ND->getIdentifier();
}
// Determine the size of this argument pack.
unsigned NewPackSize;
const auto *ND = P.dyn_cast<const NamedDecl *>();
if (ND && isa<VarDecl>(ND)) {
const auto *DAP =
CurrentInstantiationScope->findInstantiationOf(ND)
->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>();
if (!DAP) {
if (IsVarDeclPack) {
// Figure out whether we're instantiating to an argument pack or not.
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
CurrentInstantiationScope->findInstantiationOf(
ParmPack.first.get<NamedDecl *>());
if (Instantiation->is<DeclArgumentPack *>()) {
// We could expand this function parameter pack.
NewPackSize = Instantiation->get<DeclArgumentPack *>()->size();
} else {
// We can't expand this function parameter pack, so we can't expand
// the pack expansion.
ShouldExpand = false;
continue;
}
NewPackSize = DAP->size();
} else if (ND) {
Pos = getDepthAndIndex(ND);
} else if (const auto *TTP = P.dyn_cast<const TemplateTypeParmType *>()) {
Pos = {TTP->getDepth(), TTP->getIndex()};
ND = TTP->getDecl();
// FIXME: We either should have some fallback for canonical TTP, or
// never have canonical TTP here.
} else if (const auto *STP =
P.dyn_cast<const SubstTemplateTypeParmPackType *>()) {
NewPackSize = STP->getNumArgs();
ND = STP->getReplacedParameter();
} else {
const auto *SEP = P.get<const SubstNonTypeTemplateParmPackExpr *>();
NewPackSize = SEP->getArgumentPack().pack_size();
ND = SEP->getParameterPack();
}
if (Pos) {
// If we don't have a template argument at this depth/index, then we
// cannot expand the pack expansion. Make a note of this, but we still
// want to check any parameter packs we *do* have arguments for.
if (Pos->first >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Pos->first, Pos->second)) {
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index)) {
ShouldExpand = false;
continue;
}
// Determine the size of the argument pack.
NewPackSize = TemplateArgs(Pos->first, Pos->second).pack_size();
// C++0x [temp.arg.explicit]p9:
// Template argument deduction can extend the sequence of template
// arguments corresponding to a template parameter pack, even when the
// sequence contains explicitly specified template arguments.
if (CurrentInstantiationScope)
if (const NamedDecl *PartialPack =
CurrentInstantiationScope->getPartiallySubstitutedPack();
PartialPack && getDepthAndIndex(PartialPack) == *Pos) {
RetainExpansion = true;
// We don't actually know the new pack size yet.
PartialExpansion = {NewPackSize, Loc};
continue;
}
NewPackSize = TemplateArgs(Depth, Index).pack_size();
}
// FIXME: Workaround for Canonical TTP.
const IdentifierInfo *Name = ND ? ND->getIdentifier() : nullptr;
if (!CurNumExpansions) {
// C++0x [temp.arg.explicit]p9:
// Template argument deduction can extend the sequence of template
// arguments corresponding to a template parameter pack, even when the
// sequence contains explicitly specified template arguments.
if (!IsVarDeclPack && CurrentInstantiationScope) {
if (NamedDecl *PartialPack =
CurrentInstantiationScope->getPartiallySubstitutedPack()) {
unsigned PartialDepth, PartialIndex;
std::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
if (PartialDepth == Depth && PartialIndex == Index) {
RetainExpansion = true;
// We don't actually know the new pack size yet.
NumPartialExpansions = NewPackSize;
PartiallySubstitutedPackLoc = ParmPack.second;
continue;
}
}
}
if (!NumExpansions) {
// The is the first pack we've seen for which we have an argument.
// Record it.
CurNumExpansions = NewPackSize;
FirstPack = {Name, Loc};
} else if (NewPackSize != *CurNumExpansions) {
NumExpansions = NewPackSize;
FirstPack.first = Name;
FirstPack.second = ParmPack.second;
HaveFirstPack = true;
continue;
}
if (NewPackSize != *NumExpansions) {
// C++0x [temp.variadic]p5:
// All of the parameter packs expanded by a pack expansion shall have
// the same number of arguments specified.
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
<< FirstPack.first << Name << *CurNumExpansions << NewPackSize
<< SourceRange(FirstPack.second) << SourceRange(Loc);
if (HaveFirstPack)
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict)
<< FirstPack.first << Name << *NumExpansions << NewPackSize
<< SourceRange(FirstPack.second) << SourceRange(ParmPack.second);
else
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
<< Name << *NumExpansions << NewPackSize
<< SourceRange(ParmPack.second);
return true;
}
}
if (NumExpansions && CurNumExpansions &&
*NumExpansions != *CurNumExpansions) {
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel)
<< FirstPack.first << *CurNumExpansions << *NumExpansions
<< SourceRange(FirstPack.second);
return true;
}
// If we're performing a partial expansion but we also have a full expansion,
// expand to the number of common arguments. For example, given:
//
@ -790,18 +786,17 @@ bool Sema::CheckParameterPacksForExpansion(
//
// ... a call to 'A<int, int>().f<int>' should expand the pack once and
// retain an expansion.
if (PartialExpansion) {
if (CurNumExpansions && *CurNumExpansions < PartialExpansion->first) {
if (NumPartialExpansions) {
if (NumExpansions && *NumExpansions < *NumPartialExpansions) {
NamedDecl *PartialPack =
CurrentInstantiationScope->getPartiallySubstitutedPack();
Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial)
<< PartialPack << PartialExpansion->first << *CurNumExpansions
<< SourceRange(PartialExpansion->second);
<< PartialPack << *NumPartialExpansions << *NumExpansions
<< SourceRange(PartiallySubstitutedPackLoc);
return true;
}
NumExpansions = PartialExpansion->first;
} else {
NumExpansions = CurNumExpansions;
NumExpansions = NumPartialExpansions;
}
return false;
@ -814,48 +809,47 @@ std::optional<unsigned> Sema::getNumArgumentsInExpansion(
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
std::optional<unsigned> Result;
auto setResultSz = [&Result](unsigned Size) {
assert((!Result || *Result == Size) && "inconsistent pack sizes");
Result = Size;
};
auto setResultPos = [&](const std::pair<unsigned, unsigned> &Pos) -> bool {
unsigned Depth = Pos.first, Index = Pos.second;
for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
// Compute the depth and index for this parameter pack.
unsigned Depth;
unsigned Index;
if (const TemplateTypeParmType *TTP =
Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
Depth = TTP->getDepth();
Index = TTP->getIndex();
} else {
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
if (isa<VarDecl>(ND)) {
// Function parameter pack or init-capture pack.
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation =
CurrentInstantiationScope->findInstantiationOf(
Unexpanded[I].first.get<NamedDecl *>());
if (Instantiation->is<Decl *>())
// The pattern refers to an unexpanded pack. We're not ready to expand
// this pack yet.
return std::nullopt;
unsigned Size = Instantiation->get<DeclArgumentPack *>()->size();
assert((!Result || *Result == Size) && "inconsistent pack sizes");
Result = Size;
continue;
}
std::tie(Depth, Index) = getDepthAndIndex(ND);
}
if (Depth >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(Depth, Index))
// The pattern refers to an unknown template argument. We're not ready to
// expand this pack yet.
return true;
// Determine the size of the argument pack.
setResultSz(TemplateArgs(Depth, Index).pack_size());
return false;
};
return std::nullopt;
for (auto [I, _] : Unexpanded) {
if (const auto *TTP = I.dyn_cast<const TemplateTypeParmType *>()) {
if (setResultPos({TTP->getDepth(), TTP->getIndex()}))
return std::nullopt;
} else if (const auto *STP =
I.dyn_cast<const SubstTemplateTypeParmPackType *>()) {
setResultSz(STP->getNumArgs());
} else if (const auto *SEP =
I.dyn_cast<const SubstNonTypeTemplateParmPackExpr *>()) {
setResultSz(SEP->getArgumentPack().pack_size());
} else {
const auto *ND = I.get<const NamedDecl *>();
// Function parameter pack or init-capture pack.
if (isa<VarDecl>(ND)) {
const auto *DAP =
CurrentInstantiationScope->findInstantiationOf(ND)
->dyn_cast<LocalInstantiationScope::DeclArgumentPack *>();
if (!DAP)
// The pattern refers to an unexpanded pack. We're not ready to expand
// this pack yet.
return std::nullopt;
setResultSz(DAP->size());
} else if (setResultPos(getDepthAndIndex(ND))) {
return std::nullopt;
}
}
// Determine the size of the argument pack.
unsigned Size = TemplateArgs(Depth, Index).pack_size();
assert((!Result || *Result == Size) && "inconsistent pack sizes");
Result = Size;
}
return Result;

View File

@ -1588,9 +1588,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// TypeQuals handled by caller.
Result = Context.getTypeDeclType(D);
if (const auto *Using =
dyn_cast_or_null<UsingShadowDecl>(DS.getRepAsFoundDecl()))
Result = Context.getUsingType(Using, Result);
// In both C and C++, make an ElaboratedType.
ElaboratedTypeKeyword Keyword
@ -6256,9 +6253,6 @@ namespace {
void VisitTagTypeLoc(TagTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
void VisitUsingTypeLoc(UsingTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
// An AtomicTypeLoc can come from either an _Atomic(...) type specifier
// or an _Atomic qualifier.

View File

@ -4569,7 +4569,7 @@ bool TreeTransform<Derived>::TransformTemplateArgument(
getSema(),
Uneval ? Sema::ExpressionEvaluationContext::Unevaluated
: Sema::ExpressionEvaluationContext::ConstantEvaluated,
/*LambdaContextDecl=*/nullptr, /*ExprContext=*/
Sema::ReuseLambdaContextDecl, /*ExprContext=*/
Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument);
Expr *InputExpr = Input.getSourceExpression();
@ -5897,7 +5897,6 @@ bool TreeTransform<Derived>::TransformFunctionTypeParams(
= dyn_cast<PackExpansionType>(OldType)) {
// We have a function parameter pack that may need to be expanded.
QualType Pattern = Expansion->getPattern();
NumExpansions = Expansion->getNumExpansions();
SmallVector<UnexpandedParameterPack, 2> Unexpanded;
getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded);

View File

@ -41,6 +41,10 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
if (!RetE)
return;
// Skip "body farmed" functions.
if (RetE->getSourceRange().isInvalid())
return;
SVal V = C.getSVal(RetE);
const MemRegion *R = V.getAsRegion();

View File

@ -766,7 +766,7 @@ PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForSwitchOP(
case Stmt::CaseStmtClass: {
os << "Control jumps to 'case ";
const auto *Case = cast<CaseStmt>(S);
const Expr *LHS = Case->getLHS()->IgnoreParenCasts();
const Expr *LHS = Case->getLHS()->IgnoreParenImpCasts();
// Determine if it is an enum.
bool GetRawInt = true;

View File

@ -2678,7 +2678,18 @@ EquivalenceClass::simplify(SValBuilder &SVB, RangeSet::Factory &F,
if (OldState == State)
continue;
assert(find(State, MemberSym) == find(State, SimplifiedMemberSym));
// Be aware that `SimplifiedMemberSym` might refer to an already dead
// symbol. In that case, the eqclass of that might not be the same as the
// eqclass of `MemberSym`. This is because the dead symbols are not
// preserved in the `ClassMap`, hence
// `find(State, SimplifiedMemberSym)` will result in a trivial eqclass
// compared to the eqclass of `MemberSym`.
// These eqclasses should be the same if `SimplifiedMemberSym` is alive.
// --> assert(find(State, MemberSym) == find(State, SimplifiedMemberSym))
//
// Note that `MemberSym` must be alive here since that is from the
// `ClassMembers` where all the symbols are alive.
// Remove the old and more complex symbol.
State = find(State, MemberSym).removeMember(State, MemberSym);

View File

@ -1849,8 +1849,12 @@ std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
// Go to the nested initializer list.
ILE = IL;
}
llvm_unreachable(
"Unhandled InitListExpr sub-expressions or invalid offsets.");
assert(ILE);
// FIXME: Unhandeled InitListExpr sub-expression, possibly constructing an
// enum?
return std::nullopt;
}
/// Returns an SVal, if possible, for the specified position in a string

View File

@ -966,40 +966,26 @@ llvm::SmallVector<PrototypeDescriptor> RVVIntrinsic::computeBuiltinTypes(
return NewPrototype;
}
llvm::SmallVector<Policy>
RVVIntrinsic::getSupportedUnMaskedPolicies(bool HasTailPolicy,
bool HasMaskPolicy) {
return {
Policy(Policy::PolicyType::Undisturbed, HasTailPolicy,
HasMaskPolicy), // TU
Policy(Policy::PolicyType::Agnostic, HasTailPolicy, HasMaskPolicy)}; // TA
llvm::SmallVector<Policy> RVVIntrinsic::getSupportedUnMaskedPolicies() {
return {Policy(Policy::PolicyType::Undisturbed)}; // TU
}
llvm::SmallVector<Policy>
RVVIntrinsic::getSupportedMaskedPolicies(bool HasTailPolicy,
bool HasMaskPolicy) {
if (HasTailPolicy && HasMaskPolicy)
return {
Policy(Policy::PolicyType::Undisturbed, Policy::PolicyType::Agnostic,
HasTailPolicy, HasMaskPolicy), // TUMA
Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Agnostic,
HasTailPolicy, HasMaskPolicy), // TAMA
Policy(Policy::PolicyType::Undisturbed, Policy::PolicyType::Undisturbed,
HasTailPolicy, HasMaskPolicy), // TUMU
Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Undisturbed,
HasTailPolicy, HasMaskPolicy)}; // TAMU
return {Policy(Policy::PolicyType::Undisturbed,
Policy::PolicyType::Agnostic), // TUM
Policy(Policy::PolicyType::Undisturbed,
Policy::PolicyType::Undisturbed), // TUMU
Policy(Policy::PolicyType::Agnostic,
Policy::PolicyType::Undisturbed)}; // MU
if (HasTailPolicy && !HasMaskPolicy)
return {Policy(Policy::PolicyType::Undisturbed,
Policy::PolicyType::Agnostic, HasTailPolicy,
HasMaskPolicy), // TUM
Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Agnostic,
HasTailPolicy, HasMaskPolicy)}; // TAM
Policy::PolicyType::Agnostic)}; // TU
if (!HasTailPolicy && HasMaskPolicy)
return {Policy(Policy::PolicyType::Agnostic, Policy::PolicyType::Agnostic,
HasTailPolicy, HasMaskPolicy), // MA
Policy(Policy::PolicyType::Agnostic,
Policy::PolicyType::Undisturbed, HasTailPolicy,
HasMaskPolicy)}; // MU
return {Policy(Policy::PolicyType::Agnostic,
Policy::PolicyType::Undisturbed)}; // MU
llvm_unreachable("An RVV instruction should not be without both tail policy "
"and mask policy");
}
@ -1016,46 +1002,34 @@ void RVVIntrinsic::updateNamesAndPolicy(bool IsMasked, bool HasPolicy,
OverloadedName += suffix;
};
if (PolicyAttrs.isUnspecified()) {
PolicyAttrs.IsUnspecified = false;
if (IsMasked) {
// This follows the naming guideline under riscv-c-api-doc to add the
// `__riscv_` suffix for all RVV intrinsics.
Name = "__riscv_" + Name;
OverloadedName = "__riscv_" + OverloadedName;
if (IsMasked) {
if (PolicyAttrs.isTUMUPolicy())
appendPolicySuffix("_tumu");
else if (PolicyAttrs.isTUMAPolicy())
appendPolicySuffix("_tum");
else if (PolicyAttrs.isTAMUPolicy())
appendPolicySuffix("_mu");
else if (PolicyAttrs.isTAMAPolicy()) {
Name += "_m";
if (HasPolicy)
BuiltinName += "_tama";
else
BuiltinName += "_m";
} else {
} else
llvm_unreachable("Unhandled policy condition");
} else {
if (PolicyAttrs.isTUPolicy())
appendPolicySuffix("_tu");
else if (PolicyAttrs.isTAPolicy()) {
if (HasPolicy)
BuiltinName += "_ta";
}
} else {
if (IsMasked) {
if (PolicyAttrs.isTUMAPolicy() && !PolicyAttrs.hasMaskPolicy())
appendPolicySuffix("_tum");
else if (PolicyAttrs.isTAMAPolicy() && !PolicyAttrs.hasMaskPolicy())
appendPolicySuffix("_tam");
else if (PolicyAttrs.isMUPolicy() && !PolicyAttrs.hasTailPolicy())
appendPolicySuffix("_mu");
else if (PolicyAttrs.isMAPolicy() && !PolicyAttrs.hasTailPolicy())
appendPolicySuffix("_ma");
else if (PolicyAttrs.isTUMUPolicy())
appendPolicySuffix("_tumu");
else if (PolicyAttrs.isTAMUPolicy())
appendPolicySuffix("_tamu");
else if (PolicyAttrs.isTUMAPolicy())
appendPolicySuffix("_tuma");
else if (PolicyAttrs.isTAMAPolicy())
appendPolicySuffix("_tama");
else
llvm_unreachable("Unhandled policy condition");
} else {
if (PolicyAttrs.isTUPolicy())
appendPolicySuffix("_tu");
else if (PolicyAttrs.isTAPolicy())
appendPolicySuffix("_ta");
else
llvm_unreachable("Unhandled policy condition");
}
} else
llvm_unreachable("Unhandled policy condition");
}
}

View File

@ -40,67 +40,69 @@ DependencyScanningTool::DependencyScanningTool(
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS)
: Worker(Service, std::move(FS)) {}
namespace {
/// Prints out all of the gathered dependencies into a string.
class MakeDependencyPrinterConsumer : public DependencyConsumer {
public:
void handleBuildCommand(Command) override {}
void
handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
}
void handleFileDependency(StringRef File) override {
Dependencies.push_back(std::string(File));
}
void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
// Same as `handleModuleDependency`.
}
void handleModuleDependency(ModuleDeps MD) override {
// These are ignored for the make format as it can't support the full
// set of deps, and handleFileDependency handles enough for implicitly
// built modules to work.
}
void handleContextHash(std::string Hash) override {}
std::string lookupModuleOutput(const ModuleID &ID,
ModuleOutputKind Kind) override {
llvm::report_fatal_error("unexpected call to lookupModuleOutput");
}
void printDependencies(std::string &S) {
assert(Opts && "Handled dependency output options.");
class DependencyPrinter : public DependencyFileGenerator {
public:
DependencyPrinter(DependencyOutputOptions &Opts,
ArrayRef<std::string> Dependencies)
: DependencyFileGenerator(Opts) {
for (const auto &Dep : Dependencies)
addDependency(Dep);
}
void printDependencies(std::string &S) {
llvm::raw_string_ostream OS(S);
outputDependencyFile(OS);
}
};
DependencyPrinter Generator(*Opts, Dependencies);
Generator.printDependencies(S);
}
protected:
std::unique_ptr<DependencyOutputOptions> Opts;
std::vector<std::string> Dependencies;
};
} // anonymous namespace
llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
const std::vector<std::string> &CommandLine, StringRef CWD,
std::optional<StringRef> ModuleName) {
/// Prints out all of the gathered dependencies into a string.
class MakeDependencyPrinterConsumer : public DependencyConsumer {
public:
void handleBuildCommand(Command) override {}
void
handleDependencyOutputOpts(const DependencyOutputOptions &Opts) override {
this->Opts = std::make_unique<DependencyOutputOptions>(Opts);
}
void handleFileDependency(StringRef File) override {
Dependencies.push_back(std::string(File));
}
void handlePrebuiltModuleDependency(PrebuiltModuleDep PMD) override {
// Same as `handleModuleDependency`.
}
void handleModuleDependency(ModuleDeps MD) override {
// These are ignored for the make format as it can't support the full
// set of deps, and handleFileDependency handles enough for implicitly
// built modules to work.
}
void handleContextHash(std::string Hash) override {}
std::string lookupModuleOutput(const ModuleID &ID,
ModuleOutputKind Kind) override {
llvm::report_fatal_error("unexpected call to lookupModuleOutput");
}
void printDependencies(std::string &S) {
assert(Opts && "Handled dependency output options.");
class DependencyPrinter : public DependencyFileGenerator {
public:
DependencyPrinter(DependencyOutputOptions &Opts,
ArrayRef<std::string> Dependencies)
: DependencyFileGenerator(Opts) {
for (const auto &Dep : Dependencies)
addDependency(Dep);
}
void printDependencies(std::string &S) {
llvm::raw_string_ostream OS(S);
outputDependencyFile(OS);
}
};
DependencyPrinter Generator(*Opts, Dependencies);
Generator.printDependencies(S);
}
private:
std::unique_ptr<DependencyOutputOptions> Opts;
std::vector<std::string> Dependencies;
};
MakeDependencyPrinterConsumer Consumer;
auto Result =
Worker.computeDependencies(CWD, CommandLine, Consumer, ModuleName);
@ -111,6 +113,50 @@ llvm::Expected<std::string> DependencyScanningTool::getDependencyFile(
return Output;
}
llvm::Expected<P1689Rule> DependencyScanningTool::getP1689ModuleDependencyFile(
const CompileCommand &Command, StringRef CWD,
std::string &MakeformatOutput, std::string &MakeformatOutputPath) {
class P1689ModuleDependencyPrinterConsumer
: public MakeDependencyPrinterConsumer {
public:
P1689ModuleDependencyPrinterConsumer(P1689Rule &Rule,
const CompileCommand &Command)
: Filename(Command.Filename), Rule(Rule) {
Rule.PrimaryOutput = Command.Output;
}
void handleProvidedAndRequiredStdCXXModules(
std::optional<P1689ModuleInfo> Provided,
std::vector<P1689ModuleInfo> Requires) override {
Rule.Provides = Provided;
if (Rule.Provides)
Rule.Provides->SourcePath = Filename.str();
Rule.Requires = Requires;
}
StringRef getMakeFormatDependencyOutputPath() {
if (Opts->OutputFormat != DependencyOutputFormat::Make)
return {};
return Opts->OutputFile;
}
private:
StringRef Filename;
P1689Rule &Rule;
};
P1689Rule Rule;
P1689ModuleDependencyPrinterConsumer Consumer(Rule, Command);
auto Result = Worker.computeDependencies(CWD, Command.CommandLine, Consumer);
if (Result)
return std::move(Result);
MakeformatOutputPath = Consumer.getMakeFormatDependencyOutputPath();
if (!MakeformatOutputPath.empty())
Consumer.printDependencies(MakeformatOutput);
return Rule;
}
llvm::Expected<FullDependenciesResult>
DependencyScanningTool::getFullDependencies(
const std::vector<std::string> &CommandLine, StringRef CWD,

View File

@ -247,10 +247,12 @@ class DependencyScanningAction : public tooling::ToolAction {
std::make_shared<DependencyConsumerForwarder>(
std::move(Opts), WorkingDirectory, Consumer));
break;
case ScanningOutputFormat::P1689:
case ScanningOutputFormat::Full:
MDC = std::make_shared<ModuleDepCollector>(
std::move(Opts), ScanInstance, Consumer, OriginalInvocation,
OptimizeArgs, EagerLoadModules);
OptimizeArgs, EagerLoadModules,
Format == ScanningOutputFormat::P1689);
ScanInstance.addDependencyCollector(MDC);
break;
}

View File

@ -339,6 +339,14 @@ void ModuleDepCollectorPP::InclusionDirective(
void ModuleDepCollectorPP::moduleImport(SourceLocation ImportLoc,
ModuleIdPath Path,
const Module *Imported) {
if (MDC.ScanInstance.getPreprocessor().isInImportingCXXNamedModules()) {
P1689ModuleInfo RequiredModule;
RequiredModule.ModuleName = Path[0].first->getName().str();
RequiredModule.Type = P1689ModuleInfo::ModuleType::NamedCXXModule;
MDC.RequiredStdCXXModules.push_back(RequiredModule);
return;
}
handleImport(Imported);
}
@ -361,6 +369,21 @@ void ModuleDepCollectorPP::EndOfMainFile() {
.getFileEntryForID(MainFileID)
->getName());
auto &PP = MDC.ScanInstance.getPreprocessor();
if (PP.isInNamedModule()) {
P1689ModuleInfo ProvidedModule;
ProvidedModule.ModuleName = PP.getNamedModuleName();
ProvidedModule.Type = P1689ModuleInfo::ModuleType::NamedCXXModule;
ProvidedModule.IsStdCXXModuleInterface = PP.isInNamedInterfaceUnit();
// Don't put implementation (non partition) unit as Provide.
// Put the module as required instead. Since the implementation
// unit will import the primary module implicitly.
if (PP.isInImplementationUnit())
MDC.RequiredStdCXXModules.push_back(ProvidedModule);
else
MDC.ProvidedStdCXXModule = ProvidedModule;
}
if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude);
@ -374,6 +397,10 @@ void ModuleDepCollectorPP::EndOfMainFile() {
MDC.Consumer.handleDependencyOutputOpts(*MDC.Opts);
if (MDC.IsStdModuleP1689Format)
MDC.Consumer.handleProvidedAndRequiredStdCXXModules(
MDC.ProvidedStdCXXModule, MDC.RequiredStdCXXModules);
for (auto &&I : MDC.ModularDeps)
MDC.Consumer.handleModuleDependency(*I.second);
@ -548,10 +575,12 @@ void ModuleDepCollectorPP::addAffectingClangModule(
ModuleDepCollector::ModuleDepCollector(
std::unique_ptr<DependencyOutputOptions> Opts,
CompilerInstance &ScanInstance, DependencyConsumer &C,
CompilerInvocation OriginalCI, bool OptimizeArgs, bool EagerLoadModules)
CompilerInvocation OriginalCI, bool OptimizeArgs, bool EagerLoadModules,
bool IsStdModuleP1689Format)
: ScanInstance(ScanInstance), Consumer(C), Opts(std::move(Opts)),
OriginalInvocation(std::move(OriginalCI)), OptimizeArgs(OptimizeArgs),
EagerLoadModules(EagerLoadModules) {}
EagerLoadModules(EagerLoadModules),
IsStdModuleP1689Format(IsStdModuleP1689Format) {}
void ModuleDepCollector::attachToPreprocessor(Preprocessor &PP) {
PP.addPPCallbacks(std::make_unique<ModuleDepCollectorPP>(*this));

View File

@ -521,10 +521,9 @@ void RVVEmitter::createRVVIntrinsics(
StringRef MaskedIRName = R->getValueAsString("MaskedIRName");
unsigned NF = R->getValueAsInt("NF");
const Policy DefaultPolicy(HasTailPolicy, HasMaskPolicy);
const Policy DefaultPolicy;
SmallVector<Policy> SupportedUnMaskedPolicies =
RVVIntrinsic::getSupportedUnMaskedPolicies(HasTailPolicy,
HasMaskPolicy);
RVVIntrinsic::getSupportedUnMaskedPolicies();
SmallVector<Policy> SupportedMaskedPolicies =
RVVIntrinsic::getSupportedMaskedPolicies(HasTailPolicy, HasMaskPolicy);

View File

@ -924,6 +924,9 @@ int CONSTRUCTOR_ATTRIBUTE __cpu_indicator_init(void) {
#define HWCAP_SB (1 << 29)
#endif
#ifndef AT_HWCAP2
#define AT_HWCAP2 26
#endif
#ifndef HWCAP2_DCPODP
#define HWCAP2_DCPODP (1 << 0)
#endif

View File

@ -585,6 +585,7 @@ static void GetTls(uptr *addr, uptr *size) {
*addr = (uptr)tcb->tcb_dtv[1];
}
}
#else
#error "Unknown OS"
#endif
}

View File

@ -231,8 +231,6 @@ bool SymbolizerProcess::StartSymbolizerSubprocess() {
// Check that tool command lines are simple and that complete escaping is
// unnecessary.
CHECK(!internal_strchr(arg, '"') && "quotes in args unsupported");
CHECK(!internal_strstr(arg, "\\\\") &&
"double backslashes in args unsupported");
CHECK(arglen > 0 && arg[arglen - 1] != '\\' &&
"args ending in backslash and empty args unsupported");
command_line.append("\"%s\" ", arg);

View File

@ -36,7 +36,7 @@ struct __fn {
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const {
auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj);
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first));
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret));
}
template <forward_range _Range, class _Type, class _Proj = identity,
@ -46,7 +46,7 @@ struct __fn {
auto __first = ranges::begin(__r);
auto __last = ranges::end(__r);
auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj);
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first));
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret));
}
};
} // namespace __binary_search

View File

@ -11,15 +11,10 @@
#include <__algorithm/comp.h>
#include <__algorithm/comp_ref_type.h>
#include <__algorithm/iter_swap.h>
#include <__algorithm/iterator_operations.h>
#include <__algorithm/min_element.h>
#include <__algorithm/partial_sort.h>
#include <__algorithm/unwrap_iter.h>
#include <__assert>
#include <__bit/blsr.h>
#include <__bit/countl.h>
#include <__bit/countr.h>
#include <__config>
#include <__debug>
#include <__debug_utils/randomize_range.h>
@ -28,10 +23,11 @@
#include <__iterator/iterator_traits.h>
#include <__memory/destruct_n.h>
#include <__memory/unique_ptr.h>
#include <__type_traits/conditional.h>
#include <__type_traits/is_arithmetic.h>
#include <__type_traits/is_trivially_copy_assignable.h>
#include <__type_traits/is_trivially_copy_constructible.h>
#include <__utility/move.h>
#include <__utility/pair.h>
#include <bit>
#include <climits>
#include <cstdint>
@ -132,7 +128,8 @@ template <class _AlgPolicy, class _Compare, class _ForwardIterator>
_LIBCPP_HIDE_FROM_ABI
unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4,
_Compare __c) {
using _Ops = _IterOps<_AlgPolicy>;
using _Ops = _IterOps<_AlgPolicy>;
unsigned __r = std::__sort3<_AlgPolicy, _Compare>(__x1, __x2, __x3, __c);
if (__c(*__x4, *__x3)) {
_Ops::iter_swap(__x3, __x4);
@ -187,7 +184,7 @@ _LIBCPP_HIDE_FROM_ABI unsigned __sort5_wrap_policy(
_Compare __c) {
using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type;
_WrappedComp __wrapped_comp(__c);
return std::__sort5<_WrappedComp, _ForwardIterator>(
return std::__sort5<_WrappedComp>(
std::move(__x1), std::move(__x2), std::move(__x3), std::move(__x4), std::move(__x5), __wrapped_comp);
}
@ -212,13 +209,6 @@ using __use_branchless_sort =
integral_constant<bool, __is_cpp17_contiguous_iterator<_Iter>::value && sizeof(_Tp) <= sizeof(void*) &&
is_arithmetic<_Tp>::value && __is_simple_comparator<_Compare>::value>;
namespace __detail {
// Size in bits for the bitset in use.
enum { __block_size = sizeof(uint64_t) * 8 };
} // namespace __detail
// Ensures that __c(*__x, *__y) is true by swapping *__x and *__y if necessary.
template <class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _Compare __c) {
@ -278,15 +268,10 @@ __sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2,
std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c);
}
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
template <class, class _Compare, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void>
__sort5_maybe_branchless(
_RandomAccessIterator __x1,
_RandomAccessIterator __x2,
_RandomAccessIterator __x3,
_RandomAccessIterator __x4,
_RandomAccessIterator __x5,
_Compare __c) {
__sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3,
_RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) {
std::__cond_swap<_Compare>(__x1, __x2, __c);
std::__cond_swap<_Compare>(__x4, __x5, __c);
std::__partially_sorted_swap<_Compare>(__x3, __x4, __x5, __c);
@ -315,48 +300,34 @@ _LIBCPP_CONSTEXPR_SINCE_CXX14 void __selection_sort(_BidirectionalIterator __fir
}
}
// Sort the iterator range [__first, __last) using the comparator __comp using
// the insertion sort algorithm.
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
_LIBCPP_HIDE_FROM_ABI
void __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
if (__first == __last)
return;
_BidirectionalIterator __i = __first;
for (++__i; __i != __last; ++__i) {
_BidirectionalIterator __j = __i;
--__j;
if (__comp(*__i, *__j)) {
value_type __t(_Ops::__iter_move(__i));
_BidirectionalIterator __k = __j;
__j = __i;
do {
if (__first != __last) {
_BidirectionalIterator __i = __first;
for (++__i; __i != __last; ++__i) {
_BidirectionalIterator __j = __i;
value_type __t(_Ops::__iter_move(__j));
for (_BidirectionalIterator __k = __i; __k != __first && __comp(__t, *--__k); --__j)
*__j = _Ops::__iter_move(__k);
__j = __k;
} while (__j != __first && __comp(__t, *--__k));
*__j = std::move(__t);
}
}
}
// Sort the iterator range [__first, __last) using the comparator __comp using
// the insertion sort algorithm. Insertion sort has two loops, outer and inner.
// The implementation below has not bounds check (unguarded) for the inner loop.
// Assumes that there is an element in the position (__first - 1) and that each
// element in the input range is greater or equal to the element at __first - 1.
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
_LIBCPP_HIDE_FROM_ABI void
__insertion_sort_unguarded(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
_LIBCPP_HIDE_FROM_ABI
void __insertion_sort_3(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
if (__first == __last)
return;
for (_RandomAccessIterator __i = __first + difference_type(1); __i != __last; ++__i) {
_RandomAccessIterator __j = __i - difference_type(1);
_RandomAccessIterator __j = __first + difference_type(2);
std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), __j, __comp);
for (_RandomAccessIterator __i = __j + difference_type(1); __i != __last; ++__i) {
if (__comp(*__i, *__j)) {
value_type __t(_Ops::__iter_move(__i));
_RandomAccessIterator __k = __j;
@ -364,9 +335,10 @@ __insertion_sort_unguarded(_RandomAccessIterator __first, _RandomAccessIterator
do {
*__j = _Ops::__iter_move(__k);
__j = __k;
} while (__comp(__t, *--__k)); // No need for bounds check due to the assumption stated above.
} while (__j != __first && __comp(__t, *--__k));
*__j = std::move(__t);
}
__j = __i;
}
}
@ -387,7 +359,7 @@ _LIBCPP_HIDDEN bool __insertion_sort_incomplete(
return true;
case 2:
if (__comp(*--__last, *__first))
_Ops::iter_swap(__first, __last);
_IterOps<_AlgPolicy>::iter_swap(__first, __last);
return true;
case 3:
std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp);
@ -456,336 +428,17 @@ void __insertion_sort_move(_BidirectionalIterator __first1, _BidirectionalIterat
}
}
template <class _AlgPolicy, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos(
_RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t& __left_bitset, uint64_t& __right_bitset) {
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
void __introsort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __depth) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
// Swap one pair on each iteration as long as both bitsets have at least one
// element for swapping.
while (__left_bitset != 0 && __right_bitset != 0) {
difference_type tz_left = __libcpp_ctz(__left_bitset);
__left_bitset = __libcpp_blsr(__left_bitset);
difference_type tz_right = __libcpp_ctz(__right_bitset);
__right_bitset = __libcpp_blsr(__right_bitset);
_Ops::iter_swap(__first + tz_left, __last - tz_right);
}
}
template <class _Compare,
class _RandomAccessIterator,
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
inline _LIBCPP_HIDE_FROM_ABI void
__populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueType& __pivot, uint64_t& __left_bitset) {
// Possible vectorization. With a proper "-march" flag, the following loop
// will be compiled into a set of SIMD instructions.
_RandomAccessIterator __iter = __first;
for (int __j = 0; __j < __detail::__block_size;) {
bool __comp_result = !__comp(*__iter, __pivot);
__left_bitset |= (static_cast<uint64_t>(__comp_result) << __j);
__j++;
++__iter;
}
}
template <class _Compare,
class _RandomAccessIterator,
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
inline _LIBCPP_HIDE_FROM_ABI void
__populate_right_bitset(_RandomAccessIterator __lm1, _Compare __comp, _ValueType& __pivot, uint64_t& __right_bitset) {
// Possible vectorization. With a proper "-march" flag, the following loop
// will be compiled into a set of SIMD instructions.
_RandomAccessIterator __iter = __lm1;
for (int __j = 0; __j < __detail::__block_size;) {
bool __comp_result = __comp(*__iter, __pivot);
__right_bitset |= (static_cast<uint64_t>(__comp_result) << __j);
__j++;
--__iter;
}
}
template <class _AlgPolicy,
class _Compare,
class _RandomAccessIterator,
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks(
_RandomAccessIterator& __first,
_RandomAccessIterator& __lm1,
_Compare __comp,
_ValueType& __pivot,
uint64_t& __left_bitset,
uint64_t& __right_bitset) {
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
difference_type __remaining_len = __lm1 - __first + 1;
difference_type __l_size;
difference_type __r_size;
if (__left_bitset == 0 && __right_bitset == 0) {
__l_size = __remaining_len / 2;
__r_size = __remaining_len - __l_size;
} else if (__left_bitset == 0) {
// We know at least one side is a full block.
__l_size = __remaining_len - __detail::__block_size;
__r_size = __detail::__block_size;
} else { // if (__right_bitset == 0)
__l_size = __detail::__block_size;
__r_size = __remaining_len - __detail::__block_size;
}
// Record the comparison outcomes for the elements currently on the left side.
if (__left_bitset == 0) {
_RandomAccessIterator __iter = __first;
for (int j = 0; j < __l_size; j++) {
bool __comp_result = !__comp(*__iter, __pivot);
__left_bitset |= (static_cast<uint64_t>(__comp_result) << j);
++__iter;
}
}
// Record the comparison outcomes for the elements currently on the right
// side.
if (__right_bitset == 0) {
_RandomAccessIterator __iter = __lm1;
for (int j = 0; j < __r_size; j++) {
bool __comp_result = __comp(*__iter, __pivot);
__right_bitset |= (static_cast<uint64_t>(__comp_result) << j);
--__iter;
}
}
std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset);
__first += (__left_bitset == 0) ? __l_size : 0;
__lm1 -= (__right_bitset == 0) ? __r_size : 0;
}
template <class _AlgPolicy, class _RandomAccessIterator>
inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within(
_RandomAccessIterator& __first, _RandomAccessIterator& __lm1, uint64_t& __left_bitset, uint64_t& __right_bitset) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
if (__left_bitset) {
// Swap within the left side. Need to find set positions in the reverse
// order.
while (__left_bitset != 0) {
difference_type __tz_left = __detail::__block_size - 1 - __libcpp_clz(__left_bitset);
__left_bitset &= (static_cast<uint64_t>(1) << __tz_left) - 1;
_RandomAccessIterator it = __first + __tz_left;
if (it != __lm1) {
_Ops::iter_swap(it, __lm1);
}
--__lm1;
}
__first = __lm1 + difference_type(1);
} else if (__right_bitset) {
// Swap within the right side. Need to find set positions in the reverse
// order.
while (__right_bitset != 0) {
difference_type __tz_right = __detail::__block_size - 1 - __libcpp_clz(__right_bitset);
__right_bitset &= (static_cast<uint64_t>(1) << __tz_right) - 1;
_RandomAccessIterator it = __lm1 - __tz_right;
if (it != __first) {
_Ops::iter_swap(it, __first);
}
++__first;
}
}
}
// Partition [__first, __last) using the comparator __comp. *__first has the
// chosen pivot. Elements that are equivalent are kept to the left of the
// pivot. Returns the iterator for the pivot and a bool value which is true if
// the provided range is already sorted, false otherwise. We assume that the
// length of the range is at least three elements.
//
// __bitset_partition uses bitsets for storing outcomes of the comparisons
// between the pivot and other elements.
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool>
__bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
_LIBCPP_ASSERT(__last - __first >= difference_type(3), "");
_RandomAccessIterator __begin = __first;
value_type __pivot(_Ops::__iter_move(__first));
// Find the first element greater than the pivot.
if (__comp(__pivot, *(__last - difference_type(1)))) {
// Not guarded since we know the last element is greater than the pivot.
while (!__comp(__pivot, *++__first)) {
}
} else {
while (++__first < __last && !__comp(__pivot, *__first)) {
}
}
// Find the last element less than or equal to the pivot.
if (__first < __last) {
// It will be always guarded because __introsort will do the median-of-three
// before calling this.
while (__comp(__pivot, *--__last)) {
}
}
// If the first element greater than the pivot is at or after the
// last element less than or equal to the pivot, then we have covered the
// entire range without swapping elements. This implies the range is already
// partitioned.
bool __already_partitioned = __first >= __last;
if (!__already_partitioned) {
_Ops::iter_swap(__first, __last);
++__first;
}
// In [__first, __last) __last is not inclusive. From now on, it uses last
// minus one to be inclusive on both sides.
_RandomAccessIterator __lm1 = __last - difference_type(1);
uint64_t __left_bitset = 0;
uint64_t __right_bitset = 0;
// Reminder: length = __lm1 - __first + 1.
while (__lm1 - __first >= 2 * __detail::__block_size - 1) {
// Record the comparison outcomes for the elements currently on the left
// side.
if (__left_bitset == 0)
std::__populate_left_bitset<_Compare>(__first, __comp, __pivot, __left_bitset);
// Record the comparison outcomes for the elements currently on the right
// side.
if (__right_bitset == 0)
std::__populate_right_bitset<_Compare>(__lm1, __comp, __pivot, __right_bitset);
// Swap the elements recorded to be the candidates for swapping in the
// bitsets.
std::__swap_bitmap_pos<_AlgPolicy, _RandomAccessIterator>(__first, __lm1, __left_bitset, __right_bitset);
// Only advance the iterator if all the elements that need to be moved to
// other side were moved.
__first += (__left_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0);
__lm1 -= (__right_bitset == 0) ? difference_type(__detail::__block_size) : difference_type(0);
}
// Now, we have a less-than a block worth of elements on at least one of the
// sides.
std::__bitset_partition_partial_blocks<_AlgPolicy, _Compare>(
__first, __lm1, __comp, __pivot, __left_bitset, __right_bitset);
// At least one the bitsets would be empty. For the non-empty one, we need to
// properly partition the elements that appear within that bitset.
std::__swap_bitmap_pos_within<_AlgPolicy>(__first, __lm1, __left_bitset, __right_bitset);
// Move the pivot to its correct position.
_RandomAccessIterator __pivot_pos = __first - difference_type(1);
if (__begin != __pivot_pos) {
*__begin = _Ops::__iter_move(__pivot_pos);
}
*__pivot_pos = std::move(__pivot);
return std::make_pair(__pivot_pos, __already_partitioned);
}
// Partition [__first, __last) using the comparator __comp. *__first has the
// chosen pivot. Elements that are equivalent are kept to the right of the
// pivot. Returns the iterator for the pivot and a bool value which is true if
// the provided range is already sorted, false otherwise. We assume that the
// length of the range is at least three elements.
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool>
__partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
_LIBCPP_ASSERT(__last - __first >= difference_type(3), "");
_RandomAccessIterator __begin = __first;
value_type __pivot(_Ops::__iter_move(__first));
// Find the first element greater or equal to the pivot. It will be always
// guarded because __introsort will do the median-of-three before calling
// this.
while (__comp(*++__first, __pivot))
;
// Find the last element less than the pivot.
if (__begin == __first - difference_type(1)) {
while (__first < __last && !__comp(*--__last, __pivot))
;
} else {
// Guarded.
while (!__comp(*--__last, __pivot))
;
}
// If the first element greater than or equal to the pivot is at or after the
// last element less than the pivot, then we have covered the entire range
// without swapping elements. This implies the range is already partitioned.
bool __already_partitioned = __first >= __last;
// Go through the remaining elements. Swap pairs of elements (one to the
// right of the pivot and the other to left of the pivot) that are not on the
// correct side of the pivot.
while (__first < __last) {
_Ops::iter_swap(__first, __last);
while (__comp(*++__first, __pivot))
;
while (!__comp(*--__last, __pivot))
;
}
// Move the pivot to its correct position.
_RandomAccessIterator __pivot_pos = __first - difference_type(1);
if (__begin != __pivot_pos) {
*__begin = _Ops::__iter_move(__pivot_pos);
}
*__pivot_pos = std::move(__pivot);
return std::make_pair(__pivot_pos, __already_partitioned);
}
// Similar to the above function. Elements equivalent to the pivot are put to
// the left of the pivot. Returns the iterator to the pivot element.
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
__partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
_RandomAccessIterator __begin = __first;
value_type __pivot(_Ops::__iter_move(__first));
if (__comp(__pivot, *(__last - difference_type(1)))) {
// Guarded.
while (!__comp(__pivot, *++__first)) {
}
} else {
while (++__first < __last && !__comp(__pivot, *__first)) {
}
}
if (__first < __last) {
// It will be always guarded because __introsort will do the
// median-of-three before calling this.
while (__comp(__pivot, *--__last)) {
}
}
while (__first < __last) {
_Ops::iter_swap(__first, __last);
while (!__comp(__pivot, *++__first))
;
while (__comp(__pivot, *--__last))
;
}
_RandomAccessIterator __pivot_pos = __first - difference_type(1);
if (__begin != __pivot_pos) {
*__begin = _Ops::__iter_move(__pivot_pos);
}
*__pivot_pos = std::move(__pivot);
return __first;
}
// The main sorting function. Implements introsort combined with other ideas:
// - option of using block quick sort for partitioning,
// - guarded and unguarded insertion sort for small lengths,
// - Tuckey's ninther technique for computing the pivot,
// - check on whether partition was not required.
// The implementation is partly based on Orson Peters' pattern-defeating
// quicksort, published at: <https://github.com/orlp/pdqsort>.
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _UseBitSetPartition>
void __introsort(_RandomAccessIterator __first,
_RandomAccessIterator __last,
_Compare __comp,
typename iterator_traits<_RandomAccessIterator>::difference_type __depth,
bool __leftmost = true) {
using _Ops = _IterOps<_AlgPolicy>;
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
using _Comp_ref = __comp_ref_type<_Compare>;
// Upper bound for using insertion sort for sorting.
_LIBCPP_CONSTEXPR difference_type __limit = 24;
// Lower bound for using Tuckey's ninther technique for median computation.
_LIBCPP_CONSTEXPR difference_type __ninther_threshold = 128;
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
const difference_type __limit =
is_trivially_copy_constructible<value_type>::value && is_trivially_copy_assignable<value_type>::value ? 30 : 6;
while (true) {
__restart:
difference_type __len = __last - __first;
switch (__len) {
case 0:
@ -793,7 +446,7 @@ void __introsort(_RandomAccessIterator __first,
return;
case 2:
if (__comp(*--__last, *__first))
_Ops::iter_swap(__first, __last);
_IterOps<_AlgPolicy>::iter_swap(__first, __last);
return;
case 3:
std::__sort3_maybe_branchless<_AlgPolicy, _Compare>(__first, __first + difference_type(1), --__last, __comp);
@ -808,60 +461,127 @@ void __introsort(_RandomAccessIterator __first,
--__last, __comp);
return;
}
// Use insertion sort if the length of the range is below the specified limit.
if (__len < __limit) {
if (__leftmost) {
std::__insertion_sort<_AlgPolicy, _Compare>(__first, __last, __comp);
} else {
std::__insertion_sort_unguarded<_AlgPolicy, _Compare>(__first, __last, __comp);
}
if (__len <= __limit) {
std::__insertion_sort_3<_AlgPolicy, _Compare>(__first, __last, __comp);
return;
}
// __len > 5
if (__depth == 0) {
// Fallback to heap sort as Introsort suggests.
std::__partial_sort<_AlgPolicy, _Compare>(__first, __last, __last, __comp);
return;
}
--__depth;
_RandomAccessIterator __m = __first;
_RandomAccessIterator __lm1 = __last;
--__lm1;
unsigned __n_swaps;
{
difference_type __half_len = __len / 2;
// Use Tuckey's ninther technique or median of 3 for pivot selection
// depending on the length of the range being sorted.
if (__len > __ninther_threshold) {
std::__sort3<_AlgPolicy, _Compare>(__first, __first + __half_len, __last - difference_type(1), __comp);
std::__sort3<_AlgPolicy, _Compare>(
__first + difference_type(1), __first + (__half_len - 1), __last - difference_type(2), __comp);
std::__sort3<_AlgPolicy, _Compare>(
__first + difference_type(2), __first + (__half_len + 1), __last - difference_type(3), __comp);
std::__sort3<_AlgPolicy, _Compare>(
__first + (__half_len - 1), __first + __half_len, __first + (__half_len + 1), __comp);
_Ops::iter_swap(__first, __first + __half_len);
difference_type __delta;
if (__len >= 1000) {
__delta = __len / 2;
__m += __delta;
__delta /= 2;
__n_swaps = std::__sort5_wrap_policy<_AlgPolicy, _Compare>(
__first, __first + __delta, __m, __m + __delta, __lm1, __comp);
} else {
std::__sort3<_AlgPolicy, _Compare>(__first + __half_len, __first, __last - difference_type(1), __comp);
__delta = __len / 2;
__m += __delta;
__n_swaps = std::__sort3<_AlgPolicy, _Compare>(__first, __m, __lm1, __comp);
}
}
// The elements to the left of the current iterator range are already
// sorted. If the current iterator range to be sorted is not the
// leftmost part of the entire iterator range and the pivot is same as
// the highest element in the range to the left, then we know that all
// the elements in the range [first, pivot] would be equal to the pivot,
// assuming the equal elements are put on the left side when
// partitioned. This also means that we do not need to sort the left
// side of the partition.
if (!__leftmost && !__comp(*(__first - difference_type(1)), *__first)) {
__first = std::__partition_with_equals_on_left<_AlgPolicy, _RandomAccessIterator, _Comp_ref>(
__first, __last, _Comp_ref(__comp));
continue;
// *__m is median
// partition [__first, __m) < *__m and *__m <= [__m, __last)
// (this inhibits tossing elements equivalent to __m around unnecessarily)
_RandomAccessIterator __i = __first;
_RandomAccessIterator __j = __lm1;
// j points beyond range to be tested, *__m is known to be <= *__lm1
// The search going up is known to be guarded but the search coming down isn't.
// Prime the downward search with a guard.
if (!__comp(*__i, *__m)) // if *__first == *__m
{
// *__first == *__m, *__first doesn't go in first part
// manually guard downward moving __j against __i
while (true) {
if (__i == --__j) {
// *__first == *__m, *__m <= all other elements
// Parition instead into [__first, __i) == *__first and *__first < [__i, __last)
++__i; // __first + 1
__j = __last;
if (!__comp(*__first, *--__j)) // we need a guard if *__first == *(__last-1)
{
while (true) {
if (__i == __j)
return; // [__first, __last) all equivalent elements
if (__comp(*__first, *__i)) {
_Ops::iter_swap(__i, __j);
++__n_swaps;
++__i;
break;
}
++__i;
}
}
// [__first, __i) == *__first and *__first < [__j, __last) and __j == __last - 1
if (__i == __j)
return;
while (true) {
while (!__comp(*__first, *__i))
++__i;
while (__comp(*__first, *--__j))
;
if (__i >= __j)
break;
_Ops::iter_swap(__i, __j);
++__n_swaps;
++__i;
}
// [__first, __i) == *__first and *__first < [__i, __last)
// The first part is sorted, sort the second part
// std::__sort<_Compare>(__i, __last, __comp);
__first = __i;
goto __restart;
}
if (__comp(*__j, *__m)) {
_Ops::iter_swap(__i, __j);
++__n_swaps;
break; // found guard for downward moving __j, now use unguarded partition
}
}
}
// It is known that *__i < *__m
++__i;
// j points beyond range to be tested, *__m is known to be <= *__lm1
// if not yet partitioned...
if (__i < __j) {
// known that *(__i - 1) < *__m
// known that __i <= __m
while (true) {
// __m still guards upward moving __i
while (__comp(*__i, *__m))
++__i;
// It is now known that a guard exists for downward moving __j
while (!__comp(*--__j, *__m))
;
if (__i > __j)
break;
_Ops::iter_swap(__i, __j);
++__n_swaps;
// It is known that __m != __j
// If __m just moved, follow it
if (__m == __i)
__m = __j;
++__i;
}
}
// [__first, __i) < *__m and *__m <= [__i, __last)
if (__i != __m && __comp(*__m, *__i)) {
_Ops::iter_swap(__i, __m);
++__n_swaps;
}
// Use bitset partition only if asked for.
auto __ret =
_UseBitSetPartition
? std::__bitset_partition<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp)
: std::__partition_with_equals_on_right<_AlgPolicy, _RandomAccessIterator, _Compare>(__first, __last, __comp);
_RandomAccessIterator __i = __ret.first;
// [__first, __i) < *__i and *__i <= [__i+1, __last)
// If we were given a perfect partition, see if insertion sort is quick...
if (__ret.second) {
if (__n_swaps == 0) {
using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type;
_WrappedComp __wrapped_comp(__comp);
bool __fs = std::__insertion_sort_incomplete<_WrappedComp>(__first, __i, __wrapped_comp);
@ -877,11 +597,14 @@ void __introsort(_RandomAccessIterator __first,
}
}
}
// Sort the left partiton recursively and the right partition with tail recursion elimination.
std::__introsort<_AlgPolicy, _Compare, _RandomAccessIterator, _UseBitSetPartition>(
__first, __i, __comp, __depth, __leftmost);
__leftmost = false;
__first = ++__i;
// sort smaller range with recursive call and larger with tail recursion elimination
if (__i - __first < __last - __i) {
std::__introsort<_AlgPolicy, _Compare>(__first, __i, __comp, __depth);
__first = ++__i;
} else {
std::__introsort<_AlgPolicy, _Compare>(__i + difference_type(1), __last, __comp, __depth);
__last = __i;
}
}
}
@ -913,14 +636,7 @@ _LIBCPP_HIDDEN void __sort(_RandomAccessIterator __first, _RandomAccessIterator
using _AlgPolicy = typename _Unwrap::_AlgPolicy;
using _Compare = typename _Unwrap::_Comp;
_Compare __comp = _Unwrap::__get_comp(__wrapped_comp);
// Only use bitset partitioning for arithmetic types. We should also check
// that the default comparator is in use so that we are sure that there are no
// branches in the comparator.
std::__introsort<_AlgPolicy,
_Compare,
_RandomAccessIterator,
__use_branchless_sort<_Compare, _RandomAccessIterator>::value>(
__first, __last, __comp, __depth_limit);
std::__introsort<_AlgPolicy, _Compare>(__first, __last, __comp, __depth_limit);
}
template <class _Compare, class _Tp>

View File

@ -23,6 +23,7 @@
#endif
#if defined(__apple_build_version__)
// Given AppleClang XX.Y.Z, _LIBCPP_APPLE_CLANG_VER is XXYZ (e.g. AppleClang 14.0.3 => 1403)
# define _LIBCPP_COMPILER_CLANG_BASED
# define _LIBCPP_APPLE_CLANG_VER (__apple_build_version__ / 10000)
#elif defined(__clang__)
@ -37,7 +38,7 @@
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 16.0.1 == 16.00.01), _LIBCPP_VERSION is
// defined to XXYYZZ.
# define _LIBCPP_VERSION 160000
# define _LIBCPP_VERSION 160001
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
@ -134,6 +135,15 @@
# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
// According to the Standard, `bitset::operator[] const` returns bool
# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
// Fix the implementation of CityHash used for std::hash<fundamental-type>.
// This is an ABI break because `std::hash` will return a different result,
// which means that hashing the same object in translation units built against
// different versions of libc++ can return inconsistent results. This is especially
// tricky since std::hash is used in the implementation of unordered containers.
//
// The incorrect implementation of CityHash has the problem that it drops some
// bits on the floor.
# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION
// Remove the base 10 implementation of std::to_chars from the dylib.
// The implementation moved to the header, but we still export the symbols from
// the dylib for backwards compatibility.
@ -629,7 +639,11 @@ typedef __char32_t char32_t;
# else
# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
# endif
# define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
# define _LIBCPP_HIDE_FROM_ABI_VIRTUAL _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
// This macro provides a HIDE_FROM_ABI equivalent that can be applied to extern
// "C" function, as those lack mangling.
# define _LIBCPP_HIDE_FROM_ABI_C _LIBCPP_HIDDEN _LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION
# ifdef _LIBCPP_BUILDING_LIBRARY
# if _LIBCPP_ABI_VERSION > 1
@ -891,7 +905,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
// Try to find out if RTTI is disabled.
# if !defined(__cpp_rtti) || __cpp_rtti < 199711L
# define _LIBCPP_NO_RTTI
# define _LIBCPP_HAS_NO_RTTI
# endif
# ifndef _LIBCPP_WEAK
@ -1223,12 +1237,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
// functions are declared by the C library.
# define _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8
// GNU libc 2.36 and newer declare c8rtomb() and mbrtoc8() in C++ modes if
// __cpp_char8_t is defined or if C2X extensions are enabled. Unfortunately,
// determining the latter depends on internal GNU libc details. If the
// __cpp_char8_t feature test macro is not defined, then a char8_t typedef
// will be declared as well.
# if defined(_LIBCPP_GLIBC_PREREQ) && defined(__GLIBC_USE)
# if _LIBCPP_GLIBC_PREREQ(2, 36) && (defined(__cpp_char8_t) || __GLIBC_USE(ISOC2X))
// __cpp_char8_t is defined or if C2X extensions are enabled. Determining
// the latter depends on internal GNU libc details that are not appropriate
// to depend on here, so any declarations present when __cpp_char8_t is not
// defined are ignored.
# if defined(_LIBCPP_GLIBC_PREREQ)
# if _LIBCPP_GLIBC_PREREQ(2, 36) && defined(__cpp_char8_t)
# undef _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8
# endif
# endif
@ -1246,6 +1260,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "")
#endif
// TODO(varconst): currently, there are bugs in Clang's intrinsics when handling Objective-C++ `id`, so don't use
// compiler intrinsics in the Objective-C++ mode.
# ifdef __OBJC__
# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS
# endif
#endif // __cplusplus
#endif // _LIBCPP___CONFIG

View File

@ -292,7 +292,8 @@ class expected {
"be reverted to the previous state in case an exception is thrown during the assignment.");
_T2 __tmp(std::move(__oldval));
std::destroy_at(std::addressof(__oldval));
__exception_guard __trans([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); });
auto __trans =
std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); });
std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
__trans.__complete();
}
@ -451,7 +452,7 @@ class expected {
if constexpr (is_nothrow_move_constructible_v<_Err>) {
_Err __tmp(std::move(__with_err.__union_.__unex_));
std::destroy_at(std::addressof(__with_err.__union_.__unex_));
__exception_guard __trans([&] {
auto __trans = std::__make_exception_guard([&] {
std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp));
});
std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_));
@ -464,7 +465,7 @@ class expected {
"that it can be reverted to the previous state in case an exception is thrown during swap.");
_Tp __tmp(std::move(__with_val.__union_.__val_));
std::destroy_at(std::addressof(__with_val.__union_.__val_));
__exception_guard __trans([&] {
auto __trans = std::__make_exception_guard([&] {
std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp));
});
std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));

View File

@ -66,9 +66,8 @@ concept formattable = __formattable<_Tp, _CharT>;
// TODO FMT Add a test to validate we fail when using that concept after P2165
// has been implemented.
template <class _Tp>
concept __fmt_pair_like = __is_specialization_v<_Tp, pair> ||
// Use a requires since tuple_size_v may fail to instantiate,
(__is_specialization_v<_Tp, tuple> && requires { tuple_size_v<_Tp> == 2; });
concept __fmt_pair_like =
__is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2);
# endif //_LIBCPP_STD_VER > 20
#endif //_LIBCPP_STD_VER > 17

View File

@ -258,10 +258,12 @@ __handle_replacement_field(const _CharT* __begin, const _CharT* __end,
if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {
__arg_t __type = __ctx.arg(__r.__value);
if (__type == __arg_t::__handle)
if (__type == __arg_t::__none)
std::__throw_format_error("Argument index out of bounds");
else if (__type == __arg_t::__handle)
__ctx.__handle(__r.__value).__parse(__parse_ctx);
else
__format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
else if (__parse)
__format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
} else
_VSTD::__visit_format_arg(
[&](auto __arg) {

View File

@ -404,7 +404,6 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_
// In fixed mode the algorithm truncates trailing spaces and possibly the
// radix point. There's no good guess for the position of the radix point
// therefore scan the output after the first digit.
__result.__radix_point = _VSTD::find(__first, __result.__last, '.');
}
}
@ -665,7 +664,7 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif
if (__result.__exponent == __result.__last)
// if P > X >= -4, the conversion is with style f or F and precision P - 1 - X.
// By including the radix point it calculates P - (1 + X)
__p -= __result.__radix_point - __buffer.begin();
__p -= __result.__radix_point - __result.__integral;
else
// otherwise, the conversion is with style e or E and precision P - 1.
--__p;

View File

@ -268,10 +268,10 @@ class __base<_Rp(_ArgTypes...)>
virtual void destroy() _NOEXCEPT = 0;
virtual void destroy_deallocate() _NOEXCEPT = 0;
virtual _Rp operator()(_ArgTypes&& ...) = 0;
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
virtual const void* target(const type_info&) const _NOEXCEPT = 0;
virtual const std::type_info& target_type() const _NOEXCEPT = 0;
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
};
// __func implements __base for a given functor type.
@ -305,10 +305,10 @@ class __func<_Fp, _Alloc, _Rp(_ArgTypes...)>
virtual void destroy() _NOEXCEPT;
virtual void destroy_deallocate() _NOEXCEPT;
virtual _Rp operator()(_ArgTypes&&... __arg);
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
virtual const void* target(const type_info&) const _NOEXCEPT;
virtual const std::type_info& target_type() const _NOEXCEPT;
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
};
template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
@ -356,7 +356,7 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::operator()(_ArgTypes&& ... __arg)
return __f_(_VSTD::forward<_ArgTypes>(__arg)...);
}
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes>
const void*
@ -374,7 +374,7 @@ __func<_Fp, _Alloc, _Rp(_ArgTypes...)>::target_type() const _NOEXCEPT
return typeid(_Fp);
}
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
// __value_func creates a value-type from a __func.
@ -553,7 +553,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)>
_LIBCPP_INLINE_VISIBILITY
explicit operator bool() const _NOEXCEPT { return __f_ != nullptr; }
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
_LIBCPP_INLINE_VISIBILITY
const std::type_info& target_type() const _NOEXCEPT
{
@ -569,7 +569,7 @@ template <class _Rp, class... _ArgTypes> class __value_func<_Rp(_ArgTypes...)>
return nullptr;
return (const _Tp*)__f_->target(typeid(_Tp));
}
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
};
// Storage for a functor object, to be used with __policy to manage copy and
@ -616,7 +616,7 @@ struct __policy
{
static const _LIBCPP_CONSTEXPR __policy __policy_ = {nullptr, nullptr,
true,
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
&typeid(void)
#else
nullptr
@ -642,7 +642,7 @@ struct __policy
__choose_policy(/* is_small = */ false_type) {
static const _LIBCPP_CONSTEXPR __policy __policy_ = {
&__large_clone<_Fun>, &__large_destroy<_Fun>, false,
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
&typeid(typename _Fun::_Target)
#else
nullptr
@ -657,7 +657,7 @@ struct __policy
{
static const _LIBCPP_CONSTEXPR __policy __policy_ = {
nullptr, nullptr, false,
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
&typeid(typename _Fun::_Target)
#else
nullptr
@ -861,7 +861,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)>
return !__policy_->__is_null;
}
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
_LIBCPP_INLINE_VISIBILITY
const std::type_info& target_type() const _NOEXCEPT
{
@ -878,7 +878,7 @@ template <class _Rp, class... _ArgTypes> class __policy_func<_Rp(_ArgTypes...)>
else
return reinterpret_cast<const _Tp*>(&__buf_.__small);
}
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
};
#if defined(_LIBCPP_HAS_BLOCKS_RUNTIME)
@ -945,7 +945,7 @@ class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)>
return _VSTD::__invoke(__f_, _VSTD::forward<_ArgTypes>(__arg)...);
}
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
virtual const void* target(type_info const& __ti) const _NOEXCEPT {
if (__ti == typeid(__func::__block_type))
return &__f_;
@ -955,7 +955,7 @@ class __func<_Rp1(^)(_ArgTypes1...), _Alloc, _Rp(_ArgTypes...)>
virtual const std::type_info& target_type() const _NOEXCEPT {
return typeid(__func::__block_type);
}
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
};
#endif // _LIBCPP_HAS_EXTENSION_BLOCKS
@ -1056,12 +1056,12 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
// function invocation:
_Rp operator()(_ArgTypes...) const;
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
// function target access:
const std::type_info& target_type() const _NOEXCEPT;
template <typename _Tp> _Tp* target() _NOEXCEPT;
template <typename _Tp> const _Tp* target() const _NOEXCEPT;
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
};
#if _LIBCPP_STD_VER >= 17
@ -1156,7 +1156,7 @@ function<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __arg) const
return __f_(_VSTD::forward<_ArgTypes>(__arg)...);
}
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
template<class _Rp, class ..._ArgTypes>
const std::type_info&
@ -1181,7 +1181,7 @@ function<_Rp(_ArgTypes...)>::target() const _NOEXCEPT
return __f_.template target<_Tp>();
}
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
template <class _Rp, class... _ArgTypes>
inline _LIBCPP_INLINE_VISIBILITY

View File

@ -140,7 +140,11 @@ struct __murmur2_or_cityhash<_Size, 64>
if (__len >= 4) {
const uint32_t __a = std::__loadword<uint32_t>(__s);
const uint32_t __b = std::__loadword<uint32_t>(__s + __len - 4);
#ifdef _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION
return __hash_len_16(__len + (static_cast<_Size>(__a) << 3), __b);
#else
return __hash_len_16(__len + (__a << 3), __b);
#endif
}
if (__len > 0) {
const unsigned char __a = static_cast<unsigned char>(__s[0]);

View File

@ -83,6 +83,16 @@ _ForwardIterator __destroy(_ForwardIterator __first, _ForwardIterator __last) {
return __first;
}
template <class _BidirectionalIterator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
_BidirectionalIterator __reverse_destroy(_BidirectionalIterator __first, _BidirectionalIterator __last) {
while (__last != __first) {
--__last;
std::__destroy_at(std::addressof(*__last));
}
return __last;
}
#if _LIBCPP_STD_VER > 14
template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0>

View File

@ -219,7 +219,7 @@ class __shared_ptr_pointer
__shared_ptr_pointer(_Tp __p, _Dp __d, _Alloc __a)
: __data_(__compressed_pair<_Tp, _Dp>(__p, _VSTD::move(__d)), _VSTD::move(__a)) {}
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
const void* __get_deleter(const type_info&) const _NOEXCEPT override;
#endif
@ -228,7 +228,7 @@ class __shared_ptr_pointer
void __on_zero_shared_weak() _NOEXCEPT override;
};
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
template <class _Tp, class _Dp, class _Alloc>
const void*
@ -237,7 +237,7 @@ __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__get_deleter(const type_info& __t) cons
return __t == typeid(_Dp) ? _VSTD::addressof(__data_.first().second()) : nullptr;
}
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
template <class _Tp, class _Dp, class _Alloc>
void
@ -260,7 +260,10 @@ __shared_ptr_pointer<_Tp, _Dp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT
__a.deallocate(_PTraits::pointer_to(*this), 1);
}
struct __default_initialize_tag {};
// This tag is used to instantiate an allocator type. The various shared_ptr control blocks
// detect that the allocator has been instantiated for this type and perform alternative
// initialization/destruction based on that.
struct __for_overwrite_tag {};
template <class _Tp, class _Alloc>
struct __shared_ptr_emplace
@ -271,25 +274,20 @@ struct __shared_ptr_emplace
explicit __shared_ptr_emplace(_Alloc __a, _Args&& ...__args)
: __storage_(_VSTD::move(__a))
{
#if _LIBCPP_STD_VER > 17
using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type;
_TpAlloc __tmp(*__get_alloc());
allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...);
#if _LIBCPP_STD_VER >= 20
if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) {
static_assert(sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite");
::new ((void*)__get_elem()) _Tp;
} else {
using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type;
_TpAlloc __tmp(*__get_alloc());
allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...);
}
#else
::new ((void*)__get_elem()) _Tp(_VSTD::forward<_Args>(__args)...);
#endif
}
#if _LIBCPP_STD_VER >= 20
_LIBCPP_HIDE_FROM_ABI
explicit __shared_ptr_emplace(__default_initialize_tag, _Alloc __a)
: __storage_(std::move(__a))
{
::new ((void*)__get_elem()) _Tp;
}
#endif
_LIBCPP_HIDE_FROM_ABI
_Alloc* __get_alloc() _NOEXCEPT { return __storage_.__get_alloc(); }
@ -299,9 +297,13 @@ struct __shared_ptr_emplace
private:
void __on_zero_shared() _NOEXCEPT override {
#if _LIBCPP_STD_VER > 17
using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type;
_TpAlloc __tmp(*__get_alloc());
allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem());
if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) {
__get_elem()->~_Tp();
} else {
using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type;
_TpAlloc __tmp(*__get_alloc());
allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem());
}
#else
__get_elem()->~_Tp();
#endif
@ -367,13 +369,57 @@ class _LIBCPP_TEMPLATE_VIS allocator<__shared_ptr_dummy_rebind_allocator_type>
template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this;
template<class _Tp, class _Up>
// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.general-6
// A pointer type Y* is said to be compatible with a pointer type T*
// when either Y* is convertible to T* or Y is U[N] and T is cv U[].
#if _LIBCPP_STD_VER >= 17
template <class _Yp, class _Tp>
struct __bounded_convertible_to_unbounded : false_type {};
template <class _Up, std::size_t _Np, class _Tp>
struct __bounded_convertible_to_unbounded<_Up[_Np], _Tp>
: is_same<__remove_cv_t<_Tp>, _Up[]> {};
template <class _Yp, class _Tp>
struct __compatible_with
#if _LIBCPP_STD_VER > 14
: is_convertible<remove_extent_t<_Tp>*, remove_extent_t<_Up>*> {};
: _Or<
is_convertible<_Yp*, _Tp*>,
__bounded_convertible_to_unbounded<_Yp, _Tp>
> {};
#else
: is_convertible<_Tp*, _Up*> {};
#endif // _LIBCPP_STD_VER > 14
template <class _Yp, class _Tp>
struct __compatible_with
: is_convertible<_Yp*, _Tp*> {};
#endif // _LIBCPP_STD_VER >= 17
// Constructors that take raw pointers have a different set of "compatible" constraints
// http://eel.is/c++draft/util.sharedptr#util.smartptr.shared.const-9.1
// - If T is an array type, then either T is U[N] and Y(*)[N] is convertible to T*,
// or T is U[] and Y(*)[] is convertible to T*.
// - If T is not an array type, then Y* is convertible to T*.
#if _LIBCPP_STD_VER >= 17
template <class _Yp, class _Tp, class = void>
struct __raw_pointer_compatible_with : _And<
_Not<is_array<_Tp>>,
is_convertible<_Yp*, _Tp*>
> {};
template <class _Yp, class _Up, std::size_t _Np>
struct __raw_pointer_compatible_with<_Yp, _Up[_Np], __enable_if_t<
is_convertible<_Yp(*)[_Np], _Up(*)[_Np]>::value> >
: true_type {};
template <class _Yp, class _Up>
struct __raw_pointer_compatible_with<_Yp, _Up[], __enable_if_t<
is_convertible<_Yp(*)[], _Up(*)[]>::value> >
: true_type {};
#else
template <class _Yp, class _Tp>
struct __raw_pointer_compatible_with
: is_convertible<_Yp*, _Tp*> {};
#endif // _LIBCPP_STD_VER >= 17
template <class _Ptr, class = void>
struct __is_deletable : false_type { };
@ -395,12 +441,12 @@ static false_type __well_formed_deleter_test(...);
template <class _Dp, class _Pt>
struct __well_formed_deleter : decltype(std::__well_formed_deleter_test<_Dp, _Pt>(0)) {};
template<class _Dp, class _Tp, class _Yp>
template<class _Dp, class _Yp, class _Tp>
struct __shared_ptr_deleter_ctor_reqs
{
static const bool value = __compatible_with<_Tp, _Yp>::value &&
static const bool value = __raw_pointer_compatible_with<_Yp, _Tp>::value &&
is_move_constructible<_Dp>::value &&
__well_formed_deleter<_Dp, _Tp*>::value;
__well_formed_deleter<_Dp, _Yp*>::value;
};
#if defined(_LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI)
@ -439,7 +485,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
template<class _Yp, class = __enable_if_t<
_And<
__compatible_with<_Yp, _Tp>
__raw_pointer_compatible_with<_Yp, _Tp>
// In C++03 we get errors when trying to do SFINAE with the
// delete operator, so we always pretend that it's deletable.
// The same happens on GCC.
@ -457,7 +503,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
__enable_weak_this(__p, __p);
}
template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> >
template<class _Yp, class _Dp, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(_Yp* __p, _Dp __d)
: __ptr_(__p)
@ -484,7 +530,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
#endif // _LIBCPP_NO_EXCEPTIONS
}
template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value> >
template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr(_Yp* __p, _Dp __d, _Alloc __a)
: __ptr_(__p)
@ -646,6 +692,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
template <class _Yp, class _Dp, class = __enable_if_t<
!is_lvalue_reference<_Dp>::value &&
__compatible_with<_Yp, _Tp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value
> >
_LIBCPP_HIDE_FROM_ABI
@ -668,6 +715,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
template <class _Yp, class _Dp, class = void, class = __enable_if_t<
is_lvalue_reference<_Dp>::value &&
__compatible_with<_Yp, _Tp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value
> >
_LIBCPP_HIDE_FROM_ABI
@ -740,9 +788,10 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
}
#endif
template <class _Yp, class _Dp, class = __enable_if_t<
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value
> >
template <class _Yp, class _Dp, class = __enable_if_t<_And<
__compatible_with<_Yp, _Tp>,
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>
>::value> >
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp>& operator=(unique_ptr<_Yp, _Dp>&& __r)
{
@ -764,7 +813,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
}
template<class _Yp, class = __enable_if_t<
__compatible_with<_Yp, _Tp>::value
__raw_pointer_compatible_with<_Yp, _Tp>::value
> >
_LIBCPP_HIDE_FROM_ABI
void reset(_Yp* __p)
@ -773,8 +822,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
}
template<class _Yp, class _Dp, class = __enable_if_t<
__compatible_with<_Yp, _Tp>::value
> >
__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
void reset(_Yp* __p, _Dp __d)
{
@ -782,8 +830,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
}
template<class _Yp, class _Dp, class _Alloc, class = __enable_if_t<
__compatible_with<_Yp, _Tp>::value
> >
__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, _Tp>::value> >
_LIBCPP_HIDE_FROM_ABI
void reset(_Yp* __p, _Dp __d, _Alloc __a)
{
@ -858,7 +905,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
}
#endif
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
template <class _Dp>
_LIBCPP_HIDE_FROM_ABI
_Dp* __get_deleter() const _NOEXCEPT
@ -867,7 +914,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
? const_cast<void *>(__cntrl_->__get_deleter(typeid(_Dp)))
: nullptr);
}
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
template<class _Yp, class _CntrlBlk>
_LIBCPP_HIDE_FROM_ABI
@ -963,12 +1010,9 @@ template<class _Tp, class _Alloc, __enable_if_t<!is_array<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a)
{
using _ControlBlock = __shared_ptr_emplace<_Tp, _Alloc>;
using _ControlBlockAllocator = typename __allocator_traits_rebind<_Alloc, _ControlBlock>::type;
__allocation_guard<_ControlBlockAllocator> __guard(__a, 1);
::new ((void*)_VSTD::addressof(*__guard.__get())) _ControlBlock(__default_initialize_tag{}, __a);
auto __control_block = __guard.__release_ptr();
return shared_ptr<_Tp>::__create_with_control_block((*__control_block).__get_elem(), _VSTD::addressof(*__control_block));
using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>;
_ForOverwriteAllocator __alloc(__a);
return std::allocate_shared<_Tp>(__alloc);
}
template<class _Tp, __enable_if_t<!is_array<_Tp>::value, int> = 0>
@ -1000,26 +1044,25 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count
explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count, _Tp const& __arg)
: __alloc_(__alloc), __count_(__count)
{
std::__uninitialized_allocator_fill_n(__alloc_, std::begin(__data_), __count_, __arg);
std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::begin(__data_), __count_, __arg);
}
_LIBCPP_HIDE_FROM_ABI
explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count)
: __alloc_(__alloc), __count_(__count)
{
std::__uninitialized_allocator_value_construct_n(__alloc_, std::begin(__data_), __count_);
}
#if _LIBCPP_STD_VER >= 20
_LIBCPP_HIDE_FROM_ABI
explicit __unbounded_array_control_block(_Alloc const& __alloc, size_t __count, __default_initialize_tag)
: __alloc_(__alloc), __count_(__count)
{
// We are purposefully not using an allocator-aware default construction because the spec says so.
// There's currently no way of expressing default initialization in an allocator-aware manner anyway.
std::uninitialized_default_construct_n(std::begin(__data_), __count_);
}
if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) {
// We are purposefully not using an allocator-aware default construction because the spec says so.
// There's currently no way of expressing default initialization in an allocator-aware manner anyway.
std::uninitialized_default_construct_n(std::begin(__data_), __count_);
} else {
std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_);
}
#else
std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::begin(__data_), __count_);
#endif
}
// Returns the number of bytes required to store a control block followed by the given number
// of elements of _Tp, with the whole storage being aligned to a multiple of _Tp's alignment.
@ -1042,8 +1085,17 @@ struct __unbounded_array_control_block<_Tp[], _Alloc> : __shared_weak_count
private:
void __on_zero_shared() _NOEXCEPT override {
#if _LIBCPP_STD_VER >= 20
if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) {
std::__reverse_destroy(__data_, __data_ + __count_);
} else {
__allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_);
std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_);
}
#else
__allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_);
std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + __count_);
#endif
}
void __on_zero_shared_weak() _NOEXCEPT override {
@ -1096,30 +1148,40 @@ struct __bounded_array_control_block<_Tp[_Count], _Alloc>
_LIBCPP_HIDE_FROM_ABI
explicit __bounded_array_control_block(_Alloc const& __alloc, _Tp const& __arg) : __alloc_(__alloc) {
std::__uninitialized_allocator_fill_n(__alloc_, std::addressof(__data_[0]), _Count, __arg);
std::__uninitialized_allocator_fill_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count, __arg);
}
_LIBCPP_HIDE_FROM_ABI
explicit __bounded_array_control_block(_Alloc const& __alloc) : __alloc_(__alloc) {
std::__uninitialized_allocator_value_construct_n(__alloc_, std::addressof(__data_[0]), _Count);
}
#if _LIBCPP_STD_VER >= 20
_LIBCPP_HIDE_FROM_ABI
explicit __bounded_array_control_block(_Alloc const& __alloc, __default_initialize_tag) : __alloc_(__alloc) {
// We are purposefully not using an allocator-aware default construction because the spec says so.
// There's currently no way of expressing default initialization in an allocator-aware manner anyway.
std::uninitialized_default_construct_n(std::addressof(__data_[0]), _Count);
}
if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) {
// We are purposefully not using an allocator-aware default construction because the spec says so.
// There's currently no way of expressing default initialization in an allocator-aware manner anyway.
std::uninitialized_default_construct_n(std::addressof(__data_[0]), _Count);
} else {
std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count);
}
#else
std::__uninitialized_allocator_value_construct_n_multidimensional(__alloc_, std::addressof(__data_[0]), _Count);
#endif
}
_LIBCPP_HIDE_FROM_ABI_VIRTUAL
~__bounded_array_control_block() override { } // can't be `= default` because of the sometimes-non-trivial union member __data_
private:
void __on_zero_shared() _NOEXCEPT override {
#if _LIBCPP_STD_VER >= 20
if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) {
std::__reverse_destroy(__data_, __data_ + _Count);
} else {
__allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_);
std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count);
}
#else
__allocator_traits_rebind_t<_Alloc, _Tp> __value_alloc(__alloc_);
std::__allocator_destroy_multidimensional(__value_alloc, __data_, __data_ + _Count);
#endif
}
void __on_zero_shared_weak() _NOEXCEPT override {
@ -1175,7 +1237,9 @@ template<class _Tp, class _Alloc, __enable_if_t<is_bounded_array<_Tp>::value, in
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a)
{
return std::__allocate_shared_bounded_array<_Tp>(__a, __default_initialize_tag{});
using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>;
_ForOverwriteAllocator __alloc(__a);
return std::__allocate_shared_bounded_array<_Tp>(__alloc);
}
template<class _Tp, class = __enable_if_t<is_bounded_array<_Tp>::value>>
@ -1196,7 +1260,7 @@ template<class _Tp, __enable_if_t<is_bounded_array<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp> make_shared_for_overwrite()
{
return std::__allocate_shared_bounded_array<_Tp>(allocator<_Tp>(), __default_initialize_tag{});
return std::__allocate_shared_bounded_array<_Tp>(allocator<__for_overwrite_tag>());
}
// unbounded array variants
@ -1218,7 +1282,9 @@ template<class _Tp, class _Alloc, __enable_if_t<is_unbounded_array<_Tp>::value,
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp> allocate_shared_for_overwrite(const _Alloc& __a, size_t __n)
{
return std::__allocate_shared_unbounded_array<_Tp>(__a, __n, __default_initialize_tag{});
using _ForOverwriteAllocator = __allocator_traits_rebind_t<_Alloc, __for_overwrite_tag>;
_ForOverwriteAllocator __alloc(__a);
return std::__allocate_shared_unbounded_array<_Tp>(__alloc, __n);
}
template<class _Tp, class = __enable_if_t<is_unbounded_array<_Tp>::value>>
@ -1239,7 +1305,7 @@ template<class _Tp, __enable_if_t<is_unbounded_array<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
shared_ptr<_Tp> make_shared_for_overwrite(size_t __n)
{
return std::__allocate_shared_unbounded_array<_Tp>(allocator<_Tp>(), __n, __default_initialize_tag{});
return std::__allocate_shared_unbounded_array<_Tp>(allocator<__for_overwrite_tag>(), __n);
}
#endif // _LIBCPP_STD_VER > 17
@ -1465,7 +1531,7 @@ reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
typename shared_ptr<_Tp>::element_type*>(__r.get()));
}
#ifndef _LIBCPP_NO_RTTI
#ifndef _LIBCPP_HAS_NO_RTTI
template<class _Dp, class _Tp>
inline _LIBCPP_INLINE_VISIBILITY
@ -1475,7 +1541,7 @@ get_deleter(const shared_ptr<_Tp>& __p) _NOEXCEPT
return __p.template __get_deleter<_Dp>();
}
#endif // _LIBCPP_NO_RTTI
#endif // _LIBCPP_HAS_NO_RTTI
template<class _Tp>
class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr

View File

@ -410,7 +410,7 @@ constexpr void __allocator_destroy_multidimensional(_Alloc& __alloc, _BidirIter
// This function assumes that the allocator is bound to the correct type.
template<class _Alloc, class _Tp>
_LIBCPP_HIDE_FROM_ABI
constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) {
constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc) {
static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>,
"The allocator should already be rebound to the correct type");
@ -421,12 +421,12 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) {
_Tp& __array = *__loc;
// If an exception is thrown, destroy what we have constructed so far in reverse order.
__exception_guard __guard([&]() {
auto __guard = std::__make_exception_guard([&]() {
std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i);
});
for (; __i != extent_v<_Tp>; ++__i) {
std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i]));
std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]));
}
__guard.__complete();
} else {
@ -446,13 +446,13 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc) {
// This function assumes that the allocator is bound to the correct type.
template<class _Alloc, class _Tp, class _Arg>
_LIBCPP_HIDE_FROM_ABI
constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) {
constexpr void __allocator_construct_at_multidimensional(_Alloc& __alloc, _Tp* __loc, _Arg const& __arg) {
static_assert(is_same_v<typename allocator_traits<_Alloc>::value_type, _Tp>,
"The allocator should already be rebound to the correct type");
if constexpr (is_array_v<_Tp>) {
static_assert(is_array_v<_Arg>,
"Provided non-array initialization argument to __allocator_construct_at when "
"Provided non-array initialization argument to __allocator_construct_at_multidimensional when "
"trying to construct an array.");
using _Element = remove_extent_t<_Tp>;
@ -461,11 +461,11 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const&
_Tp& __array = *__loc;
// If an exception is thrown, destroy what we have constructed so far in reverse order.
__exception_guard __guard([&]() {
auto __guard = std::__make_exception_guard([&]() {
std::__allocator_destroy_multidimensional(__elem_alloc, __array, __array + __i);
});
for (; __i != extent_v<_Tp>; ++__i) {
std::__allocator_construct_at(__elem_alloc, std::addressof(__array[__i]), __arg[__i]);
std::__allocator_construct_at_multidimensional(__elem_alloc, std::addressof(__array[__i]), __arg[__i]);
}
__guard.__complete();
} else {
@ -481,33 +481,33 @@ constexpr void __allocator_construct_at(_Alloc& __alloc, _Tp* __loc, _Arg const&
// initialization using allocator_traits destruction. If the elements in the range are C-style
// arrays, they are initialized element-wise using allocator construction, and recursively so.
template<class _Alloc, class _BidirIter, class _Tp, class _Size = typename iterator_traits<_BidirIter>::difference_type>
_LIBCPP_HIDE_FROM_ABI
constexpr void __uninitialized_allocator_fill_n(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) {
_LIBCPP_HIDE_FROM_ABI constexpr void
__uninitialized_allocator_fill_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n, _Tp const& __value) {
using _ValueType = typename iterator_traits<_BidirIter>::value_type;
__allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc);
_BidirIter __begin = __it;
// If an exception is thrown, destroy what we have constructed so far in reverse order.
__exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
for (; __n != 0; --__n, ++__it) {
std::__allocator_construct_at(__value_alloc, std::addressof(*__it), __value);
std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it), __value);
}
__guard.__complete();
}
// Same as __uninitialized_allocator_fill_n, but doesn't pass any initialization argument
// Same as __uninitialized_allocator_fill_n_multidimensional, but doesn't pass any initialization argument
// to the allocator's construct method, which results in value initialization.
template<class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type>
_LIBCPP_HIDE_FROM_ABI
constexpr void __uninitialized_allocator_value_construct_n(_Alloc& __alloc, _BidirIter __it, _Size __n) {
template <class _Alloc, class _BidirIter, class _Size = typename iterator_traits<_BidirIter>::difference_type>
_LIBCPP_HIDE_FROM_ABI constexpr void
__uninitialized_allocator_value_construct_n_multidimensional(_Alloc& __alloc, _BidirIter __it, _Size __n) {
using _ValueType = typename iterator_traits<_BidirIter>::value_type;
__allocator_traits_rebind_t<_Alloc, _ValueType> __value_alloc(__alloc);
_BidirIter __begin = __it;
// If an exception is thrown, destroy what we have constructed so far in reverse order.
__exception_guard __guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
auto __guard = std::__make_exception_guard([&]() { std::__allocator_destroy_multidimensional(__value_alloc, __begin, __it); });
for (; __n != 0; --__n, ++__it) {
std::__allocator_construct_at(__value_alloc, std::addressof(*__it));
std::__allocator_construct_at_multidimensional(__value_alloc, std::addressof(*__it));
}
__guard.__complete();
}

View File

@ -98,7 +98,7 @@ class _LIBCPP_TEMPLATE_VIS polymorphic_allocator {
template <class _Type, class... _CtorArgs>
[[nodiscard]] _Type* new_object(_CtorArgs&&... __ctor_args) {
_Type* __ptr = allocate_object<_Type>();
__exception_guard __guard([&] { deallocate_object(__ptr); });
auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); });
construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...);
__guard.__complete();
return __ptr;

View File

@ -49,12 +49,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
template <class _View, size_t _Np, bool _Const>
class __elements_view_iterator;
template <class _View, size_t _Np, bool _Const>
class __elements_view_sentinel;
template <class _Tp, size_t _Np>
concept __has_tuple_element = __tuple_like<_Tp> && _Np < tuple_size<_Tp>::value;
@ -66,6 +60,13 @@ template <input_range _View, size_t _Np>
__has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> &&
__returnable_element<range_reference_t<_View>, _Np>
class elements_view : public view_interface<elements_view<_View, _Np>> {
private:
template <bool>
class __iterator;
template <bool>
class __sentinel;
public:
_LIBCPP_HIDE_FROM_ABI elements_view()
requires default_initializable<_View>
@ -130,12 +131,6 @@ class elements_view : public view_interface<elements_view<_View, _Np>> {
}
private:
template <bool _Const>
using __iterator = __elements_view_iterator<_View, _Np, _Const>;
template <bool _Const>
using __sentinel = __elements_view_sentinel<_View, _Np, _Const>;
_LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
};
@ -160,13 +155,18 @@ struct __elements_view_iterator_category_base<_Base, _Np> {
using iterator_category = decltype(__get_iterator_category());
};
template <class _View, size_t _Np, bool _Const>
class __elements_view_iterator : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> {
template <class, size_t, bool >
friend class __elements_view_iterator;
template <input_range _View, size_t _Np>
requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> &&
__has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> &&
__returnable_element<range_reference_t<_View>, _Np>
template <bool _Const>
class elements_view<_View, _Np>::__iterator
: public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> {
template <bool>
friend class __iterator;
template <class, size_t, bool >
friend class __elements_view_sentinel;
template <bool>
friend class __sentinel;
using _Base = __maybe_const<_Const, _View>;
@ -198,14 +198,13 @@ class __elements_view_iterator : public __elements_view_iterator_category_base<_
using value_type = remove_cvref_t<tuple_element_t<_Np, range_value_t<_Base>>>;
using difference_type = range_difference_t<_Base>;
_LIBCPP_HIDE_FROM_ABI __elements_view_iterator()
_LIBCPP_HIDE_FROM_ABI __iterator()
requires default_initializable<iterator_t<_Base>>
= default;
_LIBCPP_HIDE_FROM_ABI constexpr explicit __elements_view_iterator(iterator_t<_Base> __current)
: __current_(std::move(__current)) {}
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
_LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator(__elements_view_iterator<_View, _Np, !_Const> __i)
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i)
requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
: __current_(std::move(__i.__current_)) {}
@ -215,14 +214,14 @@ class __elements_view_iterator : public __elements_view_iterator_category_base<_
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return __get_element(__current_); }
_LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator++() {
_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
++__current_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; }
_LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator operator++(int)
_LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int)
requires forward_range<_Base>
{
auto temp = *this;
@ -230,14 +229,14 @@ class __elements_view_iterator : public __elements_view_iterator_category_base<_
return temp;
}
_LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator--()
_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--()
requires bidirectional_range<_Base>
{
--__current_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator operator--(int)
_LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int)
requires bidirectional_range<_Base>
{
auto temp = *this;
@ -245,14 +244,14 @@ class __elements_view_iterator : public __elements_view_iterator_category_base<_
return temp;
}
_LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator+=(difference_type __n)
_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n)
requires random_access_range<_Base>
{
__current_ += __n;
return *this;
}
_LIBCPP_HIDE_FROM_ABI constexpr __elements_view_iterator& operator-=(difference_type __n)
_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n)
requires random_access_range<_Base>
{
__current_ -= __n;
@ -265,99 +264,91 @@ class __elements_view_iterator : public __elements_view_iterator_category_base<_
return __get_element(__current_ + __n);
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const __elements_view_iterator& __x, const __elements_view_iterator& __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
requires equality_comparable<iterator_t<_Base>>
{
return __x.__current_ == __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator<(const __elements_view_iterator& __x, const __elements_view_iterator& __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ < __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator>(const __elements_view_iterator& __x, const __elements_view_iterator& __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __y < __x;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator<=(const __elements_view_iterator& __x, const __elements_view_iterator& __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return !(__y < __x);
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator>=(const __elements_view_iterator& __x, const __elements_view_iterator& __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return !(__x < __y);
}
_LIBCPP_HIDE_FROM_ABI friend constexpr auto
operator<=>(const __elements_view_iterator& __x, const __elements_view_iterator& __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>>
{
return __x.__current_ <=> __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator
operator+(const __elements_view_iterator& __x, difference_type __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __x, difference_type __y)
requires random_access_range<_Base>
{
return __elements_view_iterator{__x} += __y;
return __iterator{__x} += __y;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator
operator+(difference_type __x, const __elements_view_iterator& __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __y + __x;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr __elements_view_iterator
operator-(const __elements_view_iterator& __x, difference_type __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __x, difference_type __y)
requires random_access_range<_Base>
{
return __elements_view_iterator{__x} -= __y;
return __iterator{__x} -= __y;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
operator-(const __elements_view_iterator& __x, const __elements_view_iterator& __y)
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
{
return __x.__current_ - __y.__current_;
}
};
template <class _View, size_t _Np, bool _Const>
class __elements_view_sentinel {
template <input_range _View, size_t _Np>
requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> &&
__has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> &&
__returnable_element<range_reference_t<_View>, _Np>
template <bool _Const>
class elements_view<_View, _Np>::__sentinel {
private:
using _Base = __maybe_const<_Const, _View>;
_LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>();
template <class, size_t, bool >
friend class __elements_view_sentinel;
template <bool>
friend class __sentinel;
template <bool _AnyConst>
_LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto)
__get_current(const __elements_view_iterator<_View, _Np, _AnyConst>& __iter) {
_LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_current(const __iterator<_AnyConst>& __iter) {
return (__iter.__current_);
}
public:
_LIBCPP_HIDE_FROM_ABI __elements_view_sentinel() = default;
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
_LIBCPP_HIDE_FROM_ABI constexpr explicit __elements_view_sentinel(sentinel_t<_Base> __end)
: __end_(std::move(__end)) {}
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
_LIBCPP_HIDE_FROM_ABI constexpr __elements_view_sentinel(__elements_view_sentinel<_View, _Np, !_Const> __other)
_LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other)
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
: __end_(std::move(__other.__end_)) {}
@ -365,22 +356,21 @@ class __elements_view_sentinel {
template <bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const __elements_view_iterator<_View, _Np, _OtherConst>& __x, const __elements_view_sentinel& __y) {
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __get_current(__x) == __y.__end_;
}
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
operator-(const __elements_view_iterator<_View, _Np, _OtherConst>& __x, const __elements_view_sentinel& __y) {
operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __get_current(__x) - __y.__end_;
}
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
operator-(const __elements_view_sentinel& __x, const __elements_view_iterator<_View, _Np, _OtherConst>& __y) {
operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) {
return __x.__end_ - __get_current(__y);
}
};

View File

@ -46,15 +46,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER > 17
namespace ranges {
template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class __filter_view_iterator;
template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class __filter_view_sentinel;
template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class filter_view : public view_interface<filter_view<_View, _Pred>> {
@ -67,11 +58,8 @@ namespace ranges {
using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>;
_LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache();
using __iterator = __filter_view_iterator<_View, _Pred>;
using __sentinel = __filter_view_sentinel<_View, _Pred>;
friend __iterator;
friend __sentinel;
class __iterator;
class __sentinel;
public:
_LIBCPP_HIDE_FROM_ABI
@ -131,13 +119,11 @@ namespace ranges {
template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class __filter_view_iterator : public __filter_iterator_category<_View> {
using __filter_view = filter_view<_View, _Pred>;
class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<_View> {
public:
_LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>();
_LIBCPP_NO_UNIQUE_ADDRESS __filter_view* __parent_ = nullptr;
_LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_ = nullptr;
using iterator_concept =
_If<bidirectional_range<_View>, bidirectional_iterator_tag,
@ -149,10 +135,10 @@ namespace ranges {
using difference_type = range_difference_t<_View>;
_LIBCPP_HIDE_FROM_ABI
__filter_view_iterator() requires default_initializable<iterator_t<_View>> = default;
__iterator() requires default_initializable<iterator_t<_View>> = default;
_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator(__filter_view& __parent, iterator_t<_View> __current)
constexpr __iterator(filter_view& __parent, iterator_t<_View> __current)
: __current_(std::move(__current)), __parent_(std::addressof(__parent))
{ }
@ -171,7 +157,7 @@ namespace ranges {
}
_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator& operator++() {
constexpr __iterator& operator++() {
__current_ = ranges::find_if(std::move(++__current_), ranges::end(__parent_->__base_),
std::ref(*__parent_->__pred_));
return *this;
@ -179,42 +165,42 @@ namespace ranges {
_LIBCPP_HIDE_FROM_ABI
constexpr void operator++(int) { ++*this; }
_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator operator++(int) requires forward_range<_View> {
constexpr __iterator operator++(int) requires forward_range<_View> {
auto __tmp = *this;
++*this;
return __tmp;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator& operator--() requires bidirectional_range<_View> {
constexpr __iterator& operator--() requires bidirectional_range<_View> {
do {
--__current_;
} while (!std::invoke(*__parent_->__pred_, *__current_));
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator operator--(int) requires bidirectional_range<_View> {
constexpr __iterator operator--(int) requires bidirectional_range<_View> {
auto tmp = *this;
--*this;
return tmp;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(__filter_view_iterator const& __x, __filter_view_iterator const& __y)
friend constexpr bool operator==(__iterator const& __x, __iterator const& __y)
requires equality_comparable<iterator_t<_View>>
{
return __x.__current_ == __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr range_rvalue_reference_t<_View> iter_move(__filter_view_iterator const& __it)
friend constexpr range_rvalue_reference_t<_View> iter_move(__iterator const& __it)
noexcept(noexcept(ranges::iter_move(__it.__current_)))
{
return ranges::iter_move(__it.__current_);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr void iter_swap(__filter_view_iterator const& __x, __filter_view_iterator const& __y)
friend constexpr void iter_swap(__iterator const& __x, __iterator const& __y)
noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_)))
requires indirectly_swappable<iterator_t<_View>>
{
@ -224,17 +210,15 @@ namespace ranges {
template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class __filter_view_sentinel {
using __filter_view = filter_view<_View, _Pred>;
class filter_view<_View, _Pred>::__sentinel {
public:
sentinel_t<_View> __end_ = sentinel_t<_View>();
_LIBCPP_HIDE_FROM_ABI
__filter_view_sentinel() = default;
__sentinel() = default;
_LIBCPP_HIDE_FROM_ABI
constexpr explicit __filter_view_sentinel(__filter_view& __parent)
constexpr explicit __sentinel(filter_view& __parent)
: __end_(ranges::end(__parent.__base_))
{ }
@ -242,7 +226,7 @@ namespace ranges {
constexpr sentinel_t<_View> base() const { return __end_; }
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(__filter_view_iterator<_View, _Pred> const& __x, __filter_view_sentinel const& __y) {
operator==(__iterator const& __x, __sentinel const& __y) {
return __x.__current_ == __y.__end_;
}
};

View File

@ -83,14 +83,6 @@ namespace ranges {
{ __j - __j } -> convertible_to<_IotaDiffT<_Iter>>;
};
template <weakly_incrementable _Start>
requires copyable<_Start>
struct __iota_view_iterator;
template <weakly_incrementable _Start, semiregular _BoundSentinel>
requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start>
struct __iota_view_sentinel;
template<class>
struct __iota_iterator_category {};
@ -102,9 +94,211 @@ namespace ranges {
template <weakly_incrementable _Start, semiregular _BoundSentinel = unreachable_sentinel_t>
requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start>
class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
struct __iterator : public __iota_iterator_category<_Start> {
friend class iota_view;
using __iterator = __iota_view_iterator<_Start>;
using __sentinel = __iota_view_sentinel<_Start, _BoundSentinel>;
using iterator_concept =
_If<__advanceable<_Start>, random_access_iterator_tag,
_If<__decrementable<_Start>, bidirectional_iterator_tag,
_If<incrementable<_Start>, forward_iterator_tag,
/*Else*/ input_iterator_tag>>>;
using value_type = _Start;
using difference_type = _IotaDiffT<_Start>;
_Start __value_ = _Start();
_LIBCPP_HIDE_FROM_ABI
__iterator() requires default_initializable<_Start> = default;
_LIBCPP_HIDE_FROM_ABI
constexpr explicit __iterator(_Start __value) : __value_(std::move(__value)) {}
_LIBCPP_HIDE_FROM_ABI
constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) {
return __value_;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator& operator++() {
++__value_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr void operator++(int) { ++*this; }
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator operator++(int) requires incrementable<_Start> {
auto __tmp = *this;
++*this;
return __tmp;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator& operator--() requires __decrementable<_Start> {
--__value_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator operator--(int) requires __decrementable<_Start> {
auto __tmp = *this;
--*this;
return __tmp;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator& operator+=(difference_type __n)
requires __advanceable<_Start>
{
if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {
if (__n >= difference_type(0)) {
__value_ += static_cast<_Start>(__n);
} else {
__value_ -= static_cast<_Start>(-__n);
}
} else {
__value_ += __n;
}
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator& operator-=(difference_type __n)
requires __advanceable<_Start>
{
if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {
if (__n >= difference_type(0)) {
__value_ -= static_cast<_Start>(__n);
} else {
__value_ += static_cast<_Start>(-__n);
}
} else {
__value_ -= __n;
}
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr _Start operator[](difference_type __n) const
requires __advanceable<_Start>
{
return _Start(__value_ + __n);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
requires equality_comparable<_Start>
{
return __x.__value_ == __y.__value_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start>
{
return __x.__value_ < __y.__value_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start>
{
return __y < __x;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start>
{
return !(__y < __x);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start>
{
return !(__x < __y);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start> && three_way_comparable<_Start>
{
return __x.__value_ <=> __y.__value_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator operator+(__iterator __i, difference_type __n)
requires __advanceable<_Start>
{
__i += __n;
return __i;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator operator+(difference_type __n, __iterator __i)
requires __advanceable<_Start>
{
return __i + __n;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator operator-(__iterator __i, difference_type __n)
requires __advanceable<_Start>
{
__i -= __n;
return __i;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
requires __advanceable<_Start>
{
if constexpr (__integer_like<_Start>) {
if constexpr (__signed_integer_like<_Start>) {
return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_));
}
if (__y.__value_ > __x.__value_) {
return difference_type(-difference_type(__y.__value_ - __x.__value_));
}
return difference_type(__x.__value_ - __y.__value_);
}
return __x.__value_ - __y.__value_;
}
};
struct __sentinel {
friend class iota_view;
private:
_BoundSentinel __bound_sentinel_ = _BoundSentinel();
public:
_LIBCPP_HIDE_FROM_ABI
__sentinel() = default;
constexpr explicit __sentinel(_BoundSentinel __bound_sentinel) : __bound_sentinel_(std::move(__bound_sentinel)) {}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
return __x.__value_ == __y.__bound_sentinel_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __sentinel& __y)
requires sized_sentinel_for<_BoundSentinel, _Start>
{
return __x.__value_ - __y.__bound_sentinel_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr iter_difference_t<_Start> operator-(const __sentinel& __x, const __iterator& __y)
requires sized_sentinel_for<_BoundSentinel, _Start>
{
return -(__y - __x);
}
};
_Start __value_ = _Start();
_BoundSentinel __bound_sentinel_ = _BoundSentinel();
@ -185,224 +379,6 @@ namespace ranges {
template <class _Start, class _BoundSentinel>
inline constexpr bool enable_borrowed_range<iota_view<_Start, _BoundSentinel>> = true;
template <weakly_incrementable _Start>
requires copyable<_Start>
struct __iota_view_iterator : public __iota_iterator_category<_Start> {
template <weakly_incrementable _StartT, semiregular _BoundSentinelT>
requires __weakly_equality_comparable_with<_StartT, _BoundSentinelT> && copyable<_StartT>
friend class iota_view;
using iterator_concept =
_If<__advanceable<_Start>, random_access_iterator_tag,
_If<__decrementable<_Start>, bidirectional_iterator_tag,
_If<incrementable<_Start>, forward_iterator_tag,
/*Else*/ input_iterator_tag>>>;
using value_type = _Start;
using difference_type = _IotaDiffT<_Start>;
_Start __value_ = _Start();
_LIBCPP_HIDE_FROM_ABI
__iota_view_iterator() requires default_initializable<_Start> = default;
_LIBCPP_HIDE_FROM_ABI
constexpr explicit __iota_view_iterator(_Start __value) : __value_(std::move(__value)) {}
_LIBCPP_HIDE_FROM_ABI
constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) {
return __value_;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iota_view_iterator& operator++() {
++__value_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr void operator++(int) { ++*this; }
_LIBCPP_HIDE_FROM_ABI
constexpr __iota_view_iterator operator++(int) requires incrementable<_Start> {
auto __tmp = *this;
++*this;
return __tmp;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iota_view_iterator& operator--() requires __decrementable<_Start> {
--__value_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iota_view_iterator operator--(int) requires __decrementable<_Start> {
auto __tmp = *this;
--*this;
return __tmp;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iota_view_iterator& operator+=(difference_type __n)
requires __advanceable<_Start>
{
if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {
if (__n >= difference_type(0)) {
__value_ += static_cast<_Start>(__n);
} else {
__value_ -= static_cast<_Start>(-__n);
}
} else {
__value_ += __n;
}
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iota_view_iterator& operator-=(difference_type __n)
requires __advanceable<_Start>
{
if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) {
if (__n >= difference_type(0)) {
__value_ -= static_cast<_Start>(__n);
} else {
__value_ += static_cast<_Start>(-__n);
}
} else {
__value_ -= __n;
}
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr _Start operator[](difference_type __n) const
requires __advanceable<_Start>
{
return _Start(__value_ + __n);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iota_view_iterator& __x, const __iota_view_iterator& __y)
requires equality_comparable<_Start>
{
return __x.__value_ == __y.__value_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<(const __iota_view_iterator& __x, const __iota_view_iterator& __y)
requires totally_ordered<_Start>
{
return __x.__value_ < __y.__value_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>(const __iota_view_iterator& __x, const __iota_view_iterator& __y)
requires totally_ordered<_Start>
{
return __y < __x;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<=(const __iota_view_iterator& __x, const __iota_view_iterator& __y)
requires totally_ordered<_Start>
{
return !(__y < __x);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>=(const __iota_view_iterator& __x, const __iota_view_iterator& __y)
requires totally_ordered<_Start>
{
return !(__x < __y);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr auto operator<=>(const __iota_view_iterator& __x, const __iota_view_iterator& __y)
requires totally_ordered<_Start> && three_way_comparable<_Start>
{
return __x.__value_ <=> __y.__value_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iota_view_iterator operator+(__iota_view_iterator __i, difference_type __n)
requires __advanceable<_Start>
{
__i += __n;
return __i;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iota_view_iterator operator+(difference_type __n, __iota_view_iterator __i)
requires __advanceable<_Start>
{
return __i + __n;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iota_view_iterator operator-(__iota_view_iterator __i, difference_type __n)
requires __advanceable<_Start>
{
__i -= __n;
return __i;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr difference_type operator-(const __iota_view_iterator& __x, const __iota_view_iterator& __y)
requires __advanceable<_Start>
{
if constexpr (__integer_like<_Start>) {
if constexpr (__signed_integer_like<_Start>) {
return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_));
}
if (__y.__value_ > __x.__value_) {
return difference_type(-difference_type(__y.__value_ - __x.__value_));
}
return difference_type(__x.__value_ - __y.__value_);
}
return __x.__value_ - __y.__value_;
}
};
template <weakly_incrementable _Start, semiregular _BoundSentinel>
requires __weakly_equality_comparable_with<_Start, _BoundSentinel> && copyable<_Start>
struct __iota_view_sentinel {
template <weakly_incrementable _StartT, semiregular _BoundSentinelT>
requires __weakly_equality_comparable_with<_StartT, _BoundSentinelT> && copyable<_StartT>
friend class iota_view;
using __iterator = __iota_view_iterator<_Start>;
private:
_BoundSentinel __bound_sentinel_ = _BoundSentinel();
public:
_LIBCPP_HIDE_FROM_ABI
__iota_view_sentinel() = default;
constexpr explicit __iota_view_sentinel(_BoundSentinel __bound_sentinel) : __bound_sentinel_(std::move(__bound_sentinel)) {}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator& __x, const __iota_view_sentinel& __y) {
return __x.__value_ == __y.__bound_sentinel_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __iota_view_sentinel& __y)
requires sized_sentinel_for<_BoundSentinel, _Start>
{
return __x.__value_ - __y.__bound_sentinel_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr iter_difference_t<_Start> operator-(const __iota_view_sentinel& __x, const __iterator& __y)
requires sized_sentinel_for<_BoundSentinel, _Start>
{
return -(__y - __x);
}
};
namespace views {
namespace __iota {
struct __fn {

View File

@ -36,18 +36,10 @@ namespace ranges {
template <class _Val, class _CharT, class _Traits>
concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _Val& __t) { __is >> __t; };
template <movable _Val, class _CharT, class _Traits>
requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits>
class __basic_istream_view_iterator;
template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>>
requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits>
class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> {
using __iterator = __basic_istream_view_iterator<_Val, _CharT, _Traits>;
template <movable _ValueType, class _CharType, class _TraitsType>
requires default_initializable<_ValueType> && __stream_extractable<_ValueType, _CharType, _TraitsType>
friend class __basic_istream_view_iterator;
class __iterator;
public:
_LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream)
@ -67,23 +59,23 @@ class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT
template <movable _Val, class _CharT, class _Traits>
requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits>
class __basic_istream_view_iterator {
class basic_istream_view<_Val, _CharT, _Traits>::__iterator {
public:
using iterator_concept = input_iterator_tag;
using difference_type = ptrdiff_t;
using value_type = _Val;
_LIBCPP_HIDE_FROM_ABI constexpr explicit __basic_istream_view_iterator(
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(
basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept
: __parent_(std::addressof(__parent)) {}
__basic_istream_view_iterator(const __basic_istream_view_iterator&) = delete;
_LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator(__basic_istream_view_iterator&&) = default;
__iterator(const __iterator&) = delete;
_LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default;
__basic_istream_view_iterator& operator=(const __basic_istream_view_iterator&) = delete;
_LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator=(__basic_istream_view_iterator&&) = default;
__iterator& operator=(const __iterator&) = delete;
_LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&&) = default;
_LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator++() {
_LIBCPP_HIDE_FROM_ABI __iterator& operator++() {
*__parent_->__stream_ >> __parent_->__value_;
return *this;
}
@ -92,7 +84,7 @@ class __basic_istream_view_iterator {
_LIBCPP_HIDE_FROM_ABI _Val& operator*() const { return __parent_->__value_; }
_LIBCPP_HIDE_FROM_ABI friend bool operator==(const __basic_istream_view_iterator& __x, default_sentinel_t) {
_LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __x, default_sentinel_t) {
return !*__x.__get_parent_stream();
}

View File

@ -40,7 +40,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER > 17
// Note: `join_view` is still marked experimental because there is an ABI-breaking change that affects `join_view` in
// the pipeline (https://isocpp.org/files/papers/D2770R0.html).
// TODO: make `join_view` non-experimental once D2770 is implemented.
#if _LIBCPP_STD_VER > 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
namespace ranges {
template<class>
@ -66,14 +69,6 @@ namespace ranges {
>;
};
template <input_range _View, bool _Const>
requires view<_View> && input_range<range_reference_t<_View>>
struct __join_view_iterator;
template <input_range _View, bool _Const>
requires view<_View> && input_range<range_reference_t<_View>>
struct __join_view_sentinel;
template<input_range _View>
requires view<_View> && input_range<range_reference_t<_View>>
class join_view
@ -81,19 +76,9 @@ namespace ranges {
private:
using _InnerRange = range_reference_t<_View>;
template<bool _Const>
using __iterator = __join_view_iterator<_View, _Const>;
template<bool> struct __iterator;
template<bool _Const>
using __sentinel = __join_view_sentinel<_View, _Const>;
template <input_range _View2, bool _Const2>
requires view<_View2> && input_range<range_reference_t<_View2>>
friend struct __join_view_iterator;
template <input_range _View2, bool _Const2>
requires view<_View2> && input_range<range_reference_t<_View2>>
friend struct __join_view_sentinel;
template<bool> struct __sentinel;
template <class>
friend struct std::__segmented_iterator_traits;
@ -164,12 +149,12 @@ namespace ranges {
}
};
template<input_range _View, bool _Const>
template<input_range _View>
requires view<_View> && input_range<range_reference_t<_View>>
struct __join_view_sentinel {
template<input_range _View2, bool>
requires view<_View2> && input_range<range_reference_t<_View2>>
friend struct __join_view_sentinel;
template<bool _Const>
struct join_view<_View>::__sentinel {
template<bool>
friend struct __sentinel;
private:
using _Parent = __maybe_const<_Const, join_view<_View>>;
@ -178,37 +163,42 @@ namespace ranges {
public:
_LIBCPP_HIDE_FROM_ABI
__join_view_sentinel() = default;
__sentinel() = default;
_LIBCPP_HIDE_FROM_ABI
constexpr explicit __join_view_sentinel(_Parent& __parent)
constexpr explicit __sentinel(_Parent& __parent)
: __end_(ranges::end(__parent.__base_)) {}
_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_sentinel(__join_view_sentinel<_View, !_Const> __s)
constexpr __sentinel(__sentinel<!_Const> __s)
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
: __end_(std::move(__s.__end_)) {}
template<bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __join_view_iterator<_View, _OtherConst>& __x, const __join_view_sentinel& __y) {
friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __x.__outer_ == __y.__end_;
}
};
template<input_range _View, bool _Const>
// https://reviews.llvm.org/D142811#inline-1383022
// To simplify the segmented iterator traits specialization,
// make the iterator `final`
template<input_range _View>
requires view<_View> && input_range<range_reference_t<_View>>
struct __join_view_iterator
template<bool _Const>
struct join_view<_View>::__iterator final
: public __join_view_iterator_category<__maybe_const<_Const, _View>> {
template<input_range _View2, bool>
requires view<_View2> && input_range<range_reference_t<_View2>>
friend struct __join_view_iterator;
template<bool>
friend struct __iterator;
template <class>
friend struct std::__segmented_iterator_traits;
static constexpr bool __is_join_view_iterator = true;
private:
using _Parent = __maybe_const<_Const, join_view<_View>>;
using _Base = __maybe_const<_Const, _View>;
@ -243,7 +233,7 @@ namespace ranges {
__inner_.reset();
}
_LIBCPP_HIDE_FROM_ABI constexpr __join_view_iterator(_Parent* __parent, _Outer __outer, _Inner __inner)
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent* __parent, _Outer __outer, _Inner __inner)
: __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {}
public:
@ -264,17 +254,17 @@ namespace ranges {
range_difference_t<_Base>, range_difference_t<range_reference_t<_Base>>>;
_LIBCPP_HIDE_FROM_ABI
__join_view_iterator() requires default_initializable<_Outer> = default;
__iterator() requires default_initializable<_Outer> = default;
_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator(_Parent& __parent, _Outer __outer)
constexpr __iterator(_Parent& __parent, _Outer __outer)
: __outer_(std::move(__outer))
, __parent_(std::addressof(__parent)) {
__satisfy();
}
_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator(__join_view_iterator<_View, !_Const> __i)
constexpr __iterator(__iterator<!_Const> __i)
requires _Const &&
convertible_to<iterator_t<_View>, _Outer> &&
convertible_to<iterator_t<_InnerRange>, _Inner>
@ -295,7 +285,7 @@ namespace ranges {
}
_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator& operator++() {
constexpr __iterator& operator++() {
auto&& __inner = [&]() -> auto&& {
if constexpr (__ref_is_glvalue)
return *__outer_;
@ -315,7 +305,7 @@ namespace ranges {
}
_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator operator++(int)
constexpr __iterator operator++(int)
requires __ref_is_glvalue &&
forward_range<_Base> &&
forward_range<range_reference_t<_Base>>
@ -326,7 +316,7 @@ namespace ranges {
}
_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator& operator--()
constexpr __iterator& operator--()
requires __ref_is_glvalue &&
bidirectional_range<_Base> &&
bidirectional_range<range_reference_t<_Base>> &&
@ -345,7 +335,7 @@ namespace ranges {
}
_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator operator--(int)
constexpr __iterator operator--(int)
requires __ref_is_glvalue &&
bidirectional_range<_Base> &&
bidirectional_range<range_reference_t<_Base>> &&
@ -357,7 +347,7 @@ namespace ranges {
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __join_view_iterator& __x, const __join_view_iterator& __y)
friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
requires __ref_is_glvalue &&
equality_comparable<iterator_t<_Base>> &&
equality_comparable<iterator_t<range_reference_t<_Base>>>
@ -366,14 +356,14 @@ namespace ranges {
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr decltype(auto) iter_move(const __join_view_iterator& __i)
friend constexpr decltype(auto) iter_move(const __iterator& __i)
noexcept(noexcept(ranges::iter_move(*__i.__inner_)))
{
return ranges::iter_move(*__i.__inner_);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr void iter_swap(const __join_view_iterator& __x, const __join_view_iterator& __y)
friend constexpr void iter_swap(const __iterator& __x, const __iterator& __y)
noexcept(noexcept(ranges::iter_swap(*__x.__inner_, *__y.__inner_)))
requires indirectly_swappable<_Inner>
{
@ -401,12 +391,12 @@ inline namespace __cpo {
} // namespace views
} // namespace ranges
template <class _View, bool _Const>
requires(ranges::common_range<typename ranges::__join_view_iterator<_View, _Const>::_Parent> &&
__is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Outer>::value &&
__is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Inner>::value)
struct __segmented_iterator_traits<ranges::__join_view_iterator<_View, _Const>> {
using _JoinViewIterator = ranges::__join_view_iterator<_View, _Const>;
template <class _JoinViewIterator>
requires(_JoinViewIterator::__is_join_view_iterator &&
ranges::common_range<typename _JoinViewIterator::_Parent> &&
__is_cpp17_random_access_iterator<typename _JoinViewIterator::_Outer>::value &&
__is_cpp17_random_access_iterator<typename _JoinViewIterator::_Inner>::value)
struct __segmented_iterator_traits<_JoinViewIterator> {
using __segment_iterator =
_LIBCPP_NODEBUG __iterator_with_data<typename _JoinViewIterator::_Outer, typename _JoinViewIterator::_Parent*>;
@ -445,7 +435,7 @@ struct __segmented_iterator_traits<ranges::__join_view_iterator<_View, _Const>>
}
};
#endif // _LIBCPP_STD_VER > 17
#endif // #if _LIBCPP_STD_VER > 17 && defined(_LIBCPP_ENABLE_EXPERIMENTAL)
_LIBCPP_END_NAMESPACE_STD

View File

@ -42,12 +42,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
template <class _View, class _Pattern>
struct __split_view_iterator;
template <class _View, class _Pattern>
struct __split_view_sentinel;
template <forward_range _View, forward_range _Pattern>
requires view<_View> && view<_Pattern> &&
indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to>
@ -59,13 +53,13 @@ class split_view : public view_interface<split_view<_View, _Pattern>> {
_Cache __cached_begin_ = _Cache();
template <class, class>
friend struct __split_view_iterator;
friend struct __iterator;
template <class, class>
friend struct __split_view_sentinel;
friend struct __sentinel;
using __iterator = __split_view_iterator<_View, _Pattern>;
using __sentinel = __split_view_sentinel<_View, _Pattern>;
struct __iterator;
struct __sentinel;
_LIBCPP_HIDE_FROM_ABI constexpr subrange<iterator_t<_View>> __find_next(iterator_t<_View> __it) {
auto [__begin, __end] = ranges::search(subrange(__it, ranges::end(__base_)), __pattern_);
@ -120,16 +114,17 @@ split_view(_Range&&, _Pattern&&) -> split_view<views::all_t<_Range>, views::all_
template <forward_range _Range>
split_view(_Range&&, range_value_t<_Range>) -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>;
template <class _View, class _Pattern>
struct __split_view_iterator {
template <forward_range _View, forward_range _Pattern>
requires view<_View> && view<_Pattern> &&
indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to>
struct split_view<_View, _Pattern>::__iterator {
private:
split_view<_View, _Pattern>* __parent_ = nullptr;
split_view* __parent_ = nullptr;
_LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __cur_ = iterator_t<_View>();
_LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>();
bool __trailing_empty_ = false;
template <class, class>
friend struct __split_view_sentinel;
friend struct __sentinel;
public:
using iterator_concept = forward_iterator_tag;
@ -137,9 +132,9 @@ struct __split_view_iterator {
using value_type = subrange<iterator_t<_View>>;
using difference_type = range_difference_t<_View>;
_LIBCPP_HIDE_FROM_ABI __split_view_iterator() = default;
_LIBCPP_HIDE_FROM_ABI __iterator() = default;
_LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator(
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(
split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next)
: __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {}
@ -147,7 +142,7 @@ struct __split_view_iterator {
_LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; }
_LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator& operator++() {
_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
__cur_ = __next_.begin();
if (__cur_ != ranges::end(__parent_->__base_)) {
__cur_ = __next_.end();
@ -163,36 +158,35 @@ struct __split_view_iterator {
return *this;
}
_LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator operator++(int) {
_LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) {
auto __tmp = *this;
++*this;
return __tmp;
}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const __split_view_iterator& __x, const __split_view_iterator& __y) {
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
return __x.__cur_ == __y.__cur_ && __x.__trailing_empty_ == __y.__trailing_empty_;
}
};
template <class _View, class _Pattern>
struct __split_view_sentinel {
template <forward_range _View, forward_range _Pattern>
requires view<_View> && view<_Pattern> &&
indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to>
struct split_view<_View, _Pattern>::__sentinel {
private:
_LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>();
_LIBCPP_HIDE_FROM_ABI static constexpr bool
__equals(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) {
_LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) {
return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_;
}
public:
_LIBCPP_HIDE_FROM_ABI __split_view_sentinel() = default;
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
_LIBCPP_HIDE_FROM_ABI constexpr explicit __split_view_sentinel(split_view<_View, _Pattern>& __parent)
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent)
: __end_(ranges::end(__parent.__base_)) {}
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) {
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
return __equals(__x, __y);
}
};

View File

@ -53,17 +53,11 @@ template <class _View, class _Pred>
concept __take_while_const_is_range =
range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>>;
template <class, class, bool>
class __take_while_view_sentinel;
template <view _View, class _Pred>
requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>>
class take_while_view : public view_interface<take_while_view<_View, _Pred>> {
template <class, class, bool>
friend class __take_while_view_sentinel;
template <bool _Const>
using __sentinel = __take_while_view_sentinel<_View, _Pred, _Const>;
template <bool>
class __sentinel;
_LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
_LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_;
@ -114,37 +108,37 @@ class take_while_view : public view_interface<take_while_view<_View, _Pred>> {
template <class _Range, class _Pred>
take_while_view(_Range&&, _Pred) -> take_while_view<views::all_t<_Range>, _Pred>;
template <class _View, class _Pred, bool _Const>
class __take_while_view_sentinel {
template <view _View, class _Pred>
requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>>
template <bool _Const>
class take_while_view<_View, _Pred>::__sentinel {
using _Base = __maybe_const<_Const, _View>;
sentinel_t<_Base> __end_ = sentinel_t<_Base>();
const _Pred* __pred_ = nullptr;
template <class, class, bool>
friend class __take_while_view_sentinel;
friend class __sentinel<!_Const>;
public:
_LIBCPP_HIDE_FROM_ABI __take_while_view_sentinel() = default;
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;
_LIBCPP_HIDE_FROM_ABI constexpr explicit __take_while_view_sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
: __end_(std::move(__end)), __pred_(__pred) {}
_LIBCPP_HIDE_FROM_ABI constexpr __take_while_view_sentinel(__take_while_view_sentinel<_View, _Pred, !_Const> __s)
_LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
: __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {}
_LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; }
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const iterator_t<_Base>& __x, const __take_while_view_sentinel& __y) {
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const iterator_t<_Base>& __x, const __sentinel& __y) {
return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x);
}
template <bool _OtherConst = !_Const>
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __take_while_view_sentinel& __y) {
operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __sentinel& __y) {
return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x);
}
};

View File

@ -57,31 +57,11 @@ concept __transform_view_constraints =
regular_invocable<_Fn&, range_reference_t<_View>> &&
__can_reference<invoke_result_t<_Fn&, range_reference_t<_View>>>;
template <input_range _View, copy_constructible _Function, bool _IsConst>
requires __transform_view_constraints<_View, _Function>
class __transform_view_iterator;
template <input_range _View, copy_constructible _Function, bool _IsConst>
requires __transform_view_constraints<_View, _Function>
class __transform_view_sentinel;
template<input_range _View, copy_constructible _Fn>
requires __transform_view_constraints<_View, _Fn>
class transform_view : public view_interface<transform_view<_View, _Fn>> {
template <bool _IsConst>
using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>;
template <bool _IsConst>
using __sentinel = __transform_view_sentinel<_View, _Fn, _IsConst>;
template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_iterator;
template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_sentinel;
template<bool> class __iterator;
template<bool> class __sentinel;
_LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Fn> __func_;
_LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
@ -176,23 +156,22 @@ struct __transform_view_iterator_category_base<_View, _Fn> {
>;
};
template<input_range _View, copy_constructible _Fn, bool _Const>
template<input_range _View, copy_constructible _Fn>
requires __transform_view_constraints<_View, _Fn>
class __transform_view_iterator
template<bool _Const>
class transform_view<_View, _Fn>::__iterator
: public __transform_view_iterator_category_base<_View, _Fn> {
using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>;
using _Parent = __maybe_const<_Const, transform_view>;
using _Base = __maybe_const<_Const, _View>;
_Parent *__parent_ = nullptr;
template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_iterator;
template<bool>
friend class transform_view<_View, _Fn>::__iterator;
template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_sentinel;
template<bool>
friend class transform_view<_View, _Fn>::__sentinel;
public:
iterator_t<_Base> __current_ = iterator_t<_Base>();
@ -202,17 +181,17 @@ class __transform_view_iterator
using difference_type = range_difference_t<_Base>;
_LIBCPP_HIDE_FROM_ABI
__transform_view_iterator() requires default_initializable<iterator_t<_Base>> = default;
__iterator() requires default_initializable<iterator_t<_Base>> = default;
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator(_Parent& __parent, iterator_t<_Base> __current)
constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current)
: __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}
// Note: `__i` should always be `__transform_view_iterator<false>`, but directly using
// `__transform_view_iterator<false>` is ill-formed when `_Const` is false
// Note: `__i` should always be `__iterator<false>`, but directly using
// `__iterator<false>` is ill-formed when `_Const` is false
// (see http://wg21.link/class.copy.ctor#5).
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator(__transform_view_iterator<_View, _Fn, !_Const> __i)
constexpr __iterator(__iterator<!_Const> __i)
requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
: __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {}
@ -234,7 +213,7 @@ class __transform_view_iterator
}
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator& operator++() {
constexpr __iterator& operator++() {
++__current_;
return *this;
}
@ -243,7 +222,7 @@ class __transform_view_iterator
constexpr void operator++(int) { ++__current_; }
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator operator++(int)
constexpr __iterator operator++(int)
requires forward_range<_Base>
{
auto __tmp = *this;
@ -252,7 +231,7 @@ class __transform_view_iterator
}
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator& operator--()
constexpr __iterator& operator--()
requires bidirectional_range<_Base>
{
--__current_;
@ -260,7 +239,7 @@ class __transform_view_iterator
}
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator operator--(int)
constexpr __iterator operator--(int)
requires bidirectional_range<_Base>
{
auto __tmp = *this;
@ -269,7 +248,7 @@ class __transform_view_iterator
}
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator& operator+=(difference_type __n)
constexpr __iterator& operator+=(difference_type __n)
requires random_access_range<_Base>
{
__current_ += __n;
@ -277,7 +256,7 @@ class __transform_view_iterator
}
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator& operator-=(difference_type __n)
constexpr __iterator& operator-=(difference_type __n)
requires random_access_range<_Base>
{
__current_ -= __n;
@ -293,77 +272,77 @@ class __transform_view_iterator
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
requires equality_comparable<iterator_t<_Base>>
{
return __x.__current_ == __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ < __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ > __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<=(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ <= __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>=(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ >= __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr auto operator<=>(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>>
{
return __x.__current_ <=> __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __transform_view_iterator operator+(__transform_view_iterator __i, difference_type __n)
friend constexpr __iterator operator+(__iterator __i, difference_type __n)
requires random_access_range<_Base>
{
return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n};
return __iterator{*__i.__parent_, __i.__current_ + __n};
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __transform_view_iterator operator+(difference_type __n, __transform_view_iterator __i)
friend constexpr __iterator operator+(difference_type __n, __iterator __i)
requires random_access_range<_Base>
{
return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n};
return __iterator{*__i.__parent_, __i.__current_ + __n};
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __transform_view_iterator operator-(__transform_view_iterator __i, difference_type __n)
friend constexpr __iterator operator-(__iterator __i, difference_type __n)
requires random_access_range<_Base>
{
return __transform_view_iterator{*__i.__parent_, __i.__current_ - __n};
return __iterator{*__i.__parent_, __i.__current_ - __n};
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr difference_type operator-(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
{
return __x.__current_ - __y.__current_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr decltype(auto) iter_move(const __transform_view_iterator& __i)
friend constexpr decltype(auto) iter_move(const __iterator& __i)
noexcept(noexcept(*__i))
{
if constexpr (is_lvalue_reference_v<decltype(*__i)>)
@ -373,37 +352,33 @@ class __transform_view_iterator
}
};
template<input_range _View, copy_constructible _Fn, bool _Const>
template<input_range _View, copy_constructible _Fn>
requires __transform_view_constraints<_View, _Fn>
class __transform_view_sentinel {
using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>;
template<bool _Const>
class transform_view<_View, _Fn>::__sentinel {
using _Parent = __maybe_const<_Const, transform_view>;
using _Base = __maybe_const<_Const, _View>;
template <bool _IsConst>
using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>;
sentinel_t<_Base> __end_ = sentinel_t<_Base>();
template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_iterator;
template<bool>
friend class transform_view<_View, _Fn>::__iterator;
template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_sentinel;
template<bool>
friend class transform_view<_View, _Fn>::__sentinel;
public:
_LIBCPP_HIDE_FROM_ABI
__transform_view_sentinel() = default;
__sentinel() = default;
_LIBCPP_HIDE_FROM_ABI
constexpr explicit __transform_view_sentinel(sentinel_t<_Base> __end) : __end_(__end) {}
constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {}
// Note: `__i` should always be `__transform_view_sentinel<false>`, but directly using
// `__transform_view_sentinel<false>` is ill-formed when `_Const` is false
// Note: `__i` should always be `__sentinel<false>`, but directly using
// `__sentinel<false>` is ill-formed when `_Const` is false
// (see http://wg21.link/class.copy.ctor#5).
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_sentinel(__transform_view_sentinel<_View, _Fn, !_Const> __i)
constexpr __sentinel(__sentinel<!_Const> __i)
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
: __end_(std::move(__i.__end_)) {}
@ -413,7 +388,7 @@ class __transform_view_sentinel {
template<bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) {
friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __x.__current_ == __y.__end_;
}
@ -421,7 +396,7 @@ class __transform_view_sentinel {
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI
friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
operator-(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) {
operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __x.__current_ - __y.__end_;
}
@ -429,7 +404,7 @@ class __transform_view_sentinel {
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI
friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
operator-(const __transform_view_sentinel& __x, const __iterator<_OtherConst>& __y) {
operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) {
return __x.__end_ - __y.__current_;
}
};

Some files were not shown because too many files have changed in this diff Show More