147 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
 | 
						|
 | 
						|
struct non_trivial {
 | 
						|
  non_trivial();
 | 
						|
  non_trivial(const non_trivial&);
 | 
						|
  non_trivial& operator = (const non_trivial&);
 | 
						|
  ~non_trivial();
 | 
						|
};
 | 
						|
 | 
						|
union u {
 | 
						|
  non_trivial nt;
 | 
						|
};
 | 
						|
union u2 {
 | 
						|
  non_trivial nt;
 | 
						|
  int k;
 | 
						|
  u2(int k) : k(k) {}
 | 
						|
  u2() : nt() {}
 | 
						|
};
 | 
						|
 | 
						|
union static_data_member {
 | 
						|
  static int i;
 | 
						|
};
 | 
						|
int static_data_member::i;
 | 
						|
 | 
						|
union bad {
 | 
						|
  int &i; // expected-error {{union member 'i' has reference type 'int &'}}
 | 
						|
};
 | 
						|
 | 
						|
struct s {
 | 
						|
  union {
 | 
						|
    non_trivial nt;
 | 
						|
  };
 | 
						|
};
 | 
						|
 | 
						|
// Don't crash on this.
 | 
						|
struct TemplateCtor { template<typename T> TemplateCtor(T); };
 | 
						|
union TemplateCtorMember { TemplateCtor s; };
 | 
						|
 | 
						|
template<typename T> struct remove_ref { typedef T type; };
 | 
						|
template<typename T> struct remove_ref<T&> { typedef T type; };
 | 
						|
template<typename T> struct remove_ref<T&&> { typedef T type; };
 | 
						|
template<typename T> T &&forward(typename remove_ref<T>::type &&t);
 | 
						|
template<typename T> T &&forward(typename remove_ref<T>::type &t);
 | 
						|
template<typename T> typename remove_ref<T>::type &&move(T &&t);
 | 
						|
 | 
						|
using size_t = decltype(sizeof(int));
 | 
						|
void *operator new(size_t, void *p) noexcept { return p; }
 | 
						|
 | 
						|
namespace disabled_dtor {
 | 
						|
  template<typename T>
 | 
						|
  union disable_dtor {
 | 
						|
    T val;
 | 
						|
    template<typename...U>
 | 
						|
    disable_dtor(U &&...u) : val(forward<U>(u)...) {}
 | 
						|
    ~disable_dtor() {}
 | 
						|
  };
 | 
						|
 | 
						|
  struct deleted_dtor {
 | 
						|
    deleted_dtor(int n, char c) : n(n), c(c) {}
 | 
						|
    int n;
 | 
						|
    char c;
 | 
						|
    ~deleted_dtor() = delete;
 | 
						|
  };
 | 
						|
 | 
						|
  disable_dtor<deleted_dtor> dd(4, 'x');
 | 
						|
}
 | 
						|
 | 
						|
namespace optional {
 | 
						|
  template<typename T> struct optional {
 | 
						|
    bool has;
 | 
						|
    union { T value; };
 | 
						|
 | 
						|
    optional() : has(false) {}
 | 
						|
    template<typename...U>
 | 
						|
    optional(U &&...u) : has(true), value(forward<U>(u)...) {}
 | 
						|
 | 
						|
    optional(const optional &o) : has(o.has) {
 | 
						|
      if (has) new (&value) T(o.value);
 | 
						|
    }
 | 
						|
    optional(optional &&o) : has(o.has) {
 | 
						|
      if (has) new (&value) T(move(o.value));
 | 
						|
    }
 | 
						|
 | 
						|
    optional &operator=(const optional &o) {
 | 
						|
      if (has) {
 | 
						|
        if (o.has)
 | 
						|
          value = o.value;
 | 
						|
        else
 | 
						|
          value.~T();
 | 
						|
      } else if (o.has) {
 | 
						|
        new (&value) T(o.value);
 | 
						|
      }
 | 
						|
      has = o.has;
 | 
						|
    }
 | 
						|
    optional &operator=(optional &&o) {
 | 
						|
      if (has) {
 | 
						|
        if (o.has)
 | 
						|
          value = move(o.value);
 | 
						|
        else
 | 
						|
          value.~T();
 | 
						|
      } else if (o.has) {
 | 
						|
        new (&value) T(move(o.value));
 | 
						|
      }
 | 
						|
      has = o.has;
 | 
						|
    }
 | 
						|
 | 
						|
    ~optional() {
 | 
						|
      if (has)
 | 
						|
        value.~T();
 | 
						|
    }
 | 
						|
 | 
						|
    explicit operator bool() const { return has; }
 | 
						|
    T &operator*() const { return value; }
 | 
						|
  };
 | 
						|
 | 
						|
  optional<non_trivial> o1;
 | 
						|
  optional<non_trivial> o2{non_trivial()};
 | 
						|
  optional<non_trivial> o3{*o2};
 | 
						|
  void f() {
 | 
						|
    if (o2)
 | 
						|
      o1 = o2;
 | 
						|
    o2 = optional<non_trivial>();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace pr16061 {
 | 
						|
  struct X { X(); };
 | 
						|
 | 
						|
  template<typename T> struct Test1 {
 | 
						|
    union {
 | 
						|
      struct {
 | 
						|
        X x;
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  template<typename T> struct Test2 {
 | 
						|
    union {
 | 
						|
      struct {  // expected-note {{default constructor of 'Test2<pr16061::X>' is implicitly deleted because variant field '' has a non-trivial default constructor}}
 | 
						|
        T x;
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  Test2<X> t2x;  // expected-error {{call to implicitly-deleted default constructor of 'Test2<pr16061::X>'}}
 | 
						|
}
 |