Skip to content

Commit 50c5107

Browse files
authored
[clang] Add tests for DRs about inheriting constructors (#79981)
Covers CWG issues [1150](https://cplusplus.github.io/CWG/issues/1150.html), [1487](https://cplusplus.github.io/CWG/issues/1487.html), [1567](https://cplusplus.github.io/CWG/issues/1567.html), [1738](https://cplusplus.github.io/CWG/issues/1738.html), [2273](https://cplusplus.github.io/CWG/issues/2273.html), [2277](https://cplusplus.github.io/CWG/issues/2277.html), [2356](https://cplusplus.github.io/CWG/issues/2356.html), [2504](https://cplusplus.github.io/CWG/issues/2504.html). On top of the wording in proposed resolutions, [P0136R1](https://wg21.link/p0136r1) "Rewording inheriting constructors (core issue 1941 et al)" is a very relevant paper. Note that status for 1738 `sup P0136R1` is not officially recognized by CWG, but saying `yes` or `no` seems even more confusing to me. Official resolution is to reject certain code, but Clang is the only implementation that still rejects it to this day: https://godbolt.org/z/b1W8jc1o5. GCC rejected it until 9, now it's accepted: https://godbolt.org/z/of6oh4sdT
1 parent fcb5920 commit 50c5107

File tree

9 files changed

+195
-8
lines changed

9 files changed

+195
-8
lines changed

clang/test/CXX/drs/dr11xx.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,5 @@ namespace dr1113 { // dr1113: partial
7070
}
7171
void g() { f(); }
7272
}
73+
74+
// dr1150: na

clang/test/CXX/drs/dr14xx.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,30 @@ enum E2 : S<E2>::I { e };
614614
#endif
615615
} // namespace dr1482
616616

617+
namespace dr1487 { // dr1487: 3.3
618+
#if __cplusplus >= 201103L
619+
struct A { // #dr1482-A
620+
struct B {
621+
using A::A;
622+
// since-cxx11-error@-1 {{using declaration refers into 'A::', which is not a base class of 'B'}}
623+
};
624+
625+
struct C : A {
626+
// since-cxx11-error@-1 {{base class has incomplete type}}
627+
// since-cxx11-note@#dr1482-A {{definition of 'dr1487::A' is not complete until the closing '}'}}
628+
using A::A;
629+
// since-cxx11-error@-1 {{using declaration refers into 'A::', which is not a base class of 'C'}}
630+
};
631+
632+
struct D;
633+
};
634+
635+
struct D : A {
636+
using A::A;
637+
};
638+
#endif
639+
} // namespace dr1487
640+
617641
namespace dr1490 { // dr1490: 3.7 c++11
618642
#if __cplusplus >= 201103L
619643
// List-initialization from a string literal

clang/test/CXX/drs/dr15xx.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,45 @@ namespace dr1563 { // dr1563: yes
360360
#endif
361361
}
362362

363+
namespace dr1567 { // dr1567: 3.3
364+
#if __cplusplus >= 201103L
365+
struct B;
366+
struct A {
367+
A(const A&);
368+
A(const B&) = delete;
369+
A(A&&);
370+
A(B&&) = delete;
371+
A(int); // #dr1567-A-int
372+
};
373+
374+
struct B: A { // #dr1567-B
375+
using A::A; // #dr1567-using-A
376+
B(double); // #dr1567-B-double
377+
};
378+
379+
A a{0};
380+
B b{1.0};
381+
// Good, deleted converting ctors are not inherited as copy/move ctors
382+
B b2{b};
383+
B b3{B{1.0}};
384+
// Good, copy/move ctors are not inherited
385+
B b4{a};
386+
// since-cxx11-error@-1 {{no matching constructor for initialization of 'B'}}
387+
// since-cxx11-note@#dr1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}}
388+
// since-cxx11-note@#dr1567-using-A {{constructor from base class 'A' inherited here}}
389+
// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}}
390+
// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}}
391+
// since-cxx11-note@#dr1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}}
392+
B b5{A{0}};
393+
// since-cxx11-error@-1 {{no matching constructor for initialization of 'B'}}
394+
// since-cxx11-note@#dr1567-A-int {{candidate inherited constructor not viable: no known conversion from 'A' to 'int' for 1st argument}}
395+
// since-cxx11-note@#dr1567-using-A {{constructor from base class 'A' inherited here}}
396+
// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'A' to 'const B' for 1st argument}}
397+
// since-cxx11-note@#dr1567-B {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'A' to 'B' for 1st argument}}
398+
// since-cxx11-note@#dr1567-B-double {{candidate constructor not viable: no known conversion from 'A' to 'double' for 1st argument}}
399+
#endif
400+
}
401+
363402
namespace dr1573 { // dr1573: 3.9
364403
#if __cplusplus >= 201103L
365404
// ellipsis is inherited (p0136r1 supersedes this part).

clang/test/CXX/drs/dr17xx.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,23 @@ S s(q); // #dr1736-s
8989
#endif
9090
}
9191

92+
namespace dr1738 { // dr1738: sup P0136R1
93+
#if __cplusplus >= 201103L
94+
struct A {
95+
template <typename T>
96+
A(int, T) {}
97+
};
98+
99+
struct B : A {
100+
using A::A;
101+
};
102+
103+
// FIXME: this is well-formed since P0136R1
104+
template B::B(int, double);
105+
// since-cxx11-error@-1 {{explicit instantiation of 'B' does not refer to a function template, variable template, member function, member class, or static data member}}
106+
#endif
107+
}
108+
92109
// dr1748 is in dr1748.cpp
93110

94111
namespace dr1753 { // dr1753: 11

clang/test/CXX/drs/dr22xx.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,47 @@ const D &d3(c); // FIXME ill-formed
154154
#endif
155155
}
156156

157+
namespace dr2273 { // dr2273: 3.3
158+
#if __cplusplus >= 201103L
159+
struct A {
160+
A(int = 0) = delete; // #dr2273-A
161+
};
162+
163+
struct B : A { // #dr2273-B
164+
using A::A;
165+
};
166+
167+
B b;
168+
// since-cxx11-error@-1 {{call to implicitly-deleted default constructor of 'B'}}
169+
// since-cxx11-note@#dr2273-B {{default constructor of 'B' is implicitly deleted because base class 'A' has a deleted default constructor}}
170+
// since-cxx11-note@#dr2273-A {{'A' has been explicitly marked deleted here}}
171+
#endif
172+
}
173+
174+
namespace dr2277 { // dr2277: partial
175+
#if __cplusplus >= 201103L
176+
struct A {
177+
A(int, int = 0);
178+
void f(int, int = 0); // #dr2277-A-f
179+
};
180+
struct B : A {
181+
B(int);
182+
using A::A;
183+
184+
void f(int); // #dr2277-B-f
185+
using A::f;
186+
};
187+
188+
void g() {
189+
B b{0};
190+
b.f(0); // FIXME: this is well-formed for the same reason as initialization of 'b' above
191+
// since-cxx11-error@-1 {{call to member function 'f' is ambiguous}}
192+
// since-cxx11-note@#dr2277-A-f {{candidate function}}
193+
// since-cxx11-note@#dr2277-B-f {{candidate function}}
194+
}
195+
#endif
196+
}
197+
157198
namespace dr2292 { // dr2292: 9
158199
#if __cplusplus >= 201103L
159200
template<typename T> using id = T;

clang/test/CXX/drs/dr23xx.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,31 @@ enum struct alignas(64) B {};
147147
#endif
148148
} // namespace dr2354
149149

150+
namespace dr2356 { // dr2356: 4
151+
#if __cplusplus >= 201103L
152+
struct A {
153+
A();
154+
A(A &&); // #1
155+
template<typename T> A(T &&); // #2
156+
};
157+
struct B : A {
158+
using A::A;
159+
B(const B &); // #3
160+
B(B &&) = default; // #4, implicitly deleted
161+
// since-cxx11-warning@-1 {{explicitly defaulted move constructor is implicitly deleted}}
162+
// since-cxx11-note@#dr2356-X {{move constructor of 'B' is implicitly deleted because field 'x' has a deleted move constructor}}
163+
// since-cxx11-note@#dr2356-X {{'X' has been explicitly marked deleted here}}
164+
// since-cxx11-note@-4 {{replace 'default' with 'delete'}}
165+
166+
struct X { X(X &&) = delete; } x; // #dr2356-X
167+
};
168+
extern B b1;
169+
B b2 = static_cast<B&&>(b1); // calls #3: #1, #2, and #4 are not viable
170+
struct C { operator B&&(); };
171+
B b3 = C(); // calls #3
172+
#endif
173+
}
174+
150175
#if __cplusplus >= 201402L
151176
namespace dr2358 { // dr2358: 16
152177
void f2() {

clang/test/CXX/drs/dr2504.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %clang_cc1 -std=c++98 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK
2+
// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11
3+
// RUN: %clang_cc1 -std=c++14 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11
4+
// RUN: %clang_cc1 -std=c++17 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11
5+
// RUN: %clang_cc1 -std=c++20 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11
6+
// RUN: %clang_cc1 -std=c++23 %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11
7+
// RUN: %clang_cc1 -std=c++2c %s -triple x86_64-linux-gnu -emit-llvm -o - -fexceptions -fcxx-exceptions -pedantic-errors | llvm-cxxfilt -n | FileCheck %s --check-prefixes CHECK,SINCE-CXX11
8+
9+
namespace dr2504 { // dr2504: no
10+
#if __cplusplus >= 201103L
11+
struct V { V() = default; V(int); };
12+
struct Q { Q(); };
13+
struct A : virtual V, Q {
14+
using V::V;
15+
A() = delete;
16+
};
17+
int bar() { return 42; }
18+
struct B : A {
19+
B() : A(bar()) {} // ok
20+
};
21+
struct C : B {};
22+
void foo() { C c; } // bar is not invoked, because the V subobject is not initialized as part of B
23+
#endif
24+
}
25+
26+
// FIXME: As specified in the comment above (which comes from an example in the Standard),
27+
// we are not supposed to unconditionally call `bar()` and call a constructor
28+
// inherited from `V`.
29+
30+
// SINCE-CXX11-LABEL: define linkonce_odr void @dr2504::B::B()
31+
// SINCE-CXX11-NOT: br
32+
// SINCE-CXX11: call noundef i32 @dr2504::bar()
33+
// SINCE-CXX11-NOT: br
34+
// SINCE-CXX11: call void @dr2504::A::A(int)
35+
// SINCE-CXX11-LABEL: }
36+
37+
// CHECK: {{.*}}

clang/test/CXX/drs/dr25xx.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
// expected-no-diagnostics
1111
#endif
1212

13+
// dr2504 is in dr2504.cpp
14+
1315
namespace dr2516 { // dr2516: 3.0
1416
// NB: reusing 1482 test
1517
#if __cplusplus >= 201103L

clang/www/cxx_dr_status.html

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6708,7 +6708,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
67086708
<td><a href="https://cplusplus.github.io/CWG/issues/1150.html">1150</a></td>
67096709
<td>NAD</td>
67106710
<td>Inheriting constructors have not been implemented</td>
6711-
<td class="unknown" align="center">Unknown</td>
6711+
<td class="na" align="center">N/A</td>
67126712
</tr>
67136713
<tr id="1151">
67146714
<td><a href="https://cplusplus.github.io/CWG/issues/1151.html">1151</a></td>
@@ -8730,7 +8730,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
87308730
<td><a href="https://cplusplus.github.io/CWG/issues/1487.html">1487</a></td>
87318731
<td>CD3</td>
87328732
<td>When are inheriting constructors declared?</td>
8733-
<td class="unknown" align="center">Unknown</td>
8733+
<td class="full" align="center">Clang 3.3</td>
87348734
</tr>
87358735
<tr class="open" id="1488">
87368736
<td><a href="https://cplusplus.github.io/CWG/issues/1488.html">1488</a></td>
@@ -9210,7 +9210,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
92109210
<td><a href="https://cplusplus.github.io/CWG/issues/1567.html">1567</a></td>
92119211
<td>C++14</td>
92129212
<td>Inheriting constructors and copy/move constructors</td>
9213-
<td class="unknown" align="center">Unknown</td>
9213+
<td class="full" align="center">Clang 3.3</td>
92149214
</tr>
92159215
<tr id="1568">
92169216
<td><a href="https://cplusplus.github.io/CWG/issues/1568.html">1568</a></td>
@@ -10236,7 +10236,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1023610236
<td><a href="https://cplusplus.github.io/CWG/issues/1738.html">1738</a></td>
1023710237
<td>C++14</td>
1023810238
<td>Explicit instantiation/specialization of inheriting constructor templates</td>
10239-
<td class="unknown" align="center">Unknown</td>
10239+
<td class="na" align="center">Superseded by <a href="https://wg21.link/P0136R1">P0136R1</a></td>
1024010240
</tr>
1024110241
<tr id="1739">
1024210242
<td><a href="https://cplusplus.github.io/CWG/issues/1739.html">1739</a></td>
@@ -13446,7 +13446,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1344613446
<td><a href="https://cplusplus.github.io/CWG/issues/2273.html">2273</a></td>
1344713447
<td>CD5</td>
1344813448
<td>Inheriting constructors vs implicit default constructor</td>
13449-
<td class="unknown" align="center">Unknown</td>
13449+
<td class="full" align="center">Clang 3.3</td>
1345013450
</tr>
1345113451
<tr id="2274">
1345213452
<td><a href="https://cplusplus.github.io/CWG/issues/2274.html">2274</a></td>
@@ -13470,7 +13470,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1347013470
<td><a href="https://cplusplus.github.io/CWG/issues/2277.html">2277</a></td>
1347113471
<td>CD5</td>
1347213472
<td>Ambiguity inheriting constructors with default arguments</td>
13473-
<td class="unknown" align="center">Unknown</td>
13473+
<td class="partial" align="center">Partial</td>
1347413474
</tr>
1347513475
<tr id="2278">
1347613476
<td><a href="https://cplusplus.github.io/CWG/issues/2278.html">2278</a></td>
@@ -13944,7 +13944,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1394413944
<td><a href="https://cplusplus.github.io/CWG/issues/2356.html">2356</a></td>
1394513945
<td>CD5</td>
1394613946
<td>Base class copy and move constructors should not be inherited</td>
13947-
<td class="unknown" align="center">Unknown</td>
13947+
<td class="full" align="center">Clang 4</td>
1394813948
</tr>
1394913949
<tr id="2357">
1395013950
<td><a href="https://cplusplus.github.io/CWG/issues/2357.html">2357</a></td>
@@ -14832,7 +14832,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1483214832
<td><a href="https://cplusplus.github.io/CWG/issues/2504.html">2504</a></td>
1483314833
<td>DR</td>
1483414834
<td>Inheriting constructors from virtual base classes</td>
14835-
<td class="unknown" align="center">Unknown</td>
14835+
<td class="none" align="center">No</td>
1483614836
</tr>
1483714837
<tr class="open" id="2505">
1483814838
<td><a href="https://cplusplus.github.io/CWG/issues/2505.html">2505</a></td>

0 commit comments

Comments
 (0)