| // RUN: %clang_cc1 -std=c++11 -verify %s -pedantic |
| // RUN: %clang_cc1 -std=c++11 -verify %s -pedantic -fexperimental-new-constant-interpreter |
| // RUN: %clang_cc1 -std=c++20 -verify %s -pedantic |
| // RUN: %clang_cc1 -std=c++20 -verify %s -pedantic -fexperimental-new-constant-interpreter |
| |
| |
| namespace PR31692 { |
| struct A { |
| struct X { int n = 0; } x; |
| // Trigger construction of X() from a SFINAE context. This must not mark |
| // any part of X as invalid. |
| static_assert(!__is_constructible(X), ""); |
| // Check that X::n is not marked invalid. |
| double &r = x.n; // expected-error {{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}} |
| }; |
| // A::X can now be default-constructed. |
| static_assert(__is_constructible(A::X), ""); |
| } |
| |
| |
| struct S { |
| } constexpr s; |
| struct C { |
| C(S); |
| }; |
| class MemInit { |
| C m = s; |
| }; |
| |
| namespace std { |
| typedef decltype(sizeof(int)) size_t; |
| |
| // libc++'s implementation |
| template <class _E> class initializer_list { |
| const _E *__begin_; |
| size_t __size_; |
| |
| initializer_list(const _E *__b, size_t __s) : __begin_(__b), __size_(__s) {} |
| |
| public: |
| typedef _E value_type; |
| typedef const _E &reference; |
| typedef const _E &const_reference; |
| typedef size_t size_type; |
| |
| typedef const _E *iterator; |
| typedef const _E *const_iterator; |
| |
| initializer_list() : __begin_(nullptr), __size_(0) {} |
| |
| size_t size() const { return __size_; } |
| const _E *begin() const { return __begin_; } |
| const _E *end() const { return __begin_ + __size_; } |
| }; |
| } // namespace std |
| |
| #if __cplusplus >= 201703L |
| |
| // Test CXXDefaultInitExpr rebuild issue in |
| // https://github.com/llvm/llvm-project/pull/87933 |
| namespace test_rebuild { |
| template <typename T, int> class C { |
| public: |
| C(std::initializer_list<T>); |
| }; |
| |
| template <typename T> using Ptr = __remove_pointer(T) *; |
| template <typename T> C(T) -> C<Ptr<T>, sizeof(T)>; |
| |
| class A { |
| public: |
| template <typename T1, typename T2> T1 *some_func(T2 &&); |
| }; |
| |
| struct B : A { |
| int *ar = some_func<int>(C{some_func<int>(0)}); |
| B() {} |
| }; |
| |
| int TestBody_got; |
| template <int> class Vector { |
| public: |
| Vector(std::initializer_list<int>); |
| }; |
| template <typename... Ts> Vector(Ts...) -> Vector<sizeof...(Ts)>; |
| class ProgramBuilder { |
| public: |
| template <typename T, typename ARGS> int *create(ARGS); |
| }; |
| |
| struct TypeTest : ProgramBuilder { |
| int *str_f16 = create<int>(Vector{0}); |
| TypeTest() {} |
| }; |
| class TypeTest_Element_Test : TypeTest { |
| void TestBody(); |
| }; |
| void TypeTest_Element_Test::TestBody() { |
| int *expect = str_f16; |
| &TestBody_got != expect; // expected-warning {{inequality comparison result unused}} |
| } |
| } // namespace test_rebuild |
| |
| // Test CXXDefaultInitExpr rebuild issue in |
| // https://github.com/llvm/llvm-project/pull/92527 |
| namespace test_rebuild2 { |
| struct F { |
| int g; |
| }; |
| struct H {}; |
| struct I { |
| I(const F &); |
| I(H); |
| }; |
| struct L { |
| I i = I({.g = 0}); |
| }; |
| struct N : L {}; |
| |
| void f() { |
| delete new L; // Ok |
| delete new N; // Ok |
| } |
| } // namespace test_rebuild2 |
| #endif // __cplusplus >= 201703L |
| |
| #if __cplusplus >= 202002L |
| // This test ensures cleanup expressions are correctly produced |
| // in the presence of default member initializers. |
| namespace PR136554 { |
| struct string { |
| constexpr string(const char*) {}; |
| constexpr ~string(); |
| }; |
| struct S; |
| struct optional { |
| template <typename U = S> |
| constexpr optional(U &&) {} |
| }; |
| struct S { |
| string a; |
| optional b; |
| int defaulted = 0; |
| } test { |
| "", { |
| { "", 0 } |
| } |
| }; |
| |
| // Ensure that the this pointer is |
| // transformed without crashing |
| consteval int immediate() { return 0;} |
| struct StructWithThisInInitializer { |
| int member() const { |
| return 0; |
| } |
| int m = member() + immediate(); |
| int m2 = this->member() + immediate(); |
| }; |
| |
| template <typename T> |
| struct StructWithThisInInitializerTPL { |
| template <typename U> |
| int member() const { |
| return 0; |
| } |
| int m = member<int>() + immediate(); |
| int m2 = this->member<int>() + immediate(); |
| }; |
| |
| void test_this() { |
| (void)StructWithThisInInitializer{}; |
| (void)StructWithThisInInitializerTPL<int>{}; |
| } |
| |
| struct ReferenceToNestedMembers { |
| int m; |
| int a = ((void)immediate(), m); // ensure g is found in the correct scope |
| int b = ((void)immediate(), this->m); // ensure g is found in the correct scope |
| }; |
| struct ReferenceToNestedMembersTest { |
| void* m = nullptr; |
| ReferenceToNestedMembers j{0}; |
| } test_reference_to_nested_members; |
| |
| } |
| |
| |
| namespace odr_in_unevaluated_context { |
| template <typename e, bool = __is_constructible(e)> struct f { |
| using type = bool; |
| }; |
| |
| template <class k, f<k>::type = false> int l; |
| int m; |
| struct p { |
| // This used to crash because m is first marked odr used |
| // during parsing, but subsequently used in an unevaluated context |
| // without being transformed. |
| int o = m; |
| p() {} |
| }; |
| |
| int i = l<p>; |
| } |
| |
| #endif |