xref: /llvm-project/clang/test/CXX/drs/cwg11xx.cpp (revision 463e61a0013253bec1b5e7f07e7b1803b68e2b3d)
1d358b2deSVlad Serebrennikov // RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98 -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 -fexceptions -fcxx-exceptions -pedantic-errors
4d358b2deSVlad Serebrennikov // RUN: %clang_cc1 -std=c++17 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
5327e2b7cSVlad Serebrennikov // RUN: %clang_cc1 -std=c++20 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
6327e2b7cSVlad Serebrennikov // RUN: %clang_cc1 -std=c++23 %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
7327e2b7cSVlad Serebrennikov // RUN: %clang_cc1 -std=c++2c %s -verify=expected -fexceptions -fcxx-exceptions -pedantic-errors
8d358b2deSVlad Serebrennikov 
9d542eb7aSVlad Serebrennikov namespace cwg1110 { // cwg1110: 3.1
10d542eb7aSVlad Serebrennikov #if __cplusplus >= 201103L
11d542eb7aSVlad Serebrennikov template <typename T>
12d542eb7aSVlad Serebrennikov T return_T();
13d542eb7aSVlad Serebrennikov 
14d542eb7aSVlad Serebrennikov struct A;
15d542eb7aSVlad Serebrennikov 
16d542eb7aSVlad Serebrennikov template <typename>
17d542eb7aSVlad Serebrennikov struct B;
18d542eb7aSVlad Serebrennikov 
19d542eb7aSVlad Serebrennikov decltype(return_T<A>())* a;
20d542eb7aSVlad Serebrennikov decltype(return_T<B<int>>())* b;
21d542eb7aSVlad Serebrennikov #endif
22d542eb7aSVlad Serebrennikov } // namespace cwg1110
23d542eb7aSVlad Serebrennikov 
2464e8d5b1SVlad Serebrennikov namespace cwg1111 { // cwg1111: partial
25d358b2deSVlad Serebrennikov namespace example1 {
26d358b2deSVlad Serebrennikov template <typename> struct set; // #cwg1111-struct-set
27d358b2deSVlad Serebrennikov 
28d358b2deSVlad Serebrennikov struct X {
29d358b2deSVlad Serebrennikov   template <typename T> void set(const T &value); // #cwg1111-func-set
30d358b2deSVlad Serebrennikov };
31d358b2deSVlad Serebrennikov void foo() {
32d358b2deSVlad Serebrennikov   X x;
33d358b2deSVlad Serebrennikov   // FIXME: should we backport C++11 behavior?
34d358b2deSVlad Serebrennikov   x.set<double>(3.2);
35d358b2deSVlad Serebrennikov   // cxx98-error@-1 {{lookup of 'set' in member access expression is ambiguous; using member of 'X'}}
36d358b2deSVlad Serebrennikov   //   cxx98-note@#cwg1111-func-set {{lookup in the object type 'X' refers here}}
37d358b2deSVlad Serebrennikov   //   cxx98-note@#cwg1111-struct-set {{lookup from the current scope refers here}}
38d358b2deSVlad Serebrennikov }
39d358b2deSVlad Serebrennikov 
40d358b2deSVlad Serebrennikov struct Y {};
41d358b2deSVlad Serebrennikov void bar() {
42d358b2deSVlad Serebrennikov   Y y;
43d358b2deSVlad Serebrennikov   y.set<double>(3.2);
44d358b2deSVlad Serebrennikov   // expected-error@-1 {{no member named 'set' in 'cwg1111::example1::Y'}}
45d358b2deSVlad Serebrennikov }
46d358b2deSVlad Serebrennikov } // namespace example1
47d358b2deSVlad Serebrennikov 
48d358b2deSVlad Serebrennikov namespace example2 {
49d358b2deSVlad Serebrennikov struct A {};
50d358b2deSVlad Serebrennikov namespace N {
51d358b2deSVlad Serebrennikov struct A {
52d358b2deSVlad Serebrennikov   void g() {}
53d358b2deSVlad Serebrennikov   template <class T> operator T();
54d358b2deSVlad Serebrennikov };
55d358b2deSVlad Serebrennikov } // namespace N
56d358b2deSVlad Serebrennikov 
57d358b2deSVlad Serebrennikov void baz() {
58d358b2deSVlad Serebrennikov   N::A a;
59d358b2deSVlad Serebrennikov   a.operator A();
60d358b2deSVlad Serebrennikov }
61d358b2deSVlad Serebrennikov } // namespace example2
6264e8d5b1SVlad Serebrennikov 
6364e8d5b1SVlad Serebrennikov namespace example3 {
6464e8d5b1SVlad Serebrennikov struct A {
6564e8d5b1SVlad Serebrennikov   operator int();
6664e8d5b1SVlad Serebrennikov } a;
6764e8d5b1SVlad Serebrennikov void foo() {
6864e8d5b1SVlad Serebrennikov   typedef int T;
6964e8d5b1SVlad Serebrennikov   a.operator T(); // T is found using unqualified lookup
7064e8d5b1SVlad Serebrennikov                   // after qualified lookup in A fails.
7164e8d5b1SVlad Serebrennikov }
7264e8d5b1SVlad Serebrennikov } // namespace example3
7364e8d5b1SVlad Serebrennikov 
7464e8d5b1SVlad Serebrennikov namespace example4 {
7564e8d5b1SVlad Serebrennikov struct A {
7664e8d5b1SVlad Serebrennikov   typedef int T; // #cwg1111-A-T
7764e8d5b1SVlad Serebrennikov   operator T();
7864e8d5b1SVlad Serebrennikov };
7964e8d5b1SVlad Serebrennikov struct B : A {
8064e8d5b1SVlad Serebrennikov   operator T();
8164e8d5b1SVlad Serebrennikov } b;
8264e8d5b1SVlad Serebrennikov void foo() {
8364e8d5b1SVlad Serebrennikov   b.A::operator T(); // FIXME: qualified lookup should find T in A.
8464e8d5b1SVlad Serebrennikov   // expected-error@-1 {{unknown type name 'T'}}
8564e8d5b1SVlad Serebrennikov   //   expected-note@#cwg1111-A-T {{'A::T' declared here}}
8664e8d5b1SVlad Serebrennikov }
8764e8d5b1SVlad Serebrennikov } // namespace example4
8864e8d5b1SVlad Serebrennikov 
8964e8d5b1SVlad Serebrennikov namespace example5 {
9064e8d5b1SVlad Serebrennikov template <class T1> struct A {
9164e8d5b1SVlad Serebrennikov   operator T1();
9264e8d5b1SVlad Serebrennikov };
9364e8d5b1SVlad Serebrennikov template <class T2> struct B : A<T2> {
9464e8d5b1SVlad Serebrennikov   operator T2();
9564e8d5b1SVlad Serebrennikov   void foo() {
9664e8d5b1SVlad Serebrennikov     // In both cases, during instantiation, qualified lookup for T2 wouldn't be able
9764e8d5b1SVlad Serebrennikov     // to find anything, so T2 has to be found by unqualified lookup.
9864e8d5b1SVlad Serebrennikov     // After that, 'operator T2()' is found in A<T2> by qualfied lookup.
9964e8d5b1SVlad Serebrennikov     T2 a = A<T2>::operator T2();
10064e8d5b1SVlad Serebrennikov     T2 b = ((A<T2> *)this)->operator T2();
10164e8d5b1SVlad Serebrennikov   }
10264e8d5b1SVlad Serebrennikov };
10364e8d5b1SVlad Serebrennikov } // namespace example5
104d358b2deSVlad Serebrennikov } // namespace cwg1111
105d358b2deSVlad Serebrennikov 
106d358b2deSVlad Serebrennikov namespace cwg1113 { // cwg1113: partial
107d358b2deSVlad Serebrennikov   namespace named {
108d358b2deSVlad Serebrennikov     extern int a; // #cwg1113-a
109d358b2deSVlad Serebrennikov     static int a;
110d358b2deSVlad Serebrennikov     // expected-error@-1 {{static declaration of 'a' follows non-static}}
111d358b2deSVlad Serebrennikov     //   expected-note@#cwg1113-a {{previous declaration is here}}
112d358b2deSVlad Serebrennikov   }
113d358b2deSVlad Serebrennikov   namespace {
114d358b2deSVlad Serebrennikov     extern int a;
115d358b2deSVlad Serebrennikov     static int a; // ok, both declarations have internal linkage
116d358b2deSVlad Serebrennikov     int b = a;
117d358b2deSVlad Serebrennikov   }
118d358b2deSVlad Serebrennikov 
119d358b2deSVlad Serebrennikov   // FIXME: Per CWG1113 and CWG4, this is ill-formed due to ambiguity: the second
120d358b2deSVlad Serebrennikov   // 'f' has internal linkage, and so does not have C language linkage, so is
121d358b2deSVlad Serebrennikov   // not a redeclaration of the first 'f'.
122d358b2deSVlad Serebrennikov   //
123d358b2deSVlad Serebrennikov   // To avoid a breaking change here, Clang ignores the "internal linkage" effect
124d358b2deSVlad Serebrennikov   // of anonymous namespaces on declarations declared within an 'extern "C"'
125d358b2deSVlad Serebrennikov   // linkage-specification.
126d358b2deSVlad Serebrennikov   extern "C" void f();
127d358b2deSVlad Serebrennikov   namespace {
128d358b2deSVlad Serebrennikov     extern "C" void f();
129d358b2deSVlad Serebrennikov   }
130d358b2deSVlad Serebrennikov   void g() { f(); }
131*463e61a0SVlad Serebrennikov } // namespace cwg1113
132d358b2deSVlad Serebrennikov 
133d358b2deSVlad Serebrennikov // cwg1150: na
134