Skip to content

[clang] Add tests for CWG issues regarding completeness of types #92113

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions clang/test/CXX/drs/cwg11xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@
// RUN: %clang_cc1 -std=c++17 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2a %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors

namespace cwg1110 { // cwg1110: 3.1
#if __cplusplus >= 201103L
template <typename T>
T return_T();

struct A;

template <typename>
struct B;

decltype(return_T<A>())* a;
decltype(return_T<B<int>>())* b;
#endif
} // namespace cwg1110

namespace cwg1111 { // cwg1111: 3.2
namespace example1 {
template <typename> struct set; // #cwg1111-struct-set
Expand Down
31 changes: 31 additions & 0 deletions clang/test/CXX/drs/cwg13xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,18 @@ namespace cwg1330 { // cwg1330: 4 c++11

// cwg1334: sup 1719

namespace cwg1340 { // cwg1340: 2.9
struct A;
struct B;

void f(B* a, A B::* p) {
(*a).*p;
// expected-warning@-1 {{expression result unused}}
a->*p;
// expected-warning@-1 {{expression result unused}}
}
} // namespace cwg1340

namespace cwg1341 { // cwg1341: sup P0683R1
#if __cplusplus >= 202002L
int a;
Expand Down Expand Up @@ -451,6 +463,25 @@ static_assert(!__is_nothrow_constructible(D4, int), "");
#endif
} // namespace cwg1350

namespace cwg1352 { // cwg1352: 3.0
struct A {
#if __cplusplus >= 201103L
int a = sizeof(A);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be worth it to see that this fails for a static member since the DR specifically says non-static so we should cover both.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also mentions in the body of member function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not going to fail for static member initializers because of (I suspect) subsequent changes that were made to the wording: http://eel.is/c++draft/class.mem.general#8.5

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also mentions in the body of member function

Yeah, that is worth adding. I'll prepare a PR.

#endif
void f(int b = sizeof(A));
};

template <typename T>
struct B {
#if __cplusplus >= 201103L
int a = sizeof(B) + sizeof(T);
#endif
void f(int b = sizeof(B) + sizeof(T));
};

template class B<int>;
} // namespace cwg1352

namespace cwg1358 { // cwg1358: 3.1
#if __cplusplus >= 201103L
struct Lit { constexpr operator int() const { return 0; } };
Expand Down
17 changes: 17 additions & 0 deletions clang/test/CXX/drs/cwg14xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,23 @@ struct A {
};
}

namespace cwg1458 { // cwg1458: 3.1
#if __cplusplus >= 201103L
struct A;

void f() {
constexpr A* a = nullptr;
constexpr int p = &*a;
// expected-error@-1 {{cannot initialize a variable of type 'const int' with an rvalue of type 'A *'}}
constexpr A *p2 = &*a;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the DR says it is "unspecified" so are we documenting here that this will always be the behavior? Maybe worth a comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are documenting that our constant evaluator doesn't consider this UB.

}

struct A {
int operator&();
};
#endif
} // namespace cwg1458

namespace cwg1460 { // cwg1460: 3.5
#if __cplusplus >= 201103L
namespace DRExample {
Expand Down
28 changes: 27 additions & 1 deletion clang/test/CXX/drs/cwg18xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ namespace cwg1814 { // cwg1814: yes
#endif
}

namespace cwg1815 { // cwg1815: yes
namespace cwg1815 { // cwg1815: 19
#if __cplusplus >= 201402L
struct A { int &&r = 0; };
A a = {};
Expand Down Expand Up @@ -303,6 +303,32 @@ namespace cwg1822 { // cwg1822: yes
#endif
}

namespace cwg1824 { // cwg1824: 2.7
template<typename T>
struct A {
T t;
};

struct S {
A<S> f() { return A<S>(); }
};
} // namespace cwg1824

namespace cwg1832 { // cwg1832: 3.0
enum E { // #cwg1832-E
a = static_cast<int>(static_cast<E>(0))
// expected-error@-1 {{'E' is an incomplete type}}
// expected-note@#cwg1832-E {{definition of 'cwg1832::E' is not complete until the closing '}'}}
};

#if __cplusplus >= 201103L
enum E2: decltype(static_cast<E2>(0), 0) {};
// expected-error@-1 {{unknown type name 'E2'}}
enum class E3: decltype(static_cast<E3>(0), 0) {};
// expected-error@-1 {{unknown type name 'E3'}}
#endif
} // namespace cwg1832

namespace cwg1837 { // cwg1837: 3.3
#if __cplusplus >= 201103L
template <typename T>
Expand Down
48 changes: 46 additions & 2 deletions clang/test/CXX/drs/cwg23xx.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
// RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
// RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx11-14,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx11-14,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx14,since-cxx17,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors 2>&1 | FileCheck %s
Expand Down Expand Up @@ -47,6 +47,50 @@ void g() {
} // namespace cwg2303
#endif

namespace cwg2304 { // cwg2304: 2.8
template<typename T> void foo(T, int);
template<typename T> void foo(T&, ...);
struct Q; // #cwg2304-Q
void fn1(Q &data_vectors) {
foo(data_vectors, 0);
// expected-error@-1 {{argument type 'cwg2304::Q' is incomplete}}
// expected-note@#cwg2304-Q {{forward declaration of 'cwg2304::Q'}}
}
} // namespace cwg2304

namespace cwg2310 { // cwg2310: partial
#if __cplusplus >= 201103L
template<typename A, typename B>
struct check_derived_from {
static A a;
// FIXME: all 3 examples should be rejected in all language modes.
// FIXME: we should test this in 98 mode.
// FIXME: we accept this when MSVC triple is used
static constexpr B *p = &a;
#if !defined(_WIN32) || defined(__MINGW32__)
// cxx11-14-error@-2 {{cannot initialize a variable of type 'cwg2310::X *const' with an rvalue of type 'cwg2310::Z *'}}
// cxx11-14-note@#cwg2310-X {{in instantiation of template class 'cwg2310::check_derived_from<cwg2310::Z, cwg2310::X>' requested here}}
// cxx11-14-error@-4 {{cannot initialize a variable of type 'cwg2310::Y *const' with an rvalue of type 'cwg2310::Z *'}}
// cxx11-14-note@#cwg2310-Y {{in instantiation of template class 'cwg2310::check_derived_from<cwg2310::Z, cwg2310::Y>' requested here}}
#endif
};

struct W {};
struct X {};
struct Y {};
struct Z : W,
X, check_derived_from<Z, X>, // #cwg2310-X
check_derived_from<Z, Y>, Y // #cwg2310-Y
{
// FIXME: It was properly rejected before, but we're crashing since Clang 11 in C++11 and C++14 modes.
// See https://github.com/llvm/llvm-project/issues/59920
#if __cplusplus >= 201703L
check_derived_from<Z, W> cdf;
#endif
};
#endif
} // namespace cwg2310

// cwg2331: na
// cwg2335 is in cwg2335.cxx

Expand Down
6 changes: 6 additions & 0 deletions clang/test/CXX/drs/cwg24xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ void fallthrough(int n) {
#endif
}

namespace cwg2430 { // cwg2430: 2.7
struct S {
S f(S s) { return s; }
};
} // namespace cwg2430

namespace cwg2450 { // cwg2450: 18
#if __cplusplus >= 202302L
struct S {int a;};
Expand Down
15 changes: 12 additions & 3 deletions clang/test/CXX/drs/cwg25xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx20,since-cxx23 -fexceptions -fcxx-exceptions -pedantic-errors

#if __cplusplus == 199711L
// expected-no-diagnostics
#endif
namespace std {
struct type_info{};
} // namespace std

// cwg2504 is in cwg2504.cpp

namespace cwg2512 { // cwg2512: 2.7
struct A; // #cwg2512-A
void foo(A* p) {
typeid(*p);
// expected-error@-1 {{'typeid' of incomplete type 'A'}}
// expected-note@#cwg2512-A {{forward declaration of 'cwg2512::A'}}
}
} // namespace cwg2512

namespace cwg2516 { // cwg2516: 3.0
// NB: reusing 1482 test
#if __cplusplus >= 201103L
Expand Down
23 changes: 23 additions & 0 deletions clang/test/CXX/drs/cwg2630.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: split-file --leading-lines %s %t
// RUN: %clang_cc1 -std=c++20 -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
// RUN: %clang_cc1 -std=c++20 -verify -fmodule-file=A=%t/module.pcm %t/main.cpp
// RUN: %clang_cc1 -std=c++23 -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
// RUN: %clang_cc1 -std=c++23 -verify -fmodule-file=A=%t/module.pcm %t/main.cpp
// RUN: %clang_cc1 -std=c++2c -verify -emit-module-interface %t/module.cppm -o %t/module.pcm
// RUN: %clang_cc1 -std=c++2c -verify -fmodule-file=A=%t/module.pcm %t/main.cpp

//--- module.cppm
// expected-no-diagnostics
export module A;

namespace cwg2630 {
export class X {};
} // namespace cwg2630

//--- main.cpp
// expected-no-diagnostics
import A;

namespace cwg2630 { // cwg2630: 9
X x;
} // namespace cwg2630
2 changes: 2 additions & 0 deletions clang/test/CXX/drs/cwg26xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ void f() {
#endif
}

// cwg2630 is in cwg2630.cpp

namespace cwg2631 { // cwg2631: 16
#if __cplusplus >= 202002L
constexpr int g();
Expand Down
14 changes: 11 additions & 3 deletions clang/test/CXX/drs/cwg27xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,17 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -verify=expected,since-cxx23 %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s

#if __cplusplus <= 202002L
// expected-no-diagnostics
#endif
namespace cwg2718 { // cwg2718: 2.7
struct B {};
struct D;

void f(B b) {
static_cast<D&>(b);
// expected-error@-1 {{non-const lvalue reference to type 'D' cannot bind to a value of unrelated type 'B'}}
}

struct D : B {};
} // namespace cwg2718

namespace cwg2759 { // cwg2759: 19
#if __cplusplus >= 201103L
Expand Down
28 changes: 24 additions & 4 deletions clang/test/CXX/drs/cwg28xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
// RUN: %clang_cc1 -std=c++23 -verify=expected,since-cxx20,since-cxx23 %s
// RUN: %clang_cc1 -std=c++2c -verify=expected,since-cxx20,since-cxx23,since-cxx26 %s

#if __cplusplus < 202002L
// expected-no-diagnostics
#endif

namespace cwg2819 { // cwg2819: 19 tentatively ready 2023-12-01
#if __cpp_constexpr >= 202306L
constexpr void* p = nullptr;
Expand Down Expand Up @@ -67,6 +63,30 @@ void B<int>::g() requires true;

} // namespace cwg2847

namespace cwg2857 { // cwg2857: no
struct A {};
template <typename>
struct D;
namespace N {
struct B {};
void adl_only(A*, D<int>*); // #cwg2857-adl_only
}

void f(A* a, D<int>* d) {
adl_only(a, d);
// expected-error@-1 {{use of undeclared identifier 'adl_only'; did you mean 'N::adl_only'?}}
// expected-note@#cwg2857-adl_only {{'N::adl_only' declared here}}
}

#if __cplusplus >= 201103L
template <typename>
struct D : N::B {
// FIXME: ADL shouldn't associate it's base B and N since D is not complete here
decltype(adl_only((A*) nullptr, (D*) nullptr)) f;
};
#endif
} // namespace cwg2857

namespace cwg2858 { // cwg2858: 19 tentatively ready 2024-04-05

#if __cplusplus > 202302L
Expand Down
7 changes: 7 additions & 0 deletions clang/test/CXX/drs/cwg9xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ namespace std {
};
}

namespace cwg930 { // cwg930: 2.7
#if __cplusplus >= 201103L
static_assert(alignof(int[]) == alignof(int), "");
static_assert(alignof(int[][2]) == alignof(int[2]), "");
#endif
} // namespace cwg930

namespace cwg948 { // cwg948: 3.7
#if __cplusplus >= 201103L
class A {
Expand Down
Loading
Loading