diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -861,6 +861,11 @@ FoundDecl = true; } + } else if (const auto *ECD = dyn_cast(Decl)) { + PrimType T = *classify(ECD->getType()); + + return this->emitConst(T, getIntWidth(ECD->getType()), ECD->getInitVal(), + E); } // References are implemented using pointers, so when we get here, diff --git a/clang/test/AST/Interp/enums.cpp b/clang/test/AST/Interp/enums.cpp new file mode 100644 --- /dev/null +++ b/clang/test/AST/Interp/enums.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -verify=ref %s + +enum class EC : short { + A, B, C +}; +static_assert(static_cast(EC::A) == 0, ""); +static_assert(static_cast(EC::B) == 1, ""); +static_assert(static_cast(EC::C) == 2, ""); +static_assert(sizeof(EC) == sizeof(short), ""); + +constexpr EC ec = EC::C; +static_assert(static_cast(ec) == 2, ""); + +constexpr int N = 12; +constexpr int M = 2; + +enum CE { + ONE = -1, + TWO = 2, + THREE, + FOUR = 4, + FIVE = N + M, + SIX = FIVE + 2, + MAX = __INT_MAX__ * 2U + 1U +}; +static_assert(ONE == -1, ""); +static_assert(THREE == 3, ""); +static_assert(FIVE == 14, ""); +static_assert(SIX == 16, ""); + +constexpr EC testEnums() { + EC e = EC::C; + + e = EC::B; + + EC::B = e; // expected-error{{expression is not assignable}} \ + // ref-error{{expression is not assignable}} + + return e; +} + +constexpr EC getB() { + EC e = EC::C; + e = EC::B; + return e; +} + + +static_assert(getB() == EC::B, ""); + + +enum E { // expected-warning{{enumeration values exceed range of largest integer}} \ + // ref-warning{{enumeration values exceed range of largest integer}} + E1 = -__LONG_MAX__ -1L, + E2 = __LONG_MAX__ *2UL+1UL +};