mirror of https://github.com/microsoft/clang.git
97 lines
2.9 KiB
C++
97 lines
2.9 KiB
C++
// RUN: %clang_cc1 -verify -pedantic %s -std=c++98
|
|
// RUN: %clang_cc1 -verify -pedantic %s -std=c++11
|
|
|
|
template<typename T> struct atomic {
|
|
_Atomic(T) value;
|
|
|
|
void f() _Atomic; // expected-error {{expected ';' at end of declaration list}}
|
|
};
|
|
|
|
template<typename T> struct user {
|
|
struct inner { char n[sizeof(T)]; };
|
|
atomic<inner> i;
|
|
};
|
|
|
|
user<int> u;
|
|
|
|
// Test overloading behavior of atomics.
|
|
struct A { };
|
|
|
|
int &ovl1(_Atomic(int));
|
|
int &ovl1(_Atomic int); // ok, redeclaration
|
|
long &ovl1(_Atomic(long));
|
|
float &ovl1(_Atomic(float));
|
|
double &ovl1(_Atomic(A const *const *));
|
|
double &ovl1(A const *const *_Atomic);
|
|
short &ovl1(_Atomic(A **));
|
|
|
|
void test_overloading(int i, float f, _Atomic(int) ai, _Atomic(float) af,
|
|
long l, _Atomic(long) al, A const *const *acc,
|
|
A const ** ac, A **a) {
|
|
int& ir1 = ovl1(i);
|
|
int& ir2 = ovl1(ai);
|
|
long& lr1 = ovl1(l);
|
|
long& lr2 = ovl1(al);
|
|
float &fr1 = ovl1(f);
|
|
float &fr2 = ovl1(af);
|
|
double &dr1 = ovl1(acc);
|
|
double &dr2 = ovl1(ac);
|
|
short &sr1 = ovl1(a);
|
|
}
|
|
|
|
typedef int (A::*fp)() _Atomic; // expected-error {{expected ';' after top level declarator}} expected-warning {{does not declare anything}}
|
|
|
|
typedef _Atomic(int(A::*)) atomic_mem_ptr_to_int;
|
|
typedef int(A::*_Atomic atomic_mem_ptr_to_int);
|
|
|
|
typedef _Atomic(int)(A::*mem_ptr_to_atomic_int);
|
|
typedef _Atomic int(A::*mem_ptr_to_atomic_int);
|
|
|
|
typedef _Atomic(int)&atomic_int_ref;
|
|
typedef _Atomic int &atomic_int_ref;
|
|
typedef _Atomic atomic_int_ref atomic_int_ref; // expected-warning {{'_Atomic' qualifier on reference type 'atomic_int_ref' (aka '_Atomic(int) &') has no effect}}
|
|
|
|
typedef int &_Atomic atomic_reference_to_int; // expected-error {{'_Atomic' qualifier may not be applied to a reference}}
|
|
typedef _Atomic(int &) atomic_reference_to_int; // expected-error {{_Atomic cannot be applied to reference type 'int &'}}
|
|
|
|
struct S {
|
|
_Atomic union { int n; }; // expected-warning {{anonymous union cannot be '_Atomic'}}
|
|
};
|
|
|
|
namespace copy_init {
|
|
struct X {
|
|
X(int);
|
|
int n;
|
|
};
|
|
_Atomic(X) y = X(0);
|
|
_Atomic(X) z(X(0));
|
|
void f() { y = X(0); }
|
|
|
|
_Atomic(X) e1(0); // expected-error {{cannot initialize}}
|
|
#if __cplusplus >= 201103L
|
|
_Atomic(X) e2{0}; // expected-error {{illegal initializer}}
|
|
_Atomic(X) a{X(0)};
|
|
// FIXME: This does not seem like the right answer.
|
|
_Atomic(int) e3{0}; // expected-error {{illegal initializer}}
|
|
#endif
|
|
|
|
struct Y {
|
|
_Atomic(X) a;
|
|
_Atomic(int) b;
|
|
};
|
|
Y y1 = { X(0), 4 };
|
|
Y y2 = { 0, 4 }; // expected-error {{cannot initialize}}
|
|
|
|
// FIXME: It's not really clear if we should allow these. Generally, C++11
|
|
// allows extraneous braces around initializers. We should at least give the
|
|
// same answer in all these cases:
|
|
Y y3 = { X(0), { 4 } }; // expected-error {{illegal initializer type}}
|
|
Y y4 = { { X(0) }, 4 };
|
|
_Atomic(int) ai = { 4 }; // expected-error {{illegal initializer type}}
|
|
_Atomic(X) ax = { X(0) };
|
|
}
|
|
|
|
bool PR21836(_Atomic(int) *x) {
|
|
return *x;
|
|
}
|