From 1ecaa617e73e9c1eeba47b0d12626f0a846a4288 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Fri, 16 Sep 2022 09:17:52 +0200 Subject: [PATCH] [clang][Interp] Handle enums Handle DeclRefExprs of enum types. They are otherwise handled like integers. Differential Revision: https://reviews.llvm.org/D134020 --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 5 ++++ clang/test/AST/Interp/enums-targets.cpp | 18 ++++++++++++ clang/test/AST/Interp/enums.cpp | 50 ++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 clang/test/AST/Interp/enums-targets.cpp create mode 100644 clang/test/AST/Interp/enums.cpp diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 5974678..9264357 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -861,6 +861,11 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) { 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-targets.cpp b/clang/test/AST/Interp/enums-targets.cpp new file mode 100644 index 0000000..81601a2 --- /dev/null +++ b/clang/test/AST/Interp/enums-targets.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple i686-pc-linux -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -triple i686-pc-linux -verify %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -fexperimental-new-constant-interpreter -verify=warn %s +// RUN: %clang_cc1 -triple x86_64-pc-linux -verify=warn %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -verify %s +// RUN: %clang_cc1 -triple hexagon -fexperimental-new-constant-interpreter -verify %s +// RUN: %clang_cc1 -triple hexagon -verify %s + +// expected-no-diagnostics + +/// This test is split out from the rest since the output is target dependent. + +enum E { // warn-warning {{enumeration values exceed range of largest integer}} + E1 = -__LONG_MAX__ -1L, + E2 = __LONG_MAX__ *2UL+1UL +}; + diff --git a/clang/test/AST/Interp/enums.cpp b/clang/test/AST/Interp/enums.cpp new file mode 100644 index 0000000..c4db787 --- /dev/null +++ b/clang/test/AST/Interp/enums.cpp @@ -0,0 +1,50 @@ +// 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, ""); -- 2.7.4