127 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			127 lines
		
	
	
		
			3.8 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; }
 | |
| }
 |