brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.4 KiB · 9a61321 Raw
422 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-linux -verify=both,expected -std=c++11 %s -fexperimental-new-constant-interpreter2// RUN: %clang_cc1 -triple x86_64-linux -verify=both,ref      -std=c++11 %s3 4namespace IntOrEnum {5  const int k = 0;6  const int &p = k;7  template<int n> struct S {};8  S<p> s;9}10 11const int cval = 2;12template <int> struct C{};13template struct C<cval>;14 15 16/// FIXME: This example does not get properly diagnosed in the new interpreter.17extern const int recurse1;18const int recurse2 = recurse1; // both-note {{here}}19const int recurse1 = 1;20int array1[recurse1];21int array2[recurse2]; // both-warning {{variable length arrays in C++}} \22                      // both-note {{initializer of 'recurse2' is not a constant expression}} \23                      // expected-error {{variable length array declaration not allowed at file scope}} \24                      // ref-warning {{variable length array folded to constant array as an extension}}25 26constexpr int b = b; // both-error {{must be initialized by a constant expression}} \27                     // both-note {{read of object outside its lifetime is not allowed in a constant expression}}28 29 30[[clang::require_constant_initialization]] int c = c; // both-error {{variable does not have a constant initializer}} \31                                                      // both-note {{attribute here}} \32                                                      // both-note {{read of non-const variable}} \33                                                      // both-note {{declared here}}34 35 36struct S {37  int m;38};39constexpr S s = { 5 };40constexpr const int *p = &s.m + 1;41 42constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // both-error {{constexpr variable 'np2' must be initialized by a constant expression}} \43                                                      // both-note  {{dereferencing a null pointer is not allowed in a constant expression}}44 45constexpr int preDec(int x) { // both-error {{never produces a constant expression}}46  return --x;                 // both-note {{subexpression}}47}48 49constexpr int postDec(int x) { // both-error {{never produces a constant expression}}50  return x--;                  // both-note {{subexpression}}51}52 53constexpr int preInc(int x) { // both-error {{never produces a constant expression}}54  return ++x;                  // both-note {{subexpression}}55}56 57constexpr int postInc(int x) { // both-error {{never produces a constant expression}}58  return x++;                  // both-note {{subexpression}}59}60 61 62namespace ReferenceToConst {63  template<int n> struct S; // both-note 1{{here}}64  struct LiteralType {65    constexpr LiteralType(int n) : n(n) {}66    int n;67  };68  template<int n> struct T {69    T() {70      static const int ki = 42;71      const int &i2 = ki;72      typename S<i2>::T check5; // both-error {{undefined template}}73    }74  };75}76 77 78 79namespace GH50055 {80// Enums without fixed underlying type81enum E1 {e11=-4, e12=4};82enum E2 {e21=0, e22=4};83enum E3 {e31=-4, e32=1024};84enum E4 {e41=0};85// Empty but as-if it had a single enumerator with value 086enum EEmpty {};87 88// Enum with fixed underlying type because the underlying type is explicitly specified89enum EFixed : int {efixed1=-4, efixed2=4};90// Enum with fixed underlying type because it is scoped91enum class EScoped {escoped1=-4, escoped2=4};92 93enum EMaxInt {emaxint1=-1, emaxint2=__INT_MAX__};94 95enum NumberType {};96 97E2 testDefaultArgForParam(E2 e2Param = (E2)-1) { // ok, not a constant expression context98  E2 e2LocalInit = e2Param; // ok, not a constant expression context99  return e2LocalInit;100}101 102// #include <enum-constexpr-conversion-system-header.h>103 104void testValueInRangeOfEnumerationValues() {105  constexpr E1 x1 = static_cast<E1>(-8);106  constexpr E1 x2 = static_cast<E1>(8);107  // both-error@-1 {{constexpr variable 'x2' must be initialized by a constant expression}}108  // both-note@-2 {{integer value 8 is outside the valid range of values [-8, 7] for the enumeration type 'E1'}}109  E1 x2b = static_cast<E1>(8); // ok, not a constant expression context110 111  constexpr E2 x3 = static_cast<E2>(-8);112  // both-error@-1 {{constexpr variable 'x3' must be initialized by a constant expression}}113  // both-note@-2 {{integer value -8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}114  constexpr E2 x4 = static_cast<E2>(0);115  constexpr E2 x5 = static_cast<E2>(8);116  // both-error@-1 {{constexpr variable 'x5' must be initialized by a constant expression}}117  // both-note@-2 {{integer value 8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}118 119  constexpr E3 x6 = static_cast<E3>(-2048);120  constexpr E3 x7 = static_cast<E3>(-8);121  constexpr E3 x8 = static_cast<E3>(0);122  constexpr E3 x9 = static_cast<E3>(8);123  constexpr E3 x10 = static_cast<E3>(2048);124  // both-error@-1 {{constexpr variable 'x10' must be initialized by a constant expression}}125  // both-note@-2 {{integer value 2048 is outside the valid range of values [-2048, 2047] for the enumeration type 'E3'}}126 127  constexpr E4 x11 = static_cast<E4>(0);128  constexpr E4 x12 = static_cast<E4>(1);129  constexpr E4 x13 = static_cast<E4>(2);130  // both-error@-1 {{constexpr variable 'x13' must be initialized by a constant expression}}131  // both-note@-2 {{integer value 2 is outside the valid range of values [0, 1] for the enumeration type 'E4'}}132 133  constexpr EEmpty x14 = static_cast<EEmpty>(0);134  constexpr EEmpty x15 = static_cast<EEmpty>(1);135  constexpr EEmpty x16 = static_cast<EEmpty>(2);136  // both-error@-1 {{constexpr variable 'x16' must be initialized by a constant expression}}137  // both-note@-2 {{integer value 2 is outside the valid range of values [0, 1] for the enumeration type 'EEmpty'}}138 139  constexpr EFixed x17 = static_cast<EFixed>(100);140  constexpr EScoped x18 = static_cast<EScoped>(100);141 142  constexpr EMaxInt x19 = static_cast<EMaxInt>(__INT_MAX__-1);143  constexpr EMaxInt x20 = static_cast<EMaxInt>((long)__INT_MAX__+1);144  // both-error@-1 {{constexpr variable 'x20' must be initialized by a constant expression}}145  // both-note@-2 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for the enumeration type 'EMaxInt'}}146 147  const NumberType neg_one = (NumberType) ((NumberType) 0 - (NumberType) 1); // ok, not a constant expression context148}149struct EnumTest {150  enum type {151      Type1,152      BOUND153  };154  static const type binding_completed = type(BOUND + 1); // both-error {{in-class initializer for static data member is not a constant expression}} \155                                                         // both-note {{integer value 2 is outside the valid range of values}}156};157 158template<class T, unsigned size> struct Bitfield {159  static constexpr T max = static_cast<T>((1 << size) - 1);160  // both-error@-1 {{constexpr variable 'max' must be initialized by a constant expression}}161  // both-note@-2 {{integer value 15 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}162};163 164void testValueInRangeOfEnumerationValuesViaTemplate() {165  Bitfield<E2, 3> good;166  Bitfield<E2, 4> bad; // both-note {{in instantiation}}167}168 169enum SortOrder {170  AscendingOrder,171  DescendingOrder172};173 174class A {175  static void f(SortOrder order);176};177 178void A::f(SortOrder order) {179  if (order == SortOrder(-1)) // ok, not a constant expression context180    return;181}182}183 184namespace FinalLtorDiags {185  template<int*> struct A {}; // both-note {{template parameter is declared here}}186  int k;187  int *q = &k; // both-note {{declared here}}188  A<q> c; // both-error {{non-type template argument of type 'int *' is not a constant expression}} \189          // both-note {{read of non-constexpr variable 'q' is not allowed in a constant expression}}190}191 192void lambdas() {193  int d;194  int a9[1] = {[d = 0] = 1}; // both-error {{not an integral constant expression}}195}196 197 198namespace InitLinkToRVO {199  struct A {200    int y = 3;201    int z = 1 + y;202  };203 204  constexpr A make() { return A {}; }205  static_assert(make().z == 4, "");206}207 208namespace DynamicCast {209  struct S { int x, y; } s;210  constexpr S* sptr = &s;211  struct Str {212    int b : reinterpret_cast<S*>(sptr) == reinterpret_cast<S*>(sptr);213    int g : (S*)(void*)(sptr) == sptr;214  };215}216 217namespace GlobalInitializer {218  extern int &g; // both-note {{here}}219  struct S {220    int G : g; // both-error {{constant expression}} \221               // both-note {{initializer of 'g' is unknown}}222  };223}224 225namespace ExternPointer {226  struct S { int a; };227  extern const S pu;228  constexpr const int *pua = &pu.a; // Ok.229}230 231namespace PseudoDtor {232  typedef int I;233  constexpr int f(int a = 1) { // both-error {{never produces a constant expression}} \234                               // ref-note {{destroying object 'a' whose lifetime has already ended}}235    return (236        a.~I(), // both-note {{pseudo-destructor call is not permitted}} \237                // expected-note {{pseudo-destructor call is not permitted}}238        0);239  }240  static_assert(f() == 0, ""); // both-error {{constant expression}} \241                               // expected-note {{in call to}}242}243 244namespace IntToPtrCast {245  typedef __INTPTR_TYPE__ intptr_t;246 247  constexpr intptr_t f(intptr_t x) {248    return (((x) >> 21) * 8);249  }250 251  extern "C" int foo;252  constexpr intptr_t i = f((intptr_t)&foo - 10); // both-error{{constexpr variable 'i' must be initialized by a constant expression}} \253                                                 // both-note{{reinterpret_cast}}254}255 256namespace Volatile {257  constexpr int f(volatile int &&r) {258    return r; // both-note {{read of volatile-qualified type 'volatile int'}}259  }260  struct S {261    int j : f(0); // both-error {{constant expression}} \262                  // both-note {{in call to 'f(0)'}}263  };264}265 266namespace ZeroSizeCmp {267  extern void (*start[])();268  extern void (*end[])();269  static_assert(&start != &end, ""); // both-error {{constant expression}} \270                                     // both-note {{comparison of pointers '&start' and '&end' to unrelated zero-sized objects}}271}272 273namespace OverlappingStrings {274  static_assert(+"foo" != +"bar", "");275  static_assert(&"xfoo"[1] != &"yfoo"[1], "");276  static_assert(+"foot" != +"foo", "");277  static_assert(+"foo\0bar" != +"foo\0baz", "");278 279 280#define fold(x) (__builtin_constant_p(x) ? (x) : (x))281  static_assert(fold((const char*)u"A" != (const char*)"\0A\0x"), "");282  static_assert(fold((const char*)u"A" != (const char*)"A\0\0x"), "");283  static_assert(fold((const char*)u"AAA" != (const char*)"AAA\0\0x"), "");284 285  constexpr const char *string = "hello";286  constexpr const char *also_string = string;287  static_assert(string == string, "");288  static_assert(string == also_string, "");289 290 291  // These strings may overlap, and so the result of the comparison is unknown.292  constexpr bool may_overlap_1 = +"foo" == +"foo"; // both-error {{}} both-note {{addresses of potentially overlapping literals}}293  constexpr bool may_overlap_2 = +"foo" == +"foo\0bar"; // both-error {{}} both-note {{addresses of potentially overlapping literals}}294  constexpr bool may_overlap_3 = +"foo" == &"bar\0foo"[4]; // both-error {{}} both-note {{addresses of potentially overlapping literals}}295  constexpr bool may_overlap_4 = &"xfoo"[1] == &"xfoo"[1]; // both-error {{}} both-note {{addresses of potentially overlapping literals}}296 297 298  /// Used to crash.299  const bool x = &"ab"[0] == &"ba"[3];300 301}302 303namespace NonConstLocal {304  int a() {305    const int t=t; // both-note {{declared here}}306 307    switch(1) {308      case t:; // both-note {{initializer of 't' is not a constant expression}} \309               // both-error {{case value is not a constant expression}}310    }311  }312}313 314#define ATTR __attribute__((require_constant_initialization))315int somefunc() {316  const int non_global = 42; // both-note {{declared here}}317  ATTR static const int &local_init = non_global; // both-error {{variable does not have a constant initializer}} \318                                                  // both-note {{required by}} \319                                                  // both-note {{reference to 'non_global' is not a constant expression}}320}321 322namespace PR19010 {323  struct Empty {};324  struct Empty2 : Empty {};325  struct Test : Empty2 {326    constexpr Test() {}327    Empty2 array[2];328  };329  void test() { constexpr Test t; }330}331 332namespace ReadMutableInCopyCtor {333  struct G {334    struct X {};335    union U { X a; };336    mutable U u; // both-note {{declared here}}337  };338  constexpr G g1 = {};339  constexpr G g2 = g1; // both-error {{must be initialized by a constant expression}} \340                       // both-note {{read of mutable member 'u'}} \341                       // both-note {{in call to 'G(g1)'}}342}343 344namespace GH150709 {345  struct C { };346  struct D : C {347    constexpr int f() const { return 1; };348  };349  struct E : C { };350  struct F : D { };351  struct G : E { };352  353  constexpr C c1, c2[2];354  constexpr D d1, d2[2];355  constexpr E e1, e2[2];356  constexpr F f;357  constexpr G g;358 359  constexpr auto mp = static_cast<int (C::*)() const>(&D::f);360 361  // sanity checks for fix of GH150709 (unchanged behavior)362  static_assert((c1.*mp)() == 1, ""); // both-error {{constant expression}}363  static_assert((d1.*mp)() == 1, "");364  static_assert((f.*mp)() == 1, "");365  static_assert((c2[0].*mp)() == 1, ""); // ref-error {{constant expression}}366  static_assert((d2[0].*mp)() == 1, "");367 368  // incorrectly undiagnosed before fix of GH150709369  static_assert((e1.*mp)() == 1, ""); // ref-error {{constant expression}}370  static_assert((e2[0].*mp)() == 1, ""); // ref-error {{constant expression}}371  static_assert((g.*mp)() == 1, ""); // ref-error {{constant expression}}372}373 374namespace DiscardedAddrLabel {375  void foo(void) {376  L:377    *&&L; // both-error {{indirection not permitted on operand of type 'void *'}} \378          // both-warning {{expression result unused}}379  }380}381 382struct Counter {383  int copies;384  constexpr Counter(int copies) : copies(copies) {}385  constexpr Counter(const Counter& other) : copies(other.copies + 1) {}386};387// Passing an lvalue by value makes a non-elidable copy.388constexpr int PassByValue(Counter c) { return c.copies; }389static_assert(PassByValue(Counter(0)) == 0, "expect no copies");390 391namespace PointerCast {392  /// The two interpreters disagree here.393  struct S { int x, y; } s;394  constexpr S* sptr = &s;395  struct U {};396  struct Str {397    int e : (Str*)(sptr) == (Str*)(sptr); // expected-error {{not an integral constant expression}} \398                                          // expected-note {{cast that performs the conversions of a reinterpret_cast}}399  };400}401 402namespace DummyToGlobalBlockMove {403  struct Baz {404    unsigned int n;405  };406 407  struct AP {408    const AP *p;409    const Baz *lp;410  };411 412  class Bar {413  public:414    static Baz _m[];415    static const AP m;416  };417 418  const AP Bar::m = {0, &Bar::_m[0]};419  Baz Bar::_m[] = {{0}};420  const AP m = {&Bar ::m};421}422