brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 91ffa7c Raw
199 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -verify %s2 3namespace std {4  typedef decltype(sizeof(int)) size_t;5 6  template <class E> struct initializer_list {7    const E *data;8    size_t size;9 10    constexpr initializer_list(const E *data, size_t size)11        : data(data), size(size) {}12    constexpr initializer_list() : data(), size() {}13 14    constexpr const E *begin() const { return data; }15    constexpr const E *end() const { return data + size; }16  };17}18 19struct ConstexprString {20  constexpr ConstexprString() : ConstexprString("") {}21  constexpr ConstexprString(const char *p, std::size_t size) : data(new char[size+1]) {22    __builtin_memcpy(data, p, size);23    data[size] = '\0';24  }25  constexpr ConstexprString(const char *p) : ConstexprString(p, __builtin_strlen(p)) {}26  constexpr explicit ConstexprString(const char *p, const char *q) : data(nullptr) {27    auto p_size = __builtin_strlen(p);28    auto q_size = __builtin_strlen(q);29    data = new char[p_size + q_size + 1];30    __builtin_memcpy(data, p, p_size);31    __builtin_memcpy(data + p_size, q, q_size + 1);32  }33  constexpr ConstexprString(const ConstexprString &o) : ConstexprString(o.data) {}34  constexpr ConstexprString(ConstexprString &&o) : data(o.data) { o.data = nullptr; }35  constexpr ConstexprString &operator=(const ConstexprString &o) {36    return *this = ConstexprString(o);37  }38  constexpr ConstexprString &operator=(ConstexprString &&o) {39    delete[] data;40    data = o.data;41    o.data = nullptr;42    return *this;43  }44  constexpr ~ConstexprString() { delete[] data; }45  char *data;46 47  friend constexpr ConstexprString operator+(const ConstexprString &a, const ConstexprString &b) {48    return ConstexprString(a.data, b.data);49  }50  friend constexpr ConstexprString &operator+=(ConstexprString &a, const ConstexprString &b) {51    return a = a + b;52  }53  friend constexpr bool operator==(const ConstexprString &a, const ConstexprString &b) {54    return __builtin_strcmp(a.data, b.data) == 0;55  }56};57 58template<typename... T> constexpr void Format(ConstexprString &out, const char *fmt, T... args);59 60struct Arg {61  template<typename T, int (*)[__is_integral(T) ? 1 : -1] = nullptr>62  constexpr Arg(T value) {63    bool negative = false;64    if (value < 0) {65      value = -value;66      negative = true;67    }68    while (value > 0) {69      char str[2] = {char('0' + value % 10), '\0'};70      s = ConstexprString(str) + s;71      value /= 10;72    }73    if (negative)74      s = "-" + s;75  }76  template<typename T, int (*)[__is_class(T) ? 1 : -1] = nullptr>77  constexpr Arg(const T &value) {78    __builtin_dump_struct(&value, Format, s);79  }80  constexpr Arg(const char *s) : s(s) {}81  constexpr Arg(const ConstexprString *s) : s("\"" + *s + "\"") {}82  template<typename T, int (*)[__is_integral(T) ? 1 : -1] = nullptr>83  constexpr Arg(const T *p) : s("reference to " + Arg(*p).s) {}84  ConstexprString s;85};86 87template<typename... T> constexpr void Format(ConstexprString &out, const char *fmt, T... args) { // #Format88  Arg formatted_args[] = {args...};89  int i = 0;90  while (const char *percent = __builtin_strchr(fmt, '%')) {91    if (percent[1] == '%') continue;92    if (percent != fmt && percent[-1] == '*') --percent;93    out += ConstexprString(fmt, percent - fmt);94    out += formatted_args[i++].s;95 96    // Skip past format specifier until we hit a conversion specifier.97    fmt = percent;98    while (!__builtin_strchr("diouxXeEfFgGcsp", *fmt)) ++fmt;99    // Skip the conversion specifier too. TODO: Check it's the right one.100    ++fmt;101  }102  out += ConstexprString(fmt);103}104 105template<typename T> constexpr ConstexprString ToString(const T &t) { return Arg(t).s; }106 107struct A {108  int x, y, z : 3;109  int : 4;110  ConstexprString s;111};112struct B : A {113  int p, q;114  struct {115    int anon1, anon2;116  };117  union {118    int anon3;119  };120  struct {121    int m;122  } c;123  int &&r;124};125 126#if PRINT_OUTPUT127#include <stdio.h>128int main() {129  puts(ToString(B{1, 2, 3, "hello", 4, 5, 6, 7, 8, 9, 10}).data);130}131#else132static_assert(ToString(B{1, 2, 3, "hello", 4, 5, 6, 7, 8, 9, 10}) == &R"(133B {134  A {135    int x = 1136    int y = 2137    int z : 3 = 3138    ConstexprString s = "hello"139  }140  int p = 4141  int q = 5142  int anon1 = 6143  int anon2 = 7144  int anon3 = 8145  struct (unnamed) c = {146    int m = 9147  }148  int && r = reference to 10149}150)"[1]);151 152class Incomplete; // #incomplete-type153 154template <class T>155class Class {156  T value = {};157};158 159void errors(B b) {160  ConstexprString cs;161  __builtin_dump_struct(); // expected-error {{too few arguments to function call, expected 2, have 0}}162  __builtin_dump_struct(1); // expected-error {{too few arguments to function call, expected 2, have 1}}163  __builtin_dump_struct(1, 2); // expected-error {{expected pointer to struct as 1st argument to '__builtin_dump_struct', found 'int'}}164  __builtin_dump_struct(&b, 2); // expected-error {{expected a callable expression as 2nd argument to '__builtin_dump_struct', found 'int'}}165  __builtin_dump_struct(&b, Format, 0); // expected-error {{no matching function for call to 'Format'}}166                                        // expected-note@-1 {{in call to printing function with arguments '(0, "%s", "B")' while dumping struct}}167                                        // expected-note@#Format {{no known conversion from 'int' to 'ConstexprString &' for 1st argument}}168  __builtin_dump_struct((Incomplete *)nullptr, Format, cs); // expected-error {{incomplete type 'Incomplete' where a complete type is required}}169                                        // expected-note@#incomplete-type {{forward declaration of 'Incomplete'}}170  // Ensure the Class<int> gets instantiated; otherwise crash happens.171  __builtin_dump_struct((Class<int> *)nullptr, Format, cs);172}173#endif174 175// Check that PseudoObjectExprBitfields:NumSubExprs doesn't overflow. This176// would previously cause a crash.177struct t1 {178  int v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16,179      v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,180      v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46,181      v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61,182      v62, v63, v64, v65, v66, v67, v68, v69, v70, v71, v72, v73, v74, v75, v76,183      v77, v78, v79, v80, v81, v82, v83, v84, v85, v86, v87, v88, v89, v90, v91,184      v92, v93, v94, v95, v96, v97, v98, v99;185};186 187struct t2 {188  t1 v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16,189      v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,190      v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46,191      v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61,192      v62, v63, v64, v65, v66, v67, v68, v69, v70, v71, v72, v73, v74, v75, v76,193      v77, v78, v79, v80, v81, v82, v83, v84, v85, v86, v87, v88, v89, v90, v91,194      v92, v93, v94, v95, v96, v97, v98, v99;195};196 197int printf(const char *, ...);198void f1(t2 w) { __builtin_dump_struct(&w, printf); }199