144 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			144 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s
 | 
						|
// C++ [expr.const]p1:
 | 
						|
//   In several places, C++ requires expressions that evaluate to an integral
 | 
						|
//   or enumeration constant: as array bounds, as case expressions, as
 | 
						|
//   bit-field lengths, as enumerator initializers, as static member
 | 
						|
//   initializers, and as integral or enumeration non-type template arguments.
 | 
						|
//   An integral constant-expression can involve only literals, enumerators,
 | 
						|
//   const variables or static data members of integral or enumeration types
 | 
						|
//   initialized with constant expressions, and sizeof expressions. Floating
 | 
						|
//   literals can appear only if they are cast to integral or enumeration types.
 | 
						|
 | 
						|
enum Enum { eval = 1 };
 | 
						|
const int cval = 2;
 | 
						|
const Enum ceval = eval;
 | 
						|
struct Struct {
 | 
						|
  static const int sval = 3;
 | 
						|
  static const Enum seval = eval;
 | 
						|
};
 | 
						|
 | 
						|
template <int itval, Enum etval> struct C {
 | 
						|
  enum E {
 | 
						|
    v1 = 1,
 | 
						|
    v2 = eval,
 | 
						|
    v3 = cval,
 | 
						|
    v4 = ceval,
 | 
						|
    v5 = Struct::sval,
 | 
						|
    v6 = Struct::seval,
 | 
						|
    v7 = itval,
 | 
						|
    v8 = etval,
 | 
						|
    v9 = (int)1.5,
 | 
						|
    v10 = sizeof(Struct),
 | 
						|
    v11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0
 | 
						|
  };
 | 
						|
  unsigned
 | 
						|
    b1 : 1,
 | 
						|
    b2 : eval,
 | 
						|
    b3 : cval,
 | 
						|
    b4 : ceval,
 | 
						|
    b5 : Struct::sval,
 | 
						|
    b6 : Struct::seval,
 | 
						|
    b7 : itval,
 | 
						|
    b8 : etval,
 | 
						|
    b9 : (int)1.5,
 | 
						|
    b10 : sizeof(Struct),
 | 
						|
    b11 : true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0
 | 
						|
    ;
 | 
						|
  static const int
 | 
						|
    i1 = 1,
 | 
						|
    i2 = eval,
 | 
						|
    i3 = cval,
 | 
						|
    i4 = ceval,
 | 
						|
    i5 = Struct::sval,
 | 
						|
    i6 = Struct::seval,
 | 
						|
    i7 = itval,
 | 
						|
    i8 = etval,
 | 
						|
    i9 = (int)1.5,
 | 
						|
    i10 = sizeof(Struct),
 | 
						|
    i11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0
 | 
						|
    ;
 | 
						|
  void f(int cond) {
 | 
						|
    switch(cond) {
 | 
						|
    case    0 + 1:
 | 
						|
    case  100 + eval:
 | 
						|
    case  200 + cval:
 | 
						|
    case  300 + ceval:
 | 
						|
    case  400 + Struct::sval:
 | 
						|
    case  500 + Struct::seval:
 | 
						|
    case  600 + itval:
 | 
						|
    case  700 + etval:
 | 
						|
    case  800 + (int)1.5:
 | 
						|
    case  900 + sizeof(Struct):
 | 
						|
    case 1000 + (true? 1 + cval * Struct::sval ^
 | 
						|
                 itval / (int)1.5 - sizeof(Struct) : 0):
 | 
						|
      ;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  typedef C<itval, etval> T0;
 | 
						|
};
 | 
						|
 | 
						|
template struct C<1, eval>;
 | 
						|
template struct C<cval, ceval>;
 | 
						|
template struct C<Struct::sval, Struct::seval>;
 | 
						|
 | 
						|
enum {
 | 
						|
  a = sizeof(int) == 8,
 | 
						|
  b = a? 8 : 4
 | 
						|
};
 | 
						|
 | 
						|
void diags(int n) {
 | 
						|
  switch (n) {
 | 
						|
    case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
 | 
						|
    case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
 | 
						|
    case __imag(1/0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
 | 
						|
    case (int)__imag((double)(1/0)): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
 | 
						|
      ;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace IntOrEnum {
 | 
						|
  const int k = 0;
 | 
						|
  const int &p = k;
 | 
						|
  template<int n> struct S {};
 | 
						|
  S<p> s; // expected-error {{not an integral constant expression}}
 | 
						|
}
 | 
						|
 | 
						|
extern const int recurse1;
 | 
						|
// recurse2 cannot be used in a constant expression because it is not
 | 
						|
// initialized by a constant expression. The same expression appearing later in
 | 
						|
// the TU would be a constant expression, but here it is not.
 | 
						|
const int recurse2 = recurse1;
 | 
						|
const int recurse1 = 1;
 | 
						|
int array1[recurse1]; // ok
 | 
						|
int array2[recurse2]; // expected-warning {{variable length array}} expected-warning {{integer constant expression}}
 | 
						|
 | 
						|
namespace FloatConvert {
 | 
						|
  typedef int a[(int)42.3];
 | 
						|
  typedef int a[(int)42.997];
 | 
						|
  typedef int b[(long long)4e20]; // expected-warning {{variable length}} expected-error {{variable length}} expected-warning {{'long long' is a C++11 extension}}
 | 
						|
}
 | 
						|
 | 
						|
// PR12626
 | 
						|
namespace test3 {
 | 
						|
  struct X; // expected-note {{forward declaration of 'test3::X'}}
 | 
						|
  struct Y { bool b; X x; }; // expected-error {{field has incomplete type 'test3::X'}}
 | 
						|
  int f() { return Y().b; }
 | 
						|
}
 | 
						|
 | 
						|
// PR18283
 | 
						|
namespace test4 {
 | 
						|
  template <int> struct A {};
 | 
						|
  int const i = { 42 };
 | 
						|
  // i can be used as non-type template-parameter as "const int x = { 42 };" is
 | 
						|
  // equivalent to "const int x = 42;" as per C++03 8.5/p13.
 | 
						|
  typedef A<i> Ai; // ok
 | 
						|
}
 | 
						|
 | 
						|
// rdar://16064952
 | 
						|
namespace rdar16064952 {
 | 
						|
  template < typename T > void fn1() {
 | 
						|
   T b;
 | 
						|
   unsigned w = ({int a = b.val[sizeof(0)]; 0; }); // expected-warning {{use of GNU statement expression extension}}
 | 
						|
  }
 | 
						|
}
 |