When reverting a commit it is customary to mention *why* it is getting reverted.

On Mon, Sep 2, 2019 at 2:33 PM Nandor Licker via cfe-commits
<cfe-commits@lists.llvm.org> wrote:
>
> Author: nand
> Date: Mon Sep  2 04:34:47 2019
> New Revision: 370642
>
> URL: http://llvm.org/viewvc/llvm-project?rev=370642&view=rev
> Log:
> Revert [Clang Interpreter] Initial patch for the constexpr interpreter
>
> This reverts r370636 (git commit 8327fed9475a14c3376b4860c75370c730e08f33)
>
> Removed:
>     cfe/trunk/docs/ConstantInterpreter.rst
>     cfe/trunk/include/clang/AST/OptionalDiagnostic.h
>     cfe/trunk/lib/AST/Interp/
>     cfe/trunk/test/AST/Interp/
>     cfe/trunk/utils/TableGen/ClangOpcodesEmitter.cpp
> Modified:
>     cfe/trunk/docs/index.rst
>     cfe/trunk/include/clang/AST/ASTContext.h
>     cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
>     cfe/trunk/include/clang/Basic/LangOptions.def
>     cfe/trunk/include/clang/Driver/Options.td
>     cfe/trunk/lib/AST/ASTContext.cpp
>     cfe/trunk/lib/AST/CMakeLists.txt
>     cfe/trunk/lib/AST/ExprConstant.cpp
>     cfe/trunk/lib/Driver/ToolChains/Clang.cpp
>     cfe/trunk/lib/Frontend/CompilerInvocation.cpp
>     cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp
>     cfe/trunk/test/SemaCXX/constexpr-many-arguments.cpp
>     cfe/trunk/test/SemaCXX/shift.cpp
>     cfe/trunk/utils/TableGen/CMakeLists.txt
>     cfe/trunk/utils/TableGen/TableGen.cpp
>     cfe/trunk/utils/TableGen/TableGenBackends.h
>
> Removed: cfe/trunk/docs/ConstantInterpreter.rst
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ConstantInterpreter.rst?rev=370641&view=auto
> ==============================================================================
> --- cfe/trunk/docs/ConstantInterpreter.rst (original)
> +++ cfe/trunk/docs/ConstantInterpreter.rst (removed)
> @@ -1,194 +0,0 @@
> -====================
> -Constant Interpreter
> -====================
> -
> -.. contents::
> -   :local:
> -
> -Introduction
> -============
> -
> -The constexpr interpreter aims to replace the existing tree evaluator in 
> clang, improving performance on constructs which are executed inefficiently 
> by the evaluator. The interpreter is activated using the following flags:
> -
> -* ``-fexperimental-new-constant-interpreter`` enables the interpreter, 
> falling back to the evaluator for unsupported features
> -* ``-fforce-experimental-new-constant-interpreter`` forces the use of the 
> interpreter, bailing out if an unsupported feature is encountered
> -
> -Bytecode Compilation
> -====================
> -
> -Bytecode compilation is handled in ``ByteCodeStmtGen.h`` for statements and 
> ``ByteCodeExprGen.h`` for expressions. The compiler has two different 
> backends: one to generate bytecode for functions (``ByteCodeEmitter``) and 
> one to directly evaluate expressions as they are compiled, without generating 
> bytecode (``EvalEmitter``). All functions are compiled to bytecode, while 
> toplevel expressions used in constant contexts are directly evaluated since 
> the bytecode would never be reused. This mechanism aims to pave the way 
> towards replacing the evaluator, improving its performance on functions and 
> loops, while being just as fast on single-use toplevel expressions.
> -
> -The interpreter relies on stack-based, strongly-typed opcodes. The glue 
> logic between the code generator, along with the enumeration and description 
> of opcodes, can be found in ``Opcodes.td``. The opcodes are implemented as 
> generic template methods in ``Interp.h`` and instantiated with the relevant 
> primitive types by the interpreter loop or by the evaluating emitter.
> -
> -Primitive Types
> ----------------
> -
> -* ``PT_{U|S}int{8|16|32|64}``
> -
> -  Signed or unsigned integers of a specific bit width, implemented using the 
> ```Integral``` type.
> -
> -* ``PT_{U|S}intFP``
> -
> -  Signed or unsigned integers of an arbitrary, but fixed width used to 
> implement
> -  integral types which are required by the target, but are not supported by 
> the host.
> -  Under the hood, they rely on APValue. The ``Integral`` specialisation for 
> these
> -  types is required by opcodes to share an implementation with fixed 
> integrals.
> -
> -* ``PT_Bool``
> -
> -  Representation for boolean types, essentially a 1-bit unsigned 
> ``Integral``.
> -
> -* ``PT_RealFP``
> -
> -  Arbitrary, but fixed precision floating point numbers. Could be 
> specialised in
> -  the future similarly to integers in order to improve floating point 
> performance.
> -
> -* ``PT_Ptr``
> -
> -  Pointer type, defined in ``"Pointer.h"``.
> -
> -* ``PT_FnPtr``
> -
> -  Function pointer type, can also be a null function pointer. Defined in 
> ``"Pointer.h"``.
> -
> -* ``PT_MemPtr``
> -
> -  Member pointer type, can also be a null member pointer. Defined in 
> ``"Pointer.h"``
> -
> -Composite types
> ----------------
> -
> -The interpreter distinguishes two kinds of composite types: arrays and 
> records. Unions are represented as records, except a single field can be 
> marked as active. The contents of inactive fields are kept until they
> -are reactivated and overwritten.
> -
> -
> -Bytecode Execution
> -==================
> -
> -Bytecode is executed using a stack-based interpreter. The execution context 
> consists of an ``InterpStack``, along with a chain of ``InterpFrame`` objects 
> storing the call frames. Frames are built by call instructions and destroyed 
> by return instructions. They perform one allocation to reserve space for all 
> locals in a single block. These objects store all the required information to 
> emit stack traces whenever evaluation fails.
> -
> -Memory Organisation
> -===================
> -
> -Memory management in the interpreter relies on 3 data structures: ``Block``
> -object which store the data and associated inline metadata, ``Pointer`` 
> objects
> -which refer to or into blocks, and ``Descriptor`` structures which describe
> -blocks and subobjects nested inside blocks.
> -
> -Blocks
> -------
> -
> -Blocks contain data interleaved with metadata. They are allocated either 
> statically
> -in the code generator (globals, static members, dummy parameter values etc.) 
> or
> -dynamically in the interpreter, when creating the frame containing the local 
> variables
> -of a function. Blocks are associated with a descriptor that characterises 
> the entire
> -allocation, along with a few additional attributes:
> -
> -* ``IsStatic`` indicates whether the block has static duration in the 
> interpreter, i.e. it is not a local in a frame.
> -
> -* ``IsExtern`` indicates that the block was created for an extern and the 
> storage cannot be read or written.
> -
> -* ``DeclID`` identifies each global declaration (it is set to an invalid and 
> irrelevant value for locals) in order to prevent illegal writes and reads 
> involving globals and temporaries with static storage duration.
> -
> -Static blocks are never deallocated, but local ones might be deallocated 
> even when there are live pointers to them. Pointers are only valid as long as 
> the blocks they point to are valid, so a block with pointers to it whose 
> lifetime ends is kept alive until all pointers to it go out of scope. Since 
> the frame is destroyed on function exit, such blocks are turned into a 
> ``DeadBlock`` and copied to storage managed by the interpreter itself, not 
> the frame. Reads and writes to these blocks are illegal and cause an 
> appropriate diagnostic to be emitted. When the last pointer goes out of 
> scope, dead blocks are also deallocated.
> -
> -The lifetime of blocks is managed through 3 methods stored in the descriptor 
> of the block:
> -
> -* **CtorFn**: initializes the metadata which is store in the block, 
> alongside actual data. Invokes the default constructors of objects which are 
> not trivial (``Pointer``, ``RealFP``, etc.)
> -* **DtorFn**: invokes the destructors of non-trivial objects.
> -* **MoveFn**: moves a block to dead storage.
> -
> -Non-static blocks track all the pointers into them through an intrusive 
> doubly-linked list, this is required in order to adjust all pointers when 
> transforming a block into a dead block.
> -
> -Descriptors
> ------------
> -
> -Descriptor are generated at bytecode compilation time and contain 
> information required to determine if a particular memory access is allowed in 
> constexpr. Even though there is a single descriptor object, it encodes 
> information for several kinds of objects:
> -
> -* **Primitives**
> -
> -  A block containing a primitive reserved storage only for the primitive.
> -
> -* **Arrays of primitives**
> -
> -  An array of primitives contains a pointer to an ``InitMap`` storage as its 
> first field: the initialisation map is a bit map indicating all elements of 
> the array which were initialised. If the pointer is null, no elements were 
> initialised, while a value of ``(InitMap)-1`` indicates that the object was 
> fully initialised. when all fields are initialised, the map is deallocated 
> and replaced with that token.
> -
> -  Array elements are stored sequentially, without padding, after the pointer 
> to the map.
> -
> -* **Arrays of composites and records**
> -
> -  Each element in an array of composites is preceded by an 
> ``InlineDescriptor``. Descriptors and elements are stored sequentially in the 
> block. Records are laid out identically to arrays of composites: each field 
> and base class is preceded by an inline descriptor. The ``InlineDescriptor`` 
> has the following field:
> -
> - * **Offset**: byte offset into the array or record, used to step back to 
> the parent array or record.
> - * **IsConst**: flag indicating if the field is const-qualified.
> - * **IsInitialized**: flag indicating whether the field or element was 
> initialized. For non-primitive fields, this is only relevant for base classes.
> - * **IsBase**: flag indicating whether the record is a base class. In that 
> case, the offset can be used to identify the derived class.
> - * **IsActive**: indicates if the field is the active field of a union.
> - * **IsMutable**: indicates if the field is marked as mutable.
> -
> -Inline descriptors are filled in by the `CtorFn` of blocks, which leaves 
> storage in an uninitialised, but valid state.
> -
> -Pointers
> ---------
> -
> -Pointers track a ``Pointee``, the block to which they point or ``nullptr`` 
> for null pointers, along with a ``Base`` and an ``Offset``. The base 
> identifies the innermost field, while the offset points to an array element 
> relative to the base (including one-past-end pointers). Most subobject the 
> pointer points to in block, while the offset identifies the array element the 
> pointer points to. These two fields allow all pointers to be uniquely 
> identified and disambiguated.
> -
> -As an example, consider the following structure:
> -
> -.. code-block:: c
> -
> -    struct A {
> -        struct B {
> -            int x;
> -            int y;
> -        } b;
> -        struct C {
> -            int a;
> -            int b;
> -        } c[2];
> -        int z;
> -    };
> -    constexpr A a;
> -
> -On the target, ``&a`` and ``&a.b.x`` are equal. So are ``&a.c[0]`` and 
> ``&a.c[0].a``. In the interpreter, all these pointers must be distinguished 
> since the are all allowed to address distinct range of memory.
> -
> -In the interpreter, the object would require 240 bytes of storage and would 
> have its field interleaved with metadata. The pointers which can be derived 
> to the object are illustrated in the following diagram:
> -
> -::
> -
> -      0   16  32  40  56  64  80  96  112 120 136 144 160 176 184 200 208 
> 224 240
> -  
> +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
> -  + B | D | D | x | D | y | D | D | D | a | D | b | D | D | a | D | b | D | 
> z |
> -  
> +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
> -      ^   ^   ^       ^       ^   ^   ^       ^       ^   ^       ^       ^
> -      |   |   |       |       |   |   |   &a.c[0].b   |   |   &a.c[1].b   |
> -      a   |&a.b.x   &a.y    &a.c  |&a.c[0].a          |&a.c[1].a          |
> -        &a.b                   &a.c[0]            &a.c[1]               &a.z
> -
> -The ``Base`` offset of all pointers points to the start of a field or an 
> array and is preceded by an inline descriptor (unless ``Base == 0``, pointing 
> to the root). All the relevant attributes can be read from either the inline 
> descriptor or the descriptor of the block.
> -
> -Array elements are identified by the ``Offset`` field of pointers, pointing 
> to past the inline descriptors for composites and before the actual data in 
> the case of primitive arrays. The ``Offset`` points to the offset where 
> primitives can be read from. As an example, ``a.c + 1`` would have the same 
> base as ``a.c`` since it is an element of ``a.c``, but its offset would point 
> to ``&a.c[1]``. The ``*`` operation narrows the scope of the pointer, 
> adjusting the base to ``&a.c[1]``. The reverse operator, ``&``, expands the 
> scope of ``&a.c[1]``, turning it into ``a.c + 1``. When a one-past-end 
> pointer is narrowed, its offset is set to ``-1`` to indicate that it is an 
> invalid value (expanding returns the past-the-end pointer). As a special 
> case, narrowing ``&a.c`` results in ``&a.c[0]``. The `narrow` and `expand` 
> methods can be used to follow the chain of equivalent pointers.
> -
> -TODO
> -====
> -
> -Missing Language Features
> --------------------------
> -
> -* Definition of externs must override previous declaration
> -* Changing the active field of unions
> -* Union copy constructors
> -* ``typeid``
> -* ``volatile``
> -* ``__builtin_constant_p``
> -* ``std::initializer_list``
> -* lambdas
> -* range-based for loops
> -* ``vector_size``
> -* ``dynamic_cast``
> -
> -Known Bugs
> -----------
> -
> -* Pointer comparison for equality needs to narrow/expand pointers
> -* If execution fails, memory storing APInts and APFloats is leaked when the 
> stack is cleared
>
> Modified: cfe/trunk/docs/index.rst
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/index.rst?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/docs/index.rst (original)
> +++ cfe/trunk/docs/index.rst Mon Sep  2 04:34:47 2019
> @@ -88,7 +88,6 @@ Design Documents
>     PCHInternals
>     ItaniumMangleAbiTags
>     HardwareAssistedAddressSanitizerDesign.rst
> -   ConstantInterpreter
>
>
>  Indices and tables
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Mon Sep  2 04:34:47 2019
> @@ -139,12 +139,6 @@ class FullComment;
>
>  } // namespace comments
>
> -namespace interp {
> -
> -class Context;
> -
> -} // namespace interp
> -
>  struct TypeInfo {
>    uint64_t Width = 0;
>    unsigned Align = 0;
> @@ -570,7 +564,6 @@ private:
>    const TargetInfo *Target = nullptr;
>    const TargetInfo *AuxTarget = nullptr;
>    clang::PrintingPolicy PrintingPolicy;
> -  std::unique_ptr<interp::Context> InterpContext;
>
>  public:
>    IdentifierTable &Idents;
> @@ -580,9 +573,6 @@ public:
>    IntrusiveRefCntPtr<ExternalASTSource> ExternalSource;
>    ASTMutationListener *Listener = nullptr;
>
> -  /// Returns the clang bytecode interpreter context.
> -  interp::Context &getInterpContext();
> -
>    /// Container for either a single DynTypedNode or for an ArrayRef to
>    /// DynTypedNode. For use with ParentMap.
>    class DynTypedNodeList {
>
> Removed: cfe/trunk/include/clang/AST/OptionalDiagnostic.h
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OptionalDiagnostic.h?rev=370641&view=auto
> ==============================================================================
> --- cfe/trunk/include/clang/AST/OptionalDiagnostic.h (original)
> +++ cfe/trunk/include/clang/AST/OptionalDiagnostic.h (removed)
> @@ -1,78 +0,0 @@
> -//===- OptionalDiagnostic.h - An optional diagnostic ------------*- C++ 
> -*-===//
> -//
> -// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
> Exceptions.
> -// See https://llvm.org/LICENSE.txt for license information.
> -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
> -//
> -//===----------------------------------------------------------------------===//
> -//
> -/// \file
> -/// Implements a partial diagnostic which may not be emitted.
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#ifndef LLVM_CLANG_AST_OPTIONALDIAGNOSTIC_H
> -#define LLVM_CLANG_AST_OPTIONALDIAGNOSTIC_H
> -
> -#include "clang/AST/APValue.h"
> -#include "clang/Basic/PartialDiagnostic.h"
> -#include "llvm/ADT/APFloat.h"
> -#include "llvm/ADT/APSInt.h"
> -#include "llvm/ADT/SmallVector.h"
> -#include "llvm/ADT/StringRef.h"
> -
> -namespace clang {
> -
> -/// A partial diagnostic which we might know in advance that we are not going
> -/// to emit.
> -class OptionalDiagnostic {
> -  PartialDiagnostic *Diag;
> -
> -public:
> -  explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr) : 
> Diag(Diag) {}
> -
> -  template <typename T> OptionalDiagnostic &operator<<(const T &v) {
> -    if (Diag)
> -      *Diag << v;
> -    return *this;
> -  }
> -
> -  OptionalDiagnostic &operator<<(const llvm::APSInt &I) {
> -    if (Diag) {
> -      SmallVector<char, 32> Buffer;
> -      I.toString(Buffer);
> -      *Diag << StringRef(Buffer.data(), Buffer.size());
> -    }
> -    return *this;
> -  }
> -
> -  OptionalDiagnostic &operator<<(const llvm::APFloat &F) {
> -    if (Diag) {
> -      // FIXME: Force the precision of the source value down so we don't
> -      // print digits which are usually useless (we don't really care here if
> -      // we truncate a digit by accident in edge cases).  Ideally,
> -      // APFloat::toString would automatically print the shortest
> -      // representation which rounds to the correct value, but it's a bit
> -      // tricky to implement. Could use std::to_chars.
> -      unsigned precision = 
> llvm::APFloat::semanticsPrecision(F.getSemantics());
> -      precision = (precision * 59 + 195) / 196;
> -      SmallVector<char, 32> Buffer;
> -      F.toString(Buffer, precision);
> -      *Diag << StringRef(Buffer.data(), Buffer.size());
> -    }
> -    return *this;
> -  }
> -
> -  OptionalDiagnostic &operator<<(const APFixedPoint &FX) {
> -    if (Diag) {
> -      SmallVector<char, 32> Buffer;
> -      FX.toString(Buffer);
> -      *Diag << StringRef(Buffer.data(), Buffer.size());
> -    }
> -    return *this;
> -  }
> -};
> -
> -} // namespace clang
> -
> -#endif
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticASTKinds.td Mon Sep  2 04:34:47 
> 2019
> @@ -228,8 +228,6 @@ def note_constexpr_bit_cast_invalid_subt
>  def note_constexpr_bit_cast_indet_dest : Note<
>    "indeterminate value can only initialize an object of type 'unsigned char'"
>    "%select{, 'char',|}1 or 'std::byte'; %0 is invalid">;
> -def err_experimental_clang_interp_failed : Error<
> -  "the experimental clang interpreter failed to evaluate an expression">;
>
>  def warn_integer_constant_overflow : Warning<
>    "overflow in expression; result is %0 with type %1">,
>
> Modified: cfe/trunk/include/clang/Basic/LangOptions.def
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/LangOptions.def (original)
> +++ cfe/trunk/include/clang/Basic/LangOptions.def Mon Sep  2 04:34:47 2019
> @@ -288,10 +288,6 @@ BENIGN_LANGOPT(ConstexprCallDepth, 32, 5
>                 "maximum constexpr call depth")
>  BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576,
>                 "maximum constexpr evaluation steps")
> -BENIGN_LANGOPT(EnableNewConstInterp, 1, 0,
> -               "enable the experimental new constant interpreter")
> -BENIGN_LANGOPT(ForceNewConstInterp, 1, 0,
> -               "force the use of the experimental new constant interpreter")
>  BENIGN_LANGOPT(BracketDepth, 32, 256,
>                 "maximum bracket nesting depth")
>  BENIGN_LANGOPT(NumLargeByValueCopy, 32, 0,
>
> Modified: cfe/trunk/include/clang/Driver/Options.td
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Driver/Options.td (original)
> +++ cfe/trunk/include/clang/Driver/Options.td Mon Sep  2 04:34:47 2019
> @@ -838,10 +838,6 @@ def fconstant_cfstrings : Flag<["-"], "f
>  def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, 
> Group<f_Group>;
>  def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>;
>  def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>;
> -def fexperimental_new_constant_interpreter : Flag<["-"], 
> "fexperimental-new-constant-interpreter">, Group<f_Group>,
> -  HelpText<"Enable the experimental new constant interpreter">, 
> Flags<[CC1Option]>;
> -def fforce_experimental_new_constant_interpreter : Flag<["-"], 
> "fforce-experimental-new-constant-interpreter">, Group<f_Group>,
> -  HelpText<"Force the use of the experimental new constant interpreter, 
> failing on missing features">, Flags<[CC1Option]>;
>  def fconstexpr_backtrace_limit_EQ : Joined<["-"], 
> "fconstexpr-backtrace-limit=">,
>                                      Group<f_Group>;
>  def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, 
> Group<f_clang_Group>, Flags<[NoArgumentUnused, CoreOption]>,
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Mon Sep  2 04:34:47 2019
> @@ -12,7 +12,6 @@
>
>  #include "clang/AST/ASTContext.h"
>  #include "CXXABI.h"
> -#include "Interp/Context.h"
>  #include "clang/AST/APValue.h"
>  #include "clang/AST/ASTMutationListener.h"
>  #include "clang/AST/ASTTypeTraits.h"
> @@ -784,13 +783,6 @@ CXXABI *ASTContext::createCXXABI(const T
>    llvm_unreachable("Invalid CXXABI type!");
>  }
>
> -interp::Context &ASTContext::getInterpContext() {
> -  if (!InterpContext) {
> -    InterpContext.reset(new interp::Context(*this));
> -  }
> -  return *InterpContext.get();
> -}
> -
>  static const LangASMap *getAddressSpaceMap(const TargetInfo &T,
>                                             const LangOptions &LOpts) {
>    if (LOpts.FakeAddressSpaceMap) {
>
> Modified: cfe/trunk/lib/AST/CMakeLists.txt
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/CMakeLists.txt (original)
> +++ cfe/trunk/lib/AST/CMakeLists.txt Mon Sep  2 04:34:47 2019
> @@ -4,8 +4,6 @@ set(LLVM_LINK_COMPONENTS
>    Support
>    )
>
> -add_subdirectory(Interp)
> -
>  add_clang_library(clangAST
>    APValue.cpp
>    ASTConsumer.cpp
> @@ -83,6 +81,5 @@ add_clang_library(clangAST
>
>    LINK_LIBS
>    clangBasic
> -  clangInterp
>    clangLex
>    )
>
> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> +++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Sep  2 04:34:47 2019
> @@ -32,11 +32,6 @@
>  //
>  
> //===----------------------------------------------------------------------===//
>
> -#include <cstring>
> -#include <functional>
> -#include "Interp/Context.h"
> -#include "Interp/Frame.h"
> -#include "Interp/State.h"
>  #include "clang/AST/APValue.h"
>  #include "clang/AST/ASTContext.h"
>  #include "clang/AST/ASTDiagnostic.h"
> @@ -46,7 +41,6 @@
>  #include "clang/AST/CurrentSourceLocExprScope.h"
>  #include "clang/AST/Expr.h"
>  #include "clang/AST/OSLog.h"
> -#include "clang/AST/OptionalDiagnostic.h"
>  #include "clang/AST/RecordLayout.h"
>  #include "clang/AST/StmtVisitor.h"
>  #include "clang/AST/TypeLoc.h"
> @@ -57,6 +51,8 @@
>  #include "llvm/ADT/SmallBitVector.h"
>  #include "llvm/Support/SaveAndRestore.h"
>  #include "llvm/Support/raw_ostream.h"
> +#include <cstring>
> +#include <functional>
>
>  #define DEBUG_TYPE "exprconstant"
>
> @@ -70,8 +66,8 @@ static bool IsGlobalLValue(APValue::LVal
>
>  namespace {
>    struct LValue;
> -  class CallStackFrame;
> -  class EvalInfo;
> +  struct CallStackFrame;
> +  struct EvalInfo;
>
>    using SourceLocExprScopeGuard =
>        CurrentSourceLocExprScope::SourceLocExprScopeGuard;
> @@ -226,6 +222,12 @@ namespace {
>      return MostDerivedLength;
>    }
>
> +  // The order of this enum is important for diagnostics.
> +  enum CheckSubobjectKind {
> +    CSK_Base, CSK_Derived, CSK_Field, CSK_ArrayToPointer, CSK_ArrayIndex,
> +    CSK_Real, CSK_Imag
> +  };
> +
>    /// A path from a glvalue to a subobject of that glvalue.
>    struct SubobjectDesignator {
>      /// True if the subobject was named in a manner not supported by C++11. 
> Such
> @@ -478,8 +480,7 @@ namespace {
>    };
>
>    /// A stack frame in the constexpr call stack.
> -  class CallStackFrame : public interp::Frame {
> -  public:
> +  struct CallStackFrame {
>      EvalInfo &Info;
>
>      /// Parent - The caller of this stack frame.
> @@ -573,12 +574,6 @@ namespace {
>      }
>
>      APValue &createTemporary(const void *Key, bool IsLifetimeExtended);
> -
> -    void describe(llvm::raw_ostream &OS) override;
> -
> -    Frame *getCaller() const override { return Caller; }
> -    SourceLocation getCallLocation() const override { return CallLoc; }
> -    const FunctionDecl *getCallee() const override { return Callee; }
>    };
>
>    /// Temporarily override 'this'.
> @@ -597,6 +592,59 @@ namespace {
>      const LValue *OldThis;
>    };
>
> +  /// A partial diagnostic which we might know in advance that we are not 
> going
> +  /// to emit.
> +  class OptionalDiagnostic {
> +    PartialDiagnostic *Diag;
> +
> +  public:
> +    explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr)
> +      : Diag(Diag) {}
> +
> +    template<typename T>
> +    OptionalDiagnostic &operator<<(const T &v) {
> +      if (Diag)
> +        *Diag << v;
> +      return *this;
> +    }
> +
> +    OptionalDiagnostic &operator<<(const APSInt &I) {
> +      if (Diag) {
> +        SmallVector<char, 32> Buffer;
> +        I.toString(Buffer);
> +        *Diag << StringRef(Buffer.data(), Buffer.size());
> +      }
> +      return *this;
> +    }
> +
> +    OptionalDiagnostic &operator<<(const APFloat &F) {
> +      if (Diag) {
> +        // FIXME: Force the precision of the source value down so we don't
> +        // print digits which are usually useless (we don't really care here 
> if
> +        // we truncate a digit by accident in edge cases).  Ideally,
> +        // APFloat::toString would automatically print the shortest
> +        // representation which rounds to the correct value, but it's a bit
> +        // tricky to implement.
> +        unsigned precision =
> +            llvm::APFloat::semanticsPrecision(F.getSemantics());
> +        precision = (precision * 59 + 195) / 196;
> +        SmallVector<char, 32> Buffer;
> +        F.toString(Buffer, precision);
> +        *Diag << StringRef(Buffer.data(), Buffer.size());
> +      }
> +      return *this;
> +    }
> +
> +    OptionalDiagnostic &operator<<(const APFixedPoint &FX) {
> +      if (Diag) {
> +        SmallVector<char, 32> Buffer;
> +        FX.toString(Buffer);
> +        *Diag << StringRef(Buffer.data(), Buffer.size());
> +      }
> +      return *this;
> +    }
> +  };
> +
>    /// A cleanup, and a flag indicating whether it is lifetime-extended.
>    class Cleanup {
>      llvm::PointerIntPair<APValue*, 1, bool> Value;
> @@ -659,8 +707,7 @@ namespace {
>    /// rules.  For example, the RHS of (0 && foo()) is not evaluated.  We can
>    /// evaluate the expression regardless of what the RHS is, but C only 
> allows
>    /// certain things in certain situations.
> -  class EvalInfo : public interp::State {
> -  public:
> +  struct EvalInfo {
>      ASTContext &Ctx;
>
>      /// EvalStatus - Contains information about the evaluation.
> @@ -680,13 +727,6 @@ namespace {
>      /// we will evaluate.
>      unsigned StepsLeft;
>
> -    /// Force the use of the experimental new constant interpreter, bailing 
> out
> -    /// with an error if a feature is not supported.
> -    bool ForceNewConstInterp;
> -
> -    /// Enable the experimental new constant interpreter.
> -    bool EnableNewConstInterp;
> -
>      /// BottomFrame - The frame in which evaluation started. This must be
>      /// initialized after CurrentCall and CallStackDepth.
>      CallStackFrame BottomFrame;
> @@ -797,7 +837,7 @@ namespace {
>
>      /// Are we checking whether the expression is a potential constant
>      /// expression?
> -    bool checkingPotentialConstantExpression() const override {
> +    bool checkingPotentialConstantExpression() const {
>        return EvalMode == EM_PotentialConstantExpression ||
>               EvalMode == EM_PotentialConstantExpressionUnevaluated;
>      }
> @@ -805,28 +845,25 @@ namespace {
>      /// Are we checking an expression for overflow?
>      // FIXME: We should check for any kind of undefined or suspicious 
> behavior
>      // in such constructs, not just overflow.
> -    bool checkingForOverflow() const override {
> -      return EvalMode == EM_EvaluateForOverflow;
> -    }
> +    bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; }
>
>      EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode)
> -        : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), 
> CurrentCall(nullptr),
> -          CallStackDepth(0), NextCallIndex(1),
> -          StepsLeft(getLangOpts().ConstexprStepLimit),
> -          ForceNewConstInterp(getLangOpts().ForceNewConstInterp),
> -          EnableNewConstInterp(ForceNewConstInterp ||
> -                               getLangOpts().EnableNewConstInterp),
> -          BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
> -          EvaluatingDecl((const ValueDecl *)nullptr),
> -          EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
> -          HasFoldFailureDiagnostic(false), InConstantContext(false),
> -          EvalMode(Mode) {}
> +      : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), 
> CurrentCall(nullptr),
> +        CallStackDepth(0), NextCallIndex(1),
> +        StepsLeft(getLangOpts().ConstexprStepLimit),
> +        BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
> +        EvaluatingDecl((const ValueDecl *)nullptr),
> +        EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
> +        HasFoldFailureDiagnostic(false),
> +        InConstantContext(false), EvalMode(Mode) {}
>
>      void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
>        EvaluatingDecl = Base;
>        EvaluatingDeclValue = &Value;
>      }
>
> +    const LangOptions &getLangOpts() const { return Ctx.getLangOpts(); }
> +
>      bool CheckCallLimit(SourceLocation Loc) {
>        // Don't perform any constexpr calls (other than the call we're 
> checking)
>        // when checking a potential constant expression.
> @@ -870,52 +907,118 @@ namespace {
>      }
>
>    private:
> -    interp::Frame *getCurrentFrame() override { return CurrentCall; }
> -    const interp::Frame *getBottomFrame() const override { return 
> &BottomFrame; }
> +    /// Add a diagnostic to the diagnostics list.
> +    PartialDiagnostic &addDiag(SourceLocation Loc, diag::kind DiagId) {
> +      PartialDiagnostic PD(DiagId, Ctx.getDiagAllocator());
> +      EvalStatus.Diag->push_back(std::make_pair(Loc, PD));
> +      return EvalStatus.Diag->back().second;
> +    }
>
> -    bool hasActiveDiagnostic() override { return HasActiveDiagnostic; }
> -    void setActiveDiagnostic(bool Flag) override { HasActiveDiagnostic = 
> Flag; }
> +    /// Add notes containing a call stack to the current point of evaluation.
> +    void addCallStack(unsigned Limit);
>
> -    void setFoldFailureDiagnostic(bool Flag) override {
> -      HasFoldFailureDiagnostic = Flag;
> -    }
> +  private:
> +    OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId,
> +                            unsigned ExtraNotes, bool IsCCEDiag) {
>
> -    Expr::EvalStatus &getEvalStatus() const override { return EvalStatus; }
> -
> -    ASTContext &getCtx() const override { return Ctx; }
> -
> -    // If we have a prior diagnostic, it will be noting that the expression
> -    // isn't a constant expression. This diagnostic is more important,
> -    // unless we require this evaluation to produce a constant expression.
> -    //
> -    // FIXME: We might want to show both diagnostics to the user in
> -    // EM_ConstantFold mode.
> -    bool hasPriorDiagnostic() override {
> -      if (!EvalStatus.Diag->empty()) {
> -        switch (EvalMode) {
> -        case EM_ConstantFold:
> -        case EM_IgnoreSideEffects:
> -        case EM_EvaluateForOverflow:
> -          if (!HasFoldFailureDiagnostic)
> -            break;
> -          // We've already failed to fold something. Keep that diagnostic.
> -          LLVM_FALLTHROUGH;
> -        case EM_ConstantExpression:
> -        case EM_PotentialConstantExpression:
> -        case EM_ConstantExpressionUnevaluated:
> -        case EM_PotentialConstantExpressionUnevaluated:
> -          setActiveDiagnostic(false);
> -          return true;
> +      if (EvalStatus.Diag) {
> +        // If we have a prior diagnostic, it will be noting that the 
> expression
> +        // isn't a constant expression. This diagnostic is more important,
> +        // unless we require this evaluation to produce a constant 
> expression.
> +        //
> +        // FIXME: We might want to show both diagnostics to the user in
> +        // EM_ConstantFold mode.
> +        if (!EvalStatus.Diag->empty()) {
> +          switch (EvalMode) {
> +          case EM_ConstantFold:
> +          case EM_IgnoreSideEffects:
> +          case EM_EvaluateForOverflow:
> +            if (!HasFoldFailureDiagnostic)
> +              break;
> +            // We've already failed to fold something. Keep that diagnostic.
> +            LLVM_FALLTHROUGH;
> +          case EM_ConstantExpression:
> +          case EM_PotentialConstantExpression:
> +          case EM_ConstantExpressionUnevaluated:
> +          case EM_PotentialConstantExpressionUnevaluated:
> +            HasActiveDiagnostic = false;
> +            return OptionalDiagnostic();
> +          }
>          }
> +
> +        unsigned CallStackNotes = CallStackDepth - 1;
> +        unsigned Limit = Ctx.getDiagnostics().getConstexprBacktraceLimit();
> +        if (Limit)
> +          CallStackNotes = std::min(CallStackNotes, Limit + 1);
> +        if (checkingPotentialConstantExpression())
> +          CallStackNotes = 0;
> +
> +        HasActiveDiagnostic = true;
> +        HasFoldFailureDiagnostic = !IsCCEDiag;
> +        EvalStatus.Diag->clear();
> +        EvalStatus.Diag->reserve(1 + ExtraNotes + CallStackNotes);
> +        addDiag(Loc, DiagId);
> +        if (!checkingPotentialConstantExpression())
> +          addCallStack(Limit);
> +        return OptionalDiagnostic(&(*EvalStatus.Diag)[0].second);
>        }
> -      return false;
> +      HasActiveDiagnostic = false;
> +      return OptionalDiagnostic();
> +    }
> +  public:
> +    // Diagnose that the evaluation could not be folded (FF => FoldFailure)
> +    OptionalDiagnostic
> +    FFDiag(SourceLocation Loc,
> +          diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
> +          unsigned ExtraNotes = 0) {
> +      return Diag(Loc, DiagId, ExtraNotes, false);
> +    }
> +
> +    OptionalDiagnostic FFDiag(const Expr *E, diag::kind DiagId
> +                              = diag::note_invalid_subexpr_in_const_expr,
> +                            unsigned ExtraNotes = 0) {
> +      if (EvalStatus.Diag)
> +        return Diag(E->getExprLoc(), DiagId, ExtraNotes, /*IsCCEDiag*/false);
> +      HasActiveDiagnostic = false;
> +      return OptionalDiagnostic();
>      }
>
> -    unsigned getCallStackDepth() override {
> -      return CallStackDepth;
> +    /// Diagnose that the evaluation does not produce a C++11 core constant
> +    /// expression.
> +    ///
> +    /// FIXME: Stop evaluating if we're in EM_ConstantExpression or
> +    /// EM_PotentialConstantExpression mode and we produce one of these.
> +    OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId
> +                                 = diag::note_invalid_subexpr_in_const_expr,
> +                               unsigned ExtraNotes = 0) {
> +      // Don't override a previous diagnostic. Don't bother collecting
> +      // diagnostics if we're evaluating for overflow.
> +      if (!EvalStatus.Diag || !EvalStatus.Diag->empty()) {
> +        HasActiveDiagnostic = false;
> +        return OptionalDiagnostic();
> +      }
> +      return Diag(Loc, DiagId, ExtraNotes, true);
> +    }
> +    OptionalDiagnostic CCEDiag(const Expr *E, diag::kind DiagId
> +                                 = diag::note_invalid_subexpr_in_const_expr,
> +                               unsigned ExtraNotes = 0) {
> +      return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes);
> +    }
> +    /// Add a note to a prior diagnostic.
> +    OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId) {
> +      if (!HasActiveDiagnostic)
> +        return OptionalDiagnostic();
> +      return OptionalDiagnostic(&addDiag(Loc, DiagId));
> +    }
> +
> +    /// Add a stack of notes to a prior diagnostic.
> +    void addNotes(ArrayRef<PartialDiagnosticAt> Diags) {
> +      if (HasActiveDiagnostic) {
> +        EvalStatus.Diag->insert(EvalStatus.Diag->end(),
> +                                Diags.begin(), Diags.end());
> +      }
>      }
>
> -  public:
>      /// Should we continue evaluation after encountering a side-effect that 
> we
>      /// couldn't model?
>      bool keepEvaluatingAfterSideEffect() {
> @@ -961,14 +1064,14 @@ namespace {
>      /// Note that we hit something that was technically undefined behavior, 
> but
>      /// that we can evaluate past it (such as signed overflow or 
> floating-point
>      /// division by zero.)
> -    bool noteUndefinedBehavior() override {
> +    bool noteUndefinedBehavior() {
>        EvalStatus.HasUndefinedBehavior = true;
>        return keepEvaluatingAfterUndefinedBehavior();
>      }
>
>      /// Should we continue evaluation as much as possible after encountering 
> a
>      /// construct which can't be reduced to a value?
> -    bool keepEvaluatingAfterFailure() const override {
> +    bool keepEvaluatingAfterFailure() {
>        if (!StepsLeft)
>          return false;
>
> @@ -1218,6 +1321,62 @@ APValue &CallStackFrame::createTemporary
>    return Result;
>  }
>
> +static void describeCall(CallStackFrame *Frame, raw_ostream &Out);
> +
> +void EvalInfo::addCallStack(unsigned Limit) {
> +  // Determine which calls to skip, if any.
> +  unsigned ActiveCalls = CallStackDepth - 1;
> +  unsigned SkipStart = ActiveCalls, SkipEnd = SkipStart;
> +  if (Limit && Limit < ActiveCalls) {
> +    SkipStart = Limit / 2 + Limit % 2;
> +    SkipEnd = ActiveCalls - Limit / 2;
> +  }
> +
> +  // Walk the call stack and add the diagnostics.
> +  unsigned CallIdx = 0;
> +  for (CallStackFrame *Frame = CurrentCall; Frame != &BottomFrame;
> +       Frame = Frame->Caller, ++CallIdx) {
> +    // Skip this call?
> +    if (CallIdx >= SkipStart && CallIdx < SkipEnd) {
> +      if (CallIdx == SkipStart) {
> +        // Note that we're skipping calls.
> +        addDiag(Frame->CallLoc, diag::note_constexpr_calls_suppressed)
> +          << unsigned(ActiveCalls - Limit);
> +      }
> +      continue;
> +    }
> +
> +    // Use a different note for an inheriting constructor, because from the
> +    // user's perspective it's not really a function at all.
> +    if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Frame->Callee)) {
> +      if (CD->isInheritingConstructor()) {
> +        addDiag(Frame->CallLoc, 
> diag::note_constexpr_inherited_ctor_call_here)
> +          << CD->getParent();
> +        continue;
> +      }
> +    }
> +
> +    SmallVector<char, 128> Buffer;
> +    llvm::raw_svector_ostream Out(Buffer);
> +    describeCall(Frame, Out);
> +    addDiag(Frame->CallLoc, diag::note_constexpr_call_here) << Out.str();
> +  }
> +}
> +
> +/// Kinds of access we can perform on an object, for diagnostics. Note that
> +/// we consider a member function call to be a kind of access, even though
> +/// it is not formally an access of the object, because it has (largely) the
> +/// same set of semantic restrictions.
> +enum AccessKinds {
> +  AK_Read,
> +  AK_Assign,
> +  AK_Increment,
> +  AK_Decrement,
> +  AK_MemberCall,
> +  AK_DynamicCast,
> +  AK_TypeId,
> +};
> +
>  static bool isModification(AccessKinds AK) {
>    switch (AK) {
>    case AK_Read:
> @@ -1585,36 +1744,36 @@ static void negateAsSigned(APSInt &Int)
>  }
>
>  /// Produce a string describing the given constexpr call.
> -void CallStackFrame::describe(raw_ostream &Out) {
> +static void describeCall(CallStackFrame *Frame, raw_ostream &Out) {
>    unsigned ArgIndex = 0;
> -  bool IsMemberCall = isa<CXXMethodDecl>(Callee) &&
> -                      !isa<CXXConstructorDecl>(Callee) &&
> -                      cast<CXXMethodDecl>(Callee)->isInstance();
> +  bool IsMemberCall = isa<CXXMethodDecl>(Frame->Callee) &&
> +                      !isa<CXXConstructorDecl>(Frame->Callee) &&
> +                      cast<CXXMethodDecl>(Frame->Callee)->isInstance();
>
>    if (!IsMemberCall)
> -    Out << *Callee << '(';
> +    Out << *Frame->Callee << '(';
>
> -  if (This && IsMemberCall) {
> +  if (Frame->This && IsMemberCall) {
>      APValue Val;
> -    This->moveInto(Val);
> -    Val.printPretty(Out, Info.Ctx,
> -                    This->Designator.MostDerivedType);
> +    Frame->This->moveInto(Val);
> +    Val.printPretty(Out, Frame->Info.Ctx,
> +                    Frame->This->Designator.MostDerivedType);
>      // FIXME: Add parens around Val if needed.
> -    Out << "->" << *Callee << '(';
> +    Out << "->" << *Frame->Callee << '(';
>      IsMemberCall = false;
>    }
>
> -  for (FunctionDecl::param_const_iterator I = Callee->param_begin(),
> -       E = Callee->param_end(); I != E; ++I, ++ArgIndex) {
> +  for (FunctionDecl::param_const_iterator I = Frame->Callee->param_begin(),
> +       E = Frame->Callee->param_end(); I != E; ++I, ++ArgIndex) {
>      if (ArgIndex > (unsigned)IsMemberCall)
>        Out << ", ";
>
>      const ParmVarDecl *Param = *I;
> -    const APValue &Arg = Arguments[ArgIndex];
> -    Arg.printPretty(Out, Info.Ctx, Param->getType());
> +    const APValue &Arg = Frame->Arguments[ArgIndex];
> +    Arg.printPretty(Out, Frame->Info.Ctx, Param->getType());
>
>      if (ArgIndex == 0 && IsMemberCall)
> -      Out << "->" << *Callee << '(';
> +      Out << "->" << *Frame->Callee << '(';
>    }
>
>    Out << ')';
> @@ -12117,18 +12276,6 @@ static bool EvaluateInPlace(APValue &Res
>  /// EvaluateAsRValue - Try to evaluate this expression, performing an 
> implicit
>  /// lvalue-to-rvalue cast if it is an lvalue.
>  static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) 
> {
> -   if (Info.EnableNewConstInterp) {
> -    auto &InterpCtx = Info.Ctx.getInterpContext();
> -    switch (InterpCtx.evaluateAsRValue(Info, E, Result)) {
> -    case interp::InterpResult::Success:
> -      return true;
> -    case interp::InterpResult::Fail:
> -      return false;
> -    case interp::InterpResult::Bail:
> -      break;
> -    }
> -  }
> -
>    if (E->getType().isNull())
>      return false;
>
> @@ -12336,29 +12483,11 @@ bool Expr::EvaluateAsInitializer(APValue
>    Expr::EvalStatus EStatus;
>    EStatus.Diag = &Notes;
>
> -  EvalInfo Info(Ctx, EStatus, VD->isConstexpr()
> +  EvalInfo InitInfo(Ctx, EStatus, VD->isConstexpr()
>                                        ? EvalInfo::EM_ConstantExpression
>                                        : EvalInfo::EM_ConstantFold);
> -  Info.setEvaluatingDecl(VD, Value);
> -  Info.InConstantContext = true;
> -
> -  SourceLocation DeclLoc = VD->getLocation();
> -  QualType DeclTy = VD->getType();
> -
> -  if (Info.EnableNewConstInterp) {
> -    auto &InterpCtx = const_cast<ASTContext &>(Ctx).getInterpContext();
> -    switch (InterpCtx.evaluateAsInitializer(Info, VD, Value)) {
> -    case interp::InterpResult::Fail:
> -      // Bail out if an error was encountered.
> -      return false;
> -    case interp::InterpResult::Success:
> -      // Evaluation succeeded and value was set.
> -      return CheckConstantExpression(Info, DeclLoc, DeclTy, Value);
> -    case interp::InterpResult::Bail:
> -      // Evaluate the value again for the tree evaluator to use.
> -      break;
> -    }
> -  }
> +  InitInfo.setEvaluatingDecl(VD, Value);
> +  InitInfo.InConstantContext = true;
>
>    LValue LVal;
>    LVal.set(VD);
> @@ -12368,19 +12497,20 @@ bool Expr::EvaluateAsInitializer(APValue
>    //  zero-initialized before any other initialization takes place.
>    // This behavior is not present in C.
>    if (Ctx.getLangOpts().CPlusPlus && !VD->hasLocalStorage() &&
> -      !DeclTy->isReferenceType()) {
> -    ImplicitValueInitExpr VIE(DeclTy);
> -    if (!EvaluateInPlace(Value, Info, LVal, &VIE,
> +      !VD->getType()->isReferenceType()) {
> +    ImplicitValueInitExpr VIE(VD->getType());
> +    if (!EvaluateInPlace(Value, InitInfo, LVal, &VIE,
>                           /*AllowNonLiteralTypes=*/true))
>        return false;
>    }
>
> -  if (!EvaluateInPlace(Value, Info, LVal, this,
> +  if (!EvaluateInPlace(Value, InitInfo, LVal, this,
>                         /*AllowNonLiteralTypes=*/true) ||
>        EStatus.HasSideEffects)
>      return false;
>
> -  return CheckConstantExpression(Info, DeclLoc, DeclTy, Value);
> +  return CheckConstantExpression(InitInfo, VD->getLocation(), VD->getType(),
> +                                 Value);
>  }
>
>  /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
> @@ -13055,18 +13185,6 @@ bool Expr::isPotentialConstantExpr(const
>                  EvalInfo::EM_PotentialConstantExpression);
>    Info.InConstantContext = true;
>
> -  // The constexpr VM attempts to compile all methods to bytecode here.
> -  if (Info.EnableNewConstInterp) {
> -    auto &InterpCtx = Info.Ctx.getInterpContext();
> -    switch (InterpCtx.isPotentialConstantExpr(Info, FD)) {
> -    case interp::InterpResult::Success:
> -    case interp::InterpResult::Fail:
> -      return Diags.empty();
> -    case interp::InterpResult::Bail:
> -      break;
> -    }
> -  }
> -
>    const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
>    const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : 
> nullptr;
>
>
> Modified: cfe/trunk/lib/Driver/ToolChains/Clang.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Clang.cpp?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Driver/ToolChains/Clang.cpp (original)
> +++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp Mon Sep  2 04:34:47 2019
> @@ -4489,12 +4489,6 @@ void Clang::ConstructJob(Compilation &C,
>      CmdArgs.push_back(A->getValue());
>    }
>
> -  if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
> -    CmdArgs.push_back("-fexperimental-new-constant-interpreter");
> -
> -  if (Args.hasArg(options::OPT_fforce_experimental_new_constant_interpreter))
> -    CmdArgs.push_back("-fforce-experimental-new-constant-interpreter");
> -
>    if (Arg *A = Args.getLastArg(options::OPT_fbracket_depth_EQ)) {
>      CmdArgs.push_back("-fbracket-depth");
>      CmdArgs.push_back(A->getValue());
>
> Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
> +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Mon Sep  2 04:34:47 2019
> @@ -2783,10 +2783,6 @@ static void ParseLangArgs(LangOptions &O
>        getLastArgIntValue(Args, OPT_fconstexpr_depth, 512, Diags);
>    Opts.ConstexprStepLimit =
>        getLastArgIntValue(Args, OPT_fconstexpr_steps, 1048576, Diags);
> -  Opts.EnableNewConstInterp =
> -      Args.hasArg(OPT_fexperimental_new_constant_interpreter);
> -  Opts.ForceNewConstInterp =
> -      Args.hasArg(OPT_fforce_experimental_new_constant_interpreter);
>    Opts.BracketDepth = getLastArgIntValue(Args, OPT_fbracket_depth, 256, 
> Diags);
>    Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing);
>    Opts.NumLargeByValueCopy =
>
> Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constant-expression-cxx2a.cpp Mon Sep  2 04:34:47 
> 2019
> @@ -414,6 +414,125 @@ namespace TypeId {
>    static_assert(side_effects());
>  }
>
> +namespace Union {
> +  struct Base {
> +    int y; // expected-note {{here}}
> +  };
> +  struct A : Base {
> +    int x;
> +    int arr[3];
> +    union { int p, q; };
> +  };
> +  union B {
> +    A a;
> +    int b;
> +  };
> +  constexpr int read_wrong_member() { // expected-error {{never produces a 
> constant}}
> +    B b = {.b = 1};
> +    return b.a.x; // expected-note {{read of member 'a' of union with active 
> member 'b'}}
> +  }
> +  constexpr int change_member() {
> +    B b = {.b = 1};
> +    b.a.x = 1;
> +    return b.a.x;
> +  }
> +  static_assert(change_member() == 1);
> +  constexpr int change_member_then_read_wrong_member() { // expected-error 
> {{never produces a constant}}
> +    B b = {.b = 1};
> +    b.a.x = 1;
> +    return b.b; // expected-note {{read of member 'b' of union with active 
> member 'a'}}
> +  }
> +  constexpr int read_wrong_member_indirect() { // expected-error {{never 
> produces a constant}}
> +    B b = {.b = 1};
> +    int *p = &b.a.y;
> +    return *p; // expected-note {{read of member 'a' of union with active 
> member 'b'}}
> +  }
> +  constexpr int read_uninitialized() {
> +    B b = {.b = 1};
> +    int *p = &b.a.y;
> +    b.a.x = 1;
> +    return *p; // expected-note {{read of uninitialized object}}
> +  }
> +  static_assert(read_uninitialized() == 0); // expected-error {{constant}} 
> expected-note {{in call}}
> +  constexpr void write_wrong_member_indirect() { // expected-error {{never 
> produces a constant}}
> +    B b = {.b = 1};
> +    int *p = &b.a.y;
> +    *p = 1; // expected-note {{assignment to member 'a' of union with active 
> member 'b'}}
> +  }
> +  constexpr int write_uninitialized() {
> +    B b = {.b = 1};
> +    int *p = &b.a.y;
> +    b.a.x = 1;
> +    *p = 1;
> +    return *p;
> +  }
> +  static_assert(write_uninitialized() == 1);
> +  constexpr int change_member_indirectly() {
> +    B b = {.b = 1};
> +    b.a.arr[1] = 1;
> +    int &r = b.a.y;
> +    r = 123;
> +
> +    b.b = 2;
> +    b.a.y = 3;
> +    b.a.arr[2] = 4;
> +    return b.a.arr[2];
> +  }
> +  static_assert(change_member_indirectly() == 4);
> +  constexpr B return_uninit() {
> +    B b = {.b = 1};
> +    b.a.x = 2;
> +    return b;
> +  }
> +  constexpr B uninit = return_uninit(); // expected-error {{constant 
> expression}} expected-note {{subobject of type 'int' is not initialized}}
> +  static_assert(return_uninit().a.x == 2);
> +  constexpr A return_uninit_struct() {
> +    B b = {.b = 1};
> +    b.a.x = 2;
> +    return b.a;
> +  }
> +  // FIXME: It's unclear that this should be valid. Copying a B involves
> +  // copying the object representation of the union, but copying an A 
> invokes a
> +  // copy constructor that copies the object elementwise, and reading from
> +  // b.a.y is undefined.
> +  static_assert(return_uninit_struct().x == 2);
> +  constexpr B return_init_all() {
> +    B b = {.b = 1};
> +    b.a.x = 2;
> +    b.a.y = 3;
> +    b.a.arr[0] = 4;
> +    b.a.arr[1] = 5;
> +    b.a.arr[2] = 6;
> +    return b;
> +  }
> +  static_assert(return_init_all().a.x == 2);
> +  static_assert(return_init_all().a.y == 3);
> +  static_assert(return_init_all().a.arr[0] == 4);
> +  static_assert(return_init_all().a.arr[1] == 5);
> +  static_assert(return_init_all().a.arr[2] == 6);
> +  static_assert(return_init_all().a.p == 7); // expected-error {{}} 
> expected-note {{read of member 'p' of union with no active member}}
> +  static_assert(return_init_all().a.q == 8); // expected-error {{}} 
> expected-note {{read of member 'q' of union with no active member}}
> +  constexpr B init_all = return_init_all();
> +
> +  constexpr bool test_no_member_change =  []{
> +    union U { char dummy = {}; };
> +    U u1;
> +    U u2;
> +    u1 = u2;
> +    return true;
> +  }();
> +
> +  struct S1 {
> +    int n;
> +  };
> +  struct S2 : S1 {};
> +  struct S3 : S2 {};
> +  void f() {
> +    S3 s;
> +    s.n = 0;
> +  }
> +}
> +
>  namespace TwosComplementShifts {
>    using uint32 = __UINT32_TYPE__;
>    using int32 = __INT32_TYPE__;
>
> Modified: cfe/trunk/test/SemaCXX/constexpr-many-arguments.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-many-arguments.cpp?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/constexpr-many-arguments.cpp (original)
> +++ cfe/trunk/test/SemaCXX/constexpr-many-arguments.cpp Mon Sep  2 04:34:47 
> 2019
> @@ -12,7 +12,7 @@ struct type2
>    typedef type1 T;
>    constexpr type2(T a00, T a01, T a02, T a03, T a04, T a05, T a06, T a07, T 
> a08, T a09,
>                         T a10, T a11, T a12, T a13, T a14, T a15, T a16, T 
> a17, T a18, T a19,
> -                       T a20, T a21, T a22)
> +                       T a20, T a21, T a22)
>      : my_data{a00, a01, a02, a03, a04, a05, a06, a07, a08, a09,
>                a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
>                a20, a21, a22}
> @@ -32,7 +32,7 @@ constexpr type3 g
>     {0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
>     {0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
>     {0},{0},{0}
> -  },
> +  },
>    {
>     {0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
>     {0},{0},{0},{0},{0},{0},{0},{0},{0},{0},
>
> Modified: cfe/trunk/test/SemaCXX/shift.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/shift.cpp?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/shift.cpp (original)
> +++ cfe/trunk/test/SemaCXX/shift.cpp Mon Sep  2 04:34:47 2019
> @@ -82,8 +82,3 @@ void vect_shift_2(vec16 *x, vec16 y) { *
>  void vect_shift_3(vec16 *x, vec8 y) {
>    *x = *x << y; // expected-error {{vector operands do not have the same 
> number of elements}}
>  }
> -static_assert(-1 >> 1 == -1);
> -static_assert(-1 >> 31 == -1);
> -static_assert(-2 >> 1 == -1);
> -static_assert(-3 >> 1 == -2);
> -static_assert(-4 >> 1 == -2);
>
> Modified: cfe/trunk/utils/TableGen/CMakeLists.txt
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/CMakeLists.txt?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/utils/TableGen/CMakeLists.txt (original)
> +++ cfe/trunk/utils/TableGen/CMakeLists.txt Mon Sep  2 04:34:47 2019
> @@ -8,7 +8,6 @@ add_tablegen(clang-tblgen CLANG
>    ClangCommentHTMLTagsEmitter.cpp
>    ClangDataCollectorsEmitter.cpp
>    ClangDiagnosticsEmitter.cpp
> -  ClangOpcodesEmitter.cpp
>    ClangOpenCLBuiltinEmitter.cpp
>    ClangOptionDocEmitter.cpp
>    ClangSACheckersEmitter.cpp
>
> Removed: cfe/trunk/utils/TableGen/ClangOpcodesEmitter.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangOpcodesEmitter.cpp?rev=370641&view=auto
> ==============================================================================
> --- cfe/trunk/utils/TableGen/ClangOpcodesEmitter.cpp (original)
> +++ cfe/trunk/utils/TableGen/ClangOpcodesEmitter.cpp (removed)
> @@ -1,360 +0,0 @@
> -//=== ClangOpcodesEmitter.cpp - constexpr interpreter opcodes ---*- C++ 
> -*-===//
> -//
> -// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
> Exceptions.
> -// See https://llvm.org/LICENSE.txt for license information.
> -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
> -//
> -//===----------------------------------------------------------------------===//
> -//
> -// These tablegen backends emit Clang AST node tables
> -//
> -//===----------------------------------------------------------------------===//
> -
> -#include "llvm/TableGen/Error.h"
> -#include "llvm/TableGen/Record.h"
> -#include "llvm/TableGen/StringMatcher.h"
> -#include "llvm/TableGen/TableGenBackend.h"
> -
> -using namespace llvm;
> -
> -namespace {
> -class ClangOpcodesEmitter {
> -  RecordKeeper &Records;
> -  Record Root;
> -  unsigned NumTypes;
> -
> -public:
> -  ClangOpcodesEmitter(RecordKeeper &R)
> -    : Records(R), Root("Opcode", SMLoc(), R),
> -      NumTypes(Records.getAllDerivedDefinitions("Type").size()) {}
> -
> -  void run(raw_ostream &OS);
> -
> -private:
> -  /// Emits the opcode name for the opcode enum.
> -  /// The name is obtained by concatenating the name with the list of types.
> -  void EmitEnum(raw_ostream &OS, StringRef N, Record *R);
> -
> -  /// Emits the switch case and the invocation in the interpreter.
> -  void EmitInterp(raw_ostream &OS, StringRef N, Record *R);
> -
> -  /// Emits the disassembler.
> -  void EmitDisasm(raw_ostream &OS, StringRef N, Record *R);
> -
> -  /// Emits the byte code emitter method.
> -  void EmitEmitter(raw_ostream &OS, StringRef N, Record *R);
> -
> -  /// Emits the prototype.
> -  void EmitProto(raw_ostream &OS, StringRef N, Record *R);
> -
> -  /// Emits the prototype to dispatch from a type.
> -  void EmitGroup(raw_ostream &OS, StringRef N, Record *R);
> -
> -  /// Emits the evaluator method.
> -  void EmitEval(raw_ostream &OS, StringRef N, Record *R);
> -
> -  void PrintTypes(raw_ostream &OS, ArrayRef<Record *> Types);
> -};
> -
> -void Enumerate(const Record *R,
> -               StringRef N,
> -               std::function<void(ArrayRef<Record *>, Twine)> &&F) {
> -  llvm::SmallVector<Record *, 2> TypePath;
> -  auto *Types = R->getValueAsListInit("Types");
> -
> -  std::function<void(size_t, const Twine &)> Rec;
> -  Rec = [&TypePath, Types, &Rec, &F](size_t I, const Twine &ID) {
> -    if (I >= Types->size()) {
> -      F(TypePath, ID);
> -      return;
> -    }
> -
> -    if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
> -      for (auto *Type : TypeClass->getDef()->getValueAsListOfDefs("Types")) {
> -        TypePath.push_back(Type);
> -        Rec(I + 1, ID + Type->getName());
> -        TypePath.pop_back();
> -      }
> -    } else {
> -      PrintFatalError("Expected a type class");
> -    }
> -  };
> -  Rec(0, N);
> -}
> -
> -} // namespace
> -
> -void ClangOpcodesEmitter::run(raw_ostream &OS) {
> -  for (auto *Opcode : Records.getAllDerivedDefinitions(Root.getName())) {
> -    // The name is the record name, unless overriden.
> -    StringRef N = Opcode->getValueAsString("Name");
> -    if (N.empty())
> -      N = Opcode->getName();
> -
> -    EmitEnum(OS, N, Opcode);
> -    EmitInterp(OS, N, Opcode);
> -    EmitDisasm(OS, N, Opcode);
> -    EmitProto(OS, N, Opcode);
> -    EmitGroup(OS, N, Opcode);
> -    EmitEmitter(OS, N, Opcode);
> -    EmitEval(OS, N, Opcode);
> -  }
> -}
> -
> -void ClangOpcodesEmitter::EmitEnum(raw_ostream &OS, StringRef N, Record *R) {
> -  OS << "#ifdef GET_OPCODE_NAMES\n";
> -  Enumerate(R, N, [&OS](ArrayRef<Record *>, const Twine &ID) {
> -    OS << "OP_" << ID << ",\n";
> -  });
> -  OS << "#endif\n";
> -}
> -
> -void ClangOpcodesEmitter::EmitInterp(raw_ostream &OS, StringRef N, Record 
> *R) {
> -  OS << "#ifdef GET_INTERP\n";
> -
> -  Enumerate(R, N, [this, R, &OS, &N](ArrayRef<Record *> TS, const Twine &ID) 
> {
> -    bool CanReturn = R->getValueAsBit("CanReturn");
> -    bool ChangesPC = R->getValueAsBit("ChangesPC");
> -    auto Args = R->getValueAsListOfDefs("Args");
> -
> -    OS << "case OP_" << ID << ": {\n";
> -
> -    // Emit calls to read arguments.
> -    for (size_t I = 0, N = Args.size(); I < N; ++I) {
> -      OS << "\tauto V" << I;
> -      OS << " = ";
> -      OS << "PC.read<" << Args[I]->getValueAsString("Name") << ">();\n";
> -    }
> -
> -    // Emit a call to the template method and pass arguments.
> -    OS << "\tif (!" << N;
> -    PrintTypes(OS, TS);
> -    OS << "(S";
> -    if (ChangesPC)
> -      OS << ", PC";
> -    else
> -      OS << ", OpPC";
> -    if (CanReturn)
> -      OS << ", Result";
> -    for (size_t I = 0, N = Args.size(); I < N; ++I)
> -      OS << ", V" << I;
> -    OS << "))\n";
> -    OS << "\t\treturn false;\n";
> -
> -    // Bail out if interpreter returned.
> -    if (CanReturn) {
> -      OS << "\tif (!S.Current || S.Current->isRoot())\n";
> -      OS << "\t\treturn true;\n";
> -    }
> -
> -    OS << "\tcontinue;\n";
> -    OS << "}\n";
> -  });
> -  OS << "#endif\n";
> -}
> -
> -void ClangOpcodesEmitter::EmitDisasm(raw_ostream &OS, StringRef N, Record 
> *R) {
> -  OS << "#ifdef GET_DISASM\n";
> -  Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
> -    OS << "case OP_" << ID << ":\n";
> -    OS << "\tPrintName(\"" << ID << "\");\n";
> -    OS << "\tOS << \"\\t\"";
> -
> -    for (auto *Arg : R->getValueAsListOfDefs("Args"))
> -      OS << " << PC.read<" << Arg->getValueAsString("Name") << ">() << \" 
> \"";
> -
> -    OS << "<< \"\\n\";\n";
> -    OS << "\tcontinue;\n";
> -  });
> -  OS << "#endif\n";
> -}
> -
> -void ClangOpcodesEmitter::EmitEmitter(raw_ostream &OS, StringRef N, Record 
> *R) {
> -  if (R->getValueAsBit("HasCustomLink"))
> -    return;
> -
> -  OS << "#ifdef GET_LINK_IMPL\n";
> -  Enumerate(R, N, [R, &OS](ArrayRef<Record *>, const Twine &ID) {
> -    auto Args = R->getValueAsListOfDefs("Args");
> -
> -    // Emit the list of arguments.
> -    OS << "bool ByteCodeEmitter::emit" << ID << "(";
> -    for (size_t I = 0, N = Args.size(); I < N; ++I)
> -      OS << Args[I]->getValueAsString("Name") << " A" << I << ",";
> -    OS << "const SourceInfo &L) {\n";
> -
> -    // Emit a call to write the opcodes.
> -    OS << "\treturn emitOp<";
> -    for (size_t I = 0, N = Args.size(); I < N; ++I) {
> -      if (I != 0)
> -        OS << ", ";
> -      OS << Args[I]->getValueAsString("Name");
> -    }
> -    OS << ">(OP_" << ID;
> -    for (size_t I = 0, N = Args.size(); I < N; ++I)
> -      OS << ", A" << I;
> -    OS << ", L);\n";
> -    OS << "}\n";
> -  });
> -  OS << "#endif\n";
> -}
> -
> -void ClangOpcodesEmitter::EmitProto(raw_ostream &OS, StringRef N, Record *R) 
> {
> -  OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
> -  auto Args = R->getValueAsListOfDefs("Args");
> -  Enumerate(R, N, [&OS, &Args](ArrayRef<Record *> TS, const Twine &ID) {
> -    OS << "bool emit" << ID << "(";
> -    for (auto *Arg : Args)
> -      OS << Arg->getValueAsString("Name") << ", ";
> -    OS << "const SourceInfo &);\n";
> -  });
> -
> -  // Emit a template method for custom emitters to have less to implement.
> -  auto TypeCount = R->getValueAsListInit("Types")->size();
> -  if (R->getValueAsBit("HasCustomEval") && TypeCount) {
> -    OS << "#if defined(GET_EVAL_PROTO)\n";
> -    OS << "template<";
> -    for (size_t I = 0; I < TypeCount; ++I) {
> -      if (I != 0)
> -        OS << ", ";
> -      OS << "PrimType";
> -    }
> -    OS << ">\n";
> -    OS << "bool emit" << N << "(";
> -    for (auto *Arg : Args)
> -      OS << Arg->getValueAsString("Name") << ", ";
> -    OS << "const SourceInfo &);\n";
> -    OS << "#endif\n";
> -  }
> -
> -  OS << "#endif\n";
> -}
> -
> -void ClangOpcodesEmitter::EmitGroup(raw_ostream &OS, StringRef N, Record *R) 
> {
> -  if (!R->getValueAsBit("HasGroup"))
> -    return;
> -
> -  auto *Types = R->getValueAsListInit("Types");
> -  auto Args = R->getValueAsListOfDefs("Args");
> -
> -  // Emit the prototype of the group emitter in the header.
> -  OS << "#if defined(GET_EVAL_PROTO) || defined(GET_LINK_PROTO)\n";
> -  OS << "bool emit" << N << "(";
> -  for (size_t I = 0, N = Types->size(); I < N; ++I)
> -    OS << "PrimType, ";
> -  for (auto *Arg : Args)
> -    OS << Arg->getValueAsString("Name") << ", ";
> -  OS << "const SourceInfo &I);\n";
> -  OS << "#endif\n";
> -
> -  // Emit the dispatch implementation in the source.
> -  OS << "#if defined(GET_EVAL_IMPL) || defined(GET_LINK_IMPL)\n";
> -  OS << "bool \n";
> -  OS << "#if defined(GET_EVAL_IMPL)\n";
> -  OS << "EvalEmitter\n";
> -  OS << "#else\n";
> -  OS << "ByteCodeEmitter\n";
> -  OS << "#endif\n";
> -  OS << "::emit" << N << "(";
> -  for (size_t I = 0, N = Types->size(); I < N; ++I)
> -    OS << "PrimType T" << I << ", ";
> -  for (size_t I = 0, N = Args.size(); I < N; ++I)
> -    OS << Args[I]->getValueAsString("Name") << " A" << I << ", ";
> -  OS << "const SourceInfo &I) {\n";
> -
> -  std::function<void(size_t, const Twine &)> Rec;
> -  llvm::SmallVector<Record *, 2> TS;
> -  Rec = [this, &Rec, &OS, Types, &Args, R, &TS, N](size_t I, const Twine 
> &ID) {
> -    if (I >= Types->size()) {
> -      // Print a call to the emitter method.
> -      // Custom evaluator methods dispatch to template methods.
> -      if (R->getValueAsBit("HasCustomEval")) {
> -        OS << "#ifdef GET_LINK_IMPL\n";
> -        OS << "return emit" << ID << "\n";
> -        OS << "#else\n";
> -        OS << "return emit" << N;
> -        PrintTypes(OS, TS);
> -        OS << "\n#endif\n";
> -      } else {
> -        OS << "return emit" << ID;
> -      }
> -
> -      OS << "(";
> -      for (size_t I = 0; I < Args.size(); ++I) {
> -        OS << "A" << I << ", ";
> -      }
> -      OS << "I);\n";
> -      return;
> -    }
> -
> -    // Print a switch statement selecting T.
> -    if (auto *TypeClass = dyn_cast<DefInit>(Types->getElement(I))) {
> -      OS << "switch (T" << I << "){\n";
> -      auto Cases = TypeClass->getDef()->getValueAsListOfDefs("Types");
> -      for (auto *Case : Cases) {
> -        OS << "case PT_" << Case->getName() << ":\n";
> -        TS.push_back(Case);
> -        Rec(I + 1, ID + Case->getName());
> -        TS.pop_back();
> -      }
> -      // Emit a default case if not all types are present.
> -      if (Cases.size() < NumTypes)
> -        OS << "default: llvm_unreachable(\"invalid type\");\n";
> -      OS << "}\n";
> -      OS << "llvm_unreachable(\"invalid enum value\");\n";
> -    } else {
> -      PrintFatalError("Expected a type class");
> -    }
> -  };
> -  Rec(0, N);
> -
> -  OS << "}\n";
> -  OS << "#endif\n";
> -}
> -
> -void ClangOpcodesEmitter::EmitEval(raw_ostream &OS, StringRef N, Record *R) {
> -  if (R->getValueAsBit("HasCustomEval"))
> -    return;
> -
> -  OS << "#ifdef GET_EVAL_IMPL\n";
> -  Enumerate(R, N, [this, R, &N, &OS](ArrayRef<Record *> TS, const Twine &ID) 
> {
> -    auto Args = R->getValueAsListOfDefs("Args");
> -
> -    OS << "bool EvalEmitter::emit" << ID << "(";
> -    for (size_t I = 0, N = Args.size(); I < N; ++I)
> -      OS << Args[I]->getValueAsString("Name") << " A" << I << ",";
> -    OS << "const SourceInfo &L) {\n";
> -    OS << "if (!isActive()) return true;\n";
> -    OS << "CurrentSource = L;\n";
> -
> -    OS << "return " << N;
> -    PrintTypes(OS, TS);
> -    OS << "(S, OpPC";
> -    for (size_t I = 0, N = Args.size(); I < N; ++I)
> -      OS << ", A" << I;
> -    OS << ");\n";
> -    OS << "}\n";
> -  });
> -
> -  OS << "#endif\n";
> -}
> -
> -void ClangOpcodesEmitter::PrintTypes(raw_ostream &OS, ArrayRef<Record *> 
> Types) {
> -  if (Types.empty())
> -    return;
> -  OS << "<";
> -  for (size_t I = 0, N = Types.size(); I < N; ++I) {
> -    if (I != 0)
> -      OS << ", ";
> -    OS << "PT_" << Types[I]->getName();
> -  }
> -  OS << ">";
> -}
> -
> -namespace clang {
> -
> -void EmitClangOpcodes(RecordKeeper &Records, raw_ostream &OS) {
> -  ClangOpcodesEmitter(Records).run(OS);
> -}
> -
> -} // end namespace clang
>
> Modified: cfe/trunk/utils/TableGen/TableGen.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGen.cpp?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/utils/TableGen/TableGen.cpp (original)
> +++ cfe/trunk/utils/TableGen/TableGen.cpp Mon Sep  2 04:34:47 2019
> @@ -47,7 +47,6 @@ enum ActionType {
>    GenClangCommentNodes,
>    GenClangDeclNodes,
>    GenClangStmtNodes,
> -  GenClangOpcodes,
>    GenClangSACheckers,
>    GenClangCommentHTMLTags,
>    GenClangCommentHTMLTagsProperties,
> @@ -130,8 +129,6 @@ cl::opt<ActionType> Action(
>                     "Generate Clang AST declaration nodes"),
>          clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
>                     "Generate Clang AST statement nodes"),
> -        clEnumValN(GenClangOpcodes, "gen-clang-opcodes",
> -                   "Generate Clang constexpr interpreter opcodes"),
>          clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
>                     "Generate Clang Static Analyzer checkers"),
>          clEnumValN(GenClangCommentHTMLTags, "gen-clang-comment-html-tags",
> @@ -254,9 +251,6 @@ bool ClangTableGenMain(raw_ostream &OS,
>    case GenClangStmtNodes:
>      EmitClangASTNodes(Records, OS, "Stmt", "");
>      break;
> -  case GenClangOpcodes:
> -    EmitClangOpcodes(Records, OS);
> -    break;
>    case GenClangSACheckers:
>      EmitClangSACheckers(Records, OS);
>      break;
>
> Modified: cfe/trunk/utils/TableGen/TableGenBackends.h
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGenBackends.h?rev=370642&r1=370641&r2=370642&view=diff
> ==============================================================================
> --- cfe/trunk/utils/TableGen/TableGenBackends.h (original)
> +++ cfe/trunk/utils/TableGen/TableGenBackends.h Mon Sep  2 04:34:47 2019
> @@ -77,7 +77,6 @@ void EmitClangCommentCommandInfo(llvm::R
>                                   llvm::raw_ostream &OS);
>  void EmitClangCommentCommandList(llvm::RecordKeeper &Records,
>                                   llvm::raw_ostream &OS);
> -void EmitClangOpcodes(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
>
>  void EmitNeon(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
>  void EmitFP16(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits@lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to