xref: /llvm-project/clang/test/CXX/drs/cwg10xx.cpp (revision 463e61a0013253bec1b5e7f07e7b1803b68e2b3d)
1d358b2deSVlad Serebrennikov // RUN: %clang_cc1 -std=c++98 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
2d358b2deSVlad Serebrennikov // RUN: %clang_cc1 -std=c++11 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
3d358b2deSVlad Serebrennikov // RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
4d358b2deSVlad Serebrennikov // RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
5d358b2deSVlad Serebrennikov // RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
6d358b2deSVlad Serebrennikov // RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
7327e2b7cSVlad Serebrennikov // RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
8d358b2deSVlad Serebrennikov 
9d358b2deSVlad Serebrennikov namespace std {
10d358b2deSVlad Serebrennikov   __extension__ typedef __SIZE_TYPE__ size_t;
11d358b2deSVlad Serebrennikov 
12d358b2deSVlad Serebrennikov   template<typename T> struct initializer_list {
13d358b2deSVlad Serebrennikov     const T *p; size_t n;
14d358b2deSVlad Serebrennikov     initializer_list(const T *p, size_t n);
15d358b2deSVlad Serebrennikov   };
16*463e61a0SVlad Serebrennikov } // namespace std
17d358b2deSVlad Serebrennikov 
18d358b2deSVlad Serebrennikov namespace cwg1004 { // cwg1004: 5
19d358b2deSVlad Serebrennikov   template<typename> struct A {};
20d358b2deSVlad Serebrennikov   template<typename> struct B1 {};
21d358b2deSVlad Serebrennikov   template<template<typename> class> struct B2 {};
22d358b2deSVlad Serebrennikov   template<typename X> void f(); // #cwg1004-f-1
23d358b2deSVlad Serebrennikov   template<template<typename> class X> void f(); // #cwg1004-f-2
24d358b2deSVlad Serebrennikov   template<template<typename> class X> void g(); // #cwg1004-g-1
25d358b2deSVlad Serebrennikov   template<typename X> void g(); // #cwg1004-g-2
26d358b2deSVlad Serebrennikov   struct C : A<int> {
27d358b2deSVlad Serebrennikov     B1<A> b1a;
28d358b2deSVlad Serebrennikov     B2<A> b2a;
29d358b2deSVlad Serebrennikov     void h() {
30d358b2deSVlad Serebrennikov       f<A>();
31d358b2deSVlad Serebrennikov       // expected-error@-1 {{call to 'f' is ambiguous}}
32d358b2deSVlad Serebrennikov       //   expected-note@#cwg1004-f-1 {{candidate function [with X = cwg1004::A<int>]}}
33d358b2deSVlad Serebrennikov       //   expected-note@#cwg1004-f-2 {{candidate function [with X = cwg1004::A]}}
34d358b2deSVlad Serebrennikov       g<A>();
35d358b2deSVlad Serebrennikov       // expected-error@-1 {{call to 'g' is ambiguous}}
36d358b2deSVlad Serebrennikov       //   expected-note@#cwg1004-g-1 {{candidate function [with X = cwg1004::A]}}
37d358b2deSVlad Serebrennikov       //   expected-note@#cwg1004-g-2 {{candidate function [with X = cwg1004::A<int>]}}
38d358b2deSVlad Serebrennikov     }
39d358b2deSVlad Serebrennikov   };
40d358b2deSVlad Serebrennikov 
41d358b2deSVlad Serebrennikov   // This example (from the standard) is actually ill-formed, because
42d358b2deSVlad Serebrennikov   // name lookup of "T::template A" names the constructor.
43d358b2deSVlad Serebrennikov   template<class T, template<class> class U = T::template A> struct Third { };
44d358b2deSVlad Serebrennikov   // expected-error@-1 {{is a constructor name}}
45d358b2deSVlad Serebrennikov   //   expected-note@#cwg1004-t {{in instantiation of default argument}}
46d358b2deSVlad Serebrennikov   Third<A<int> > t; // #cwg1004-t
47*463e61a0SVlad Serebrennikov } // namespace cwg1004
48d358b2deSVlad Serebrennikov 
49d358b2deSVlad Serebrennikov namespace cwg1042 { // cwg1042: 3.5
50d358b2deSVlad Serebrennikov #if __cplusplus >= 201402L
51d358b2deSVlad Serebrennikov   // C++14 added an attribute that we can test the semantics of.
52d358b2deSVlad Serebrennikov   using foo [[deprecated]] = int; // #cwg1042-using
53d358b2deSVlad Serebrennikov   foo f = 12;
54d358b2deSVlad Serebrennikov   // since-cxx14-warning@-1 {{'foo' is deprecated}}
55d358b2deSVlad Serebrennikov   //   since-cxx14-note@#cwg1042-using {{'foo' has been explicitly marked deprecated here}}
56d358b2deSVlad Serebrennikov #elif __cplusplus >= 201103L
57d358b2deSVlad Serebrennikov   // C++11 did not have any attributes that could be applied to an alias
58d358b2deSVlad Serebrennikov   // declaration, so the best we can test is that we accept an empty attribute
59d358b2deSVlad Serebrennikov   // list in this mode.
60d358b2deSVlad Serebrennikov   using foo [[]] = int;
61d358b2deSVlad Serebrennikov #endif
62*463e61a0SVlad Serebrennikov } // namespace cwg1042
63d358b2deSVlad Serebrennikov 
64d358b2deSVlad Serebrennikov namespace cwg1048 { // cwg1048: 3.6
65d358b2deSVlad Serebrennikov   struct A {};
66d358b2deSVlad Serebrennikov   const A f();
67d358b2deSVlad Serebrennikov   A g();
68d358b2deSVlad Serebrennikov   typedef const A CA;
69d358b2deSVlad Serebrennikov #if __cplusplus >= 201103L
70d358b2deSVlad Serebrennikov   // ok: we deduce non-const A in each case.
71d358b2deSVlad Serebrennikov   A &&a = [] (int n) {
72d358b2deSVlad Serebrennikov     while (1) switch (n) {
73d358b2deSVlad Serebrennikov       case 0: return f();
74d358b2deSVlad Serebrennikov       case 1: return g();
75d358b2deSVlad Serebrennikov       case 2: return A();
76d358b2deSVlad Serebrennikov       case 3: return CA();
77d358b2deSVlad Serebrennikov     }
78d358b2deSVlad Serebrennikov   } (0);
79d358b2deSVlad Serebrennikov #endif
80*463e61a0SVlad Serebrennikov } // namespace cwg1048
81d358b2deSVlad Serebrennikov 
82d358b2deSVlad Serebrennikov namespace cwg1054 { // cwg1054: no
83d358b2deSVlad Serebrennikov   // FIXME: Test is incomplete.
84d358b2deSVlad Serebrennikov   struct A {} volatile a;
85d358b2deSVlad Serebrennikov   void f() {
86d358b2deSVlad Serebrennikov     // FIXME: This is wrong: an lvalue-to-rvalue conversion is applied here,
87d358b2deSVlad Serebrennikov     // which copy-initializes a temporary from 'a'. Therefore this is
88d358b2deSVlad Serebrennikov     // ill-formed because A does not have a volatile copy constructor.
89d358b2deSVlad Serebrennikov     // (We might want to track this aspect under cwg1383 instead?)
90d358b2deSVlad Serebrennikov     a;
91d358b2deSVlad Serebrennikov     // expected-warning@-1 {{expression result unused; assign into a variable to force a volatile load}}
92d358b2deSVlad Serebrennikov   }
93*463e61a0SVlad Serebrennikov } // namespace cwg1054
94d358b2deSVlad Serebrennikov 
95d358b2deSVlad Serebrennikov namespace cwg1070 { // cwg1070: 3.5
96d358b2deSVlad Serebrennikov #if __cplusplus >= 201103L
97d358b2deSVlad Serebrennikov   struct A {
98d358b2deSVlad Serebrennikov     A(std::initializer_list<int>);
99d358b2deSVlad Serebrennikov   };
100d358b2deSVlad Serebrennikov   struct B {
101d358b2deSVlad Serebrennikov     int i;
102d358b2deSVlad Serebrennikov     A a;
103d358b2deSVlad Serebrennikov   };
104d358b2deSVlad Serebrennikov   B b = {1};
105d358b2deSVlad Serebrennikov   struct C {
106d358b2deSVlad Serebrennikov     std::initializer_list<int> a;
107d358b2deSVlad Serebrennikov     B b;
108d358b2deSVlad Serebrennikov     std::initializer_list<double> c;
109d358b2deSVlad Serebrennikov   };
110d358b2deSVlad Serebrennikov   C c = {};
111d358b2deSVlad Serebrennikov #endif
112*463e61a0SVlad Serebrennikov } // namespace cwg1070
113