Tyker updated this revision to Diff 264237.
Tyker added a comment.



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76420/new/

https://reviews.llvm.org/D76420

Files:
  clang/lib/AST/Expr.cpp
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBlocks.cpp
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CGDecl.cpp
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprAgg.cpp
  clang/lib/CodeGen/CGExprComplex.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/lib/CodeGen/CGObjC.cpp
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/ConstantEmitter.h
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenCXX/cxx2a-consteval.cpp
  clang/test/SemaCXX/constant-expression-cxx11.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp

Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===================================================================
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++2a -fsyntax-only -Wno-unused-value %s -verify
+// RUN: %clang_cc1 -std=c++2a -emit-llvm-only -Wno-unused-value %s -verify
 
 typedef __SIZE_TYPE__ size_t;
 
Index: clang/test/SemaCXX/constant-expression-cxx11.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1578,7 +1578,7 @@
 namespace CompoundLiteral {
   // Matching GCC, file-scope array compound literals initialized by constants
   // are lifetime-extended.
-  constexpr int *p = (int*)(int[1]){3}; // expected-warning {{C99}}
+  constexpr int *p = (int*)(int[1]){2 + __builtin_is_constant_evaluated()}; // expected-warning {{C99}}
   static_assert(*p == 3, "");
   static_assert((int[2]){1, 2}[1] == 2, ""); // expected-warning {{C99}}
 
Index: clang/test/CodeGenCXX/cxx2a-consteval.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/cxx2a-consteval.cpp
@@ -0,0 +1,212 @@
+// NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+// RUN: %clang_cc1 -emit-llvm %s -std=c++2a -o %t.ll
+// RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s
+// RUN: FileCheck -check-prefix=EVAL-FN -input-file=%t.ll %s
+// RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s
+// RUN: %clang_cc1 -emit-llvm %s -Dconsteval="" -std=c++2a -o %t.ll
+// RUN: FileCheck -check-prefix=EXPR -input-file=%t.ll %s
+
+// there is two version of symbol checks to ensure
+// that the symbol we are looking for are correct
+// EVAL-NOT: @__cxx_global_var_init()
+// EXPR: @__cxx_global_var_init()
+
+// EVAL-NOT: @_Z4ret7v()
+// EXPR: @_Z4ret7v()
+consteval int ret7() {
+  return 7;
+}
+
+int test_ret7() {
+  // EVAL-FN-LABEL: @_Z9test_ret7v(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    [[I:%.*]] = alloca i32, align 4
+  // EVAL-FN-NEXT:    store i32 7, i32* [[I]], align 4
+  // EVAL-FN-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I]], align 4
+  // EVAL-FN-NEXT:    ret i32 [[TMP0]]
+  //
+  int i = ret7();
+  return i;
+}
+
+// EVAL-STATIC: @global_i = global i32 7, align 4
+int global_i = ret7();
+
+// EVAL-STATIC: @_ZL7i_const = internal constant i32 5, align 4
+constexpr int i_const = 5;
+
+// EVAL-NOT: @_Z4retIv()
+// EXPR: @_Z4retIv()
+consteval const int &retI() {
+  return i_const;
+}
+
+const int &test_retRefI() {
+  // EVAL-FN-LABEL: @_Z12test_retRefIv(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    ret i32* @_ZL7i_const
+  //
+  return retI();
+}
+
+int test_retI() {
+  // EVAL-FN-LABEL: @_Z9test_retIv(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    [[TMP0:%.*]] = load i32, i32* @_ZL7i_const, align 4
+  // EVAL-FN-NEXT:    ret i32 [[TMP0]]
+  //
+  return retI();
+}
+
+// EVAL-NOT: @_Z4retIv()
+// EXPR: @_Z4retIv()
+consteval const int *retIPtr() {
+  return &i_const;
+}
+
+int test_retIPtr() {
+  // EVAL-FN-LABEL: @_Z12test_retIPtrv(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    [[TMP0:%.*]] = load i32, i32* @_ZL7i_const, align 4
+  // EVAL-FN-NEXT:    ret i32 [[TMP0]]
+  //
+  return *retIPtr();
+}
+
+const int *test_retPIPtr() {
+  // EVAL-FN-LABEL: @_Z13test_retPIPtrv(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    ret i32* @_ZL7i_const
+  //
+  return retIPtr();
+}
+
+// EVAL-NOT: @_Z4retIv()
+// EXPR: @_Z4retIv()
+consteval const int &&retIRRef() {
+  return static_cast<const int &&>(i_const);
+}
+
+// EVAL-NOT: @_Z4retIv()
+// EXPR: @_Z4retIv()
+const int &&test_retIRRef() {
+  return static_cast<const int &&>(retIRRef());
+}
+
+int test_retIRRefI() {
+  // EVAL-FN-LABEL: @_Z14test_retIRRefIv(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    [[TMP0:%.*]] = load i32, i32* @_ZL7i_const, align 4
+  // EVAL-FN-NEXT:    ret i32 [[TMP0]]
+  //
+  return retIRRef();
+}
+
+struct Agg {
+  int a;
+  long b;
+};
+
+// EVAL-NOT: @_Z6retAggv()
+// EXPR: @_Z6retAggv()
+consteval Agg retAgg() {
+  return {13, 17};
+}
+
+long test_retAgg() {
+  // EVAL-FN-LABEL: @_Z11test_retAggv(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    [[B:%.*]] = alloca i64, align 8
+  // EVAL-FN-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
+  // EVAL-FN-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 0
+  // EVAL-FN-NEXT:    store i32 13, i32* [[TMP0]], align 8
+  // EVAL-FN-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 1
+  // EVAL-FN-NEXT:    store i64 17, i64* [[TMP1]], align 8
+  // EVAL-FN-NEXT:    store i64 17, i64* [[B]], align 8
+  // EVAL-FN-NEXT:    [[TMP2:%.*]] = load i64, i64* [[B]], align 8
+  // EVAL-FN-NEXT:    ret i64 [[TMP2]]
+  //
+  long b = retAgg().b;
+  return b;
+}
+
+// EVAL-STATIC: @A = global %struct.Agg { i32 13, i64 17 }, align 8
+Agg A = retAgg();
+
+// EVAL-NOT: @_Z9retRefAggv()
+// EXPR: @_Z9retRefAggv()
+consteval const Agg &retRefAgg() {
+  const Agg &tmp = A;
+  return A;
+}
+
+long test_retRefAgg() {
+  // EVAL-FN-LABEL: @_Z14test_retRefAggv(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    [[B:%.*]] = alloca i64, align 8
+  // EVAL-FN-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
+  // EVAL-FN-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 0
+  // EVAL-FN-NEXT:    store i32 13, i32* [[TMP0]], align 8
+  // EVAL-FN-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 1
+  // EVAL-FN-NEXT:    store i64 17, i64* [[TMP1]], align 8
+  // EVAL-FN-NEXT:    store i64 17, i64* [[B]], align 8
+  // EVAL-FN-NEXT:    [[TMP2:%.*]] = load i64, i64* [[B]], align 8
+  // EVAL-FN-NEXT:    ret i64 [[TMP2]]
+  //
+  long b = retAgg().b;
+  return b;
+}
+
+// EVAL-NOT: define i64@_Z7is_constv()
+// EXPR: : define i64 @_Z7is_constv()
+consteval Agg is_const() {
+  return {5, 19 * __builtin_is_constant_evaluated()};
+}
+
+long test_is_const() {
+  // EVAL-FN-LABEL: @_Z13test_is_constv(
+  // EVAL-FN-NEXT:  entry:
+  // EVAL-FN-NEXT:    [[B:%.*]] = alloca i64, align 8
+  // EVAL-FN-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
+  // EVAL-FN-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 0
+  // EVAL-FN-NEXT:    store i32 5, i32* [[TMP0]], align 8
+  // EVAL-FN-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 1
+  // EVAL-FN-NEXT:    store i64 19, i64* [[TMP1]], align 8
+  // EVAL-FN-NEXT:    store i64 19, i64* [[B]], align 8
+  // EVAL-FN-NEXT:    [[TMP2:%.*]] = load i64, i64* [[B]], align 8
+  // EVAL-FN-NEXT:    ret i64 [[TMP2]]
+  //
+  long b = is_const().b;
+  return b;
+}
+
+// EVAL-NOT: @_ZN7AggCtorC
+// EXPR: @_ZN7AggCtorC
+struct AggCtor {
+  consteval AggCtor(int a = 3, long b = 5) : a(a * a), b(a * b) {}
+  int a;
+  long b;
+};
+
+long test_AggCtor() {
+  // CHECK-LABEL: @_Z12test_AggCtorv(
+  // CHECK-NEXT:  entry:
+  // CHECK-NEXT:    [[I:%.*]] = alloca i32, align 4
+  // CHECK-NEXT:    [[C:%.*]] = alloca [[STRUCT_AGGCTOR:%.*]], align 8
+  // CHECK-NEXT:    store i32 2, i32* [[I]], align 4
+  // CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_AGGCTOR]], %struct.AggCtor* [[C]], i32 0, i32 0
+  // CHECK-NEXT:    store i32 4, i32* [[TMP0]], align 8
+  // CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_AGGCTOR]], %struct.AggCtor* [[C]], i32 0, i32 1
+  // CHECK-NEXT:    store i64 10, i64* [[TMP1]], align 8
+  // CHECK-NEXT:    [[A:%.*]] = getelementptr inbounds [[STRUCT_AGGCTOR]], %struct.AggCtor* [[C]], i32 0, i32 0
+  // CHECK-NEXT:    [[TMP2:%.*]] = load i32, i32* [[A]], align 8
+  // CHECK-NEXT:    [[CONV:%.*]] = sext i32 [[TMP2]] to i64
+  // CHECK-NEXT:    [[B:%.*]] = getelementptr inbounds [[STRUCT_AGGCTOR]], %struct.AggCtor* [[C]], i32 0, i32 1
+  // CHECK-NEXT:    [[TMP3:%.*]] = load i64, i64* [[B]], align 8
+  // CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[CONV]], [[TMP3]]
+  // CHECK-NEXT:    ret i64 [[ADD]]
+  //
+  const int i = 2;
+  AggCtor C(i);
+  return C.a + C.b;
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -15917,7 +15917,7 @@
 
   ConstantExpr *Res = ConstantExpr::Create(
       getASTContext(), E.get(),
-      ConstantExpr::getStorageKind(E.get()->getType().getTypePtr(),
+      ConstantExpr::getStorageKind(Decl->getReturnType().getTypePtr(),
                                    getASTContext()),
       /*IsImmediateInvocation*/ true);
   ExprEvalContexts.back().ImmediateInvocationCandidates.emplace_back(Res, 0);
Index: clang/lib/CodeGen/ConstantEmitter.h
===================================================================
--- clang/lib/CodeGen/ConstantEmitter.h
+++ clang/lib/CodeGen/ConstantEmitter.h
@@ -110,6 +110,8 @@
   llvm::Constant *tryEmitAbstract(const APValue &value, QualType T);
   llvm::Constant *tryEmitAbstractForMemory(const APValue &value, QualType T);
 
+  llvm::Constant *tryEmitConstantExpr(const ConstantExpr *CE);
+
   llvm::Constant *emitNullForMemory(QualType T) {
     return emitNullForMemory(CGM, T);
   }
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3332,6 +3332,8 @@
                                                  bool ForVTable,
                                                  bool DontDefer,
                                               ForDefinition_t IsForDefinition) {
+  assert(!cast<FunctionDecl>(GD.getDecl())->isConsteval() &&
+         "consteval function should never be emitted");
   // If there was no specific requested type, just convert it now.
   if (!Ty) {
     const auto *FD = cast<FunctionDecl>(GD.getDecl());
@@ -5319,6 +5321,11 @@
   if (D->isTemplated())
     return;
 
+  // Consteval function shouldn't be emitted.
+  if (auto *FD = dyn_cast<FunctionDecl>(D))
+    if (FD->isConsteval())
+      return;
+
   switch (D->getKind()) {
   case Decl::CXXConversion:
   case Decl::CXXMethod:
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -4092,6 +4092,10 @@
   /// aggregate type into a temporary LValue.
   LValue EmitAggExprToLValue(const Expr *E);
 
+  /// Build all the stores needed to initialize an aggregate at Dest with the
+  /// value Val.
+  void EmitAggregateStore(llvm::Value *Val, Address Dest, bool DestIsVolatile);
+
   /// EmitExtendGCLifetime - Given a pointer to an Objective-C object,
   /// make sure it survives garbage collection until this point.
   void EmitExtendGCLifetime(llvm::Value *object);
@@ -4181,13 +4185,13 @@
 
   void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp);
 
-  void enterFullExpression(const FullExpr *E) {
+  void enterExprWithCleanups(const ExprWithCleanups *E) {
     if (const auto *EWC = dyn_cast<ExprWithCleanups>(E))
       if (EWC->getNumObjects() == 0)
         return;
-    enterNonTrivialFullExpression(E);
+    enterNonTrivialExprWithCleanups(E);
   }
-  void enterNonTrivialFullExpression(const FullExpr *E);
+  void enterNonTrivialExprWithCleanups(const FullExpr *E);
 
   void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true);
 
Index: clang/lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4789,13 +4789,13 @@
   }
 
   const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
-  if (const auto *FE = dyn_cast<FullExpr>(CS))
-    enterFullExpression(FE);
+  if (const auto *FE = dyn_cast<ExprWithCleanups>(CS))
+    enterExprWithCleanups(FE);
   // Processing for statements under 'atomic capture'.
   if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
     for (const Stmt *C : Compound->body()) {
-      if (const auto *FE = dyn_cast<FullExpr>(C))
-        enterFullExpression(FE);
+      if (const auto *FE = dyn_cast<ExprWithCleanups>(C))
+        enterExprWithCleanups(FE);
     }
   }
 
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -1091,9 +1091,9 @@
   // exception to our over-conservative rules about not jumping to
   // statements following block literals with non-trivial cleanups.
   RunCleanupsScope cleanupScope(*this);
-  if (const FullExpr *fe = dyn_cast_or_null<FullExpr>(RV)) {
-    enterFullExpression(fe);
-    RV = fe->getSubExpr();
+  if (const auto *EWC = dyn_cast_or_null<ExprWithCleanups>(RV)) {
+    enterExprWithCleanups(EWC);
+    RV = EWC->getSubExpr();
   }
 
   // FIXME: Clean this up by using an LValue for ReturnTemp,
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -3256,7 +3256,7 @@
 llvm::Value *CodeGenFunction::EmitARCRetainScalarExpr(const Expr *e) {
   // The retain needs to happen within the full-expression.
   if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) {
-    enterFullExpression(cleanups);
+    enterExprWithCleanups(cleanups);
     RunCleanupsScope scope(*this);
     return EmitARCRetainScalarExpr(cleanups->getSubExpr());
   }
@@ -3272,7 +3272,7 @@
 CodeGenFunction::EmitARCRetainAutoreleaseScalarExpr(const Expr *e) {
   // The retain needs to happen within the full-expression.
   if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) {
-    enterFullExpression(cleanups);
+    enterExprWithCleanups(cleanups);
     RunCleanupsScope scope(*this);
     return EmitARCRetainAutoreleaseScalarExpr(cleanups->getSubExpr());
   }
@@ -3383,7 +3383,7 @@
 llvm::Value *CodeGenFunction::EmitARCUnsafeUnretainedScalarExpr(const Expr *e) {
   // Look through full-expressions.
   if (const ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(e)) {
-    enterFullExpression(cleanups);
+    enterExprWithCleanups(cleanups);
     RunCleanupsScope scope(*this);
     return emitARCUnsafeUnretainedScalarExpr(*this, cleanups->getSubExpr());
   }
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -460,6 +460,12 @@
   Value *VisitExpr(Expr *S);
 
   Value *VisitConstantExpr(ConstantExpr *E) {
+    if (Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) {
+      if (E->isGLValue())
+        return CGF.Builder.CreateLoad(Address(
+            Result, CGF.getContext().getTypeAlignInChars(E->getType())));
+      return Result;
+    }
     return Visit(E->getSubExpr());
   }
   Value *VisitParenExpr(ParenExpr *PE) {
@@ -2348,7 +2354,7 @@
 }
 
 Value *ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
-  CGF.enterFullExpression(E);
+  CGF.enterExprWithCleanups(E);
   CodeGenFunction::RunCleanupsScope Scope(CGF);
   Value *V = Visit(E->getSubExpr());
   // Defend against dominance problems caused by jumps out of expression
Index: clang/lib/CodeGen/CGExprConstant.cpp
===================================================================
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -1011,6 +1011,8 @@
   }
 
   llvm::Constant *VisitConstantExpr(ConstantExpr *CE, QualType T) {
+    if (llvm::Constant *Result = Emitter.tryEmitConstantExpr(CE))
+      return Result;
     return Visit(CE->getSubExpr(), T);
   }
 
@@ -1358,6 +1360,20 @@
   return validateAndPopAbstract(C, state);
 }
 
+llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
+  if (!CE->hasAPValueResult())
+    return nullptr;
+  const Expr *Inner = CE->getSubExpr()->IgnoreImplicit();
+  QualType RetType;
+  if (auto *Call = dyn_cast<CallExpr>(Inner))
+    RetType = Call->getCallReturnType(CGF->getContext());
+  else if (auto *Ctor = dyn_cast<CXXConstructExpr>(Inner))
+    RetType = Ctor->getType();
+  llvm::Constant *Res =
+      emitAbstract(CE->getBeginLoc(), CE->getAPValueResult(), RetType);
+  return Res;
+}
+
 llvm::Constant *
 ConstantEmitter::emitAbstract(const Expr *E, QualType destType) {
   auto state = pushAbstract();
@@ -1903,6 +1919,8 @@
 
 ConstantLValue
 ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *E) {
+  if (llvm::Constant *Result = Emitter.tryEmitConstantExpr(E))
+    return Result;
   return Visit(E->getSubExpr());
 }
 
Index: clang/lib/CodeGen/CGExprComplex.cpp
===================================================================
--- clang/lib/CodeGen/CGExprComplex.cpp
+++ clang/lib/CodeGen/CGExprComplex.cpp
@@ -13,6 +13,7 @@
 #include "CGOpenMPRuntime.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "ConstantEmitter.h"
 #include "clang/AST/StmtVisitor.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/Constants.h"
@@ -102,6 +103,9 @@
   }
   ComplexPairTy VisitExpr(Expr *S);
   ComplexPairTy VisitConstantExpr(ConstantExpr *E) {
+    if (llvm::Constant *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E))
+      return ComplexPairTy(Result->getAggregateElement(0U),
+                           Result->getAggregateElement(1U));
     return Visit(E->getSubExpr());
   }
   ComplexPairTy VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr());}
@@ -222,7 +226,7 @@
     return Visit(DIE->getExpr());
   }
   ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) {
-    CGF.enterFullExpression(E);
+    CGF.enterExprWithCleanups(E);
     CodeGenFunction::RunCleanupsScope Scope(CGF);
     ComplexPairTy Vals = Visit(E->getSubExpr());
     // Defend against dominance problems caused by jumps out of expression
Index: clang/lib/CodeGen/CGExprAgg.cpp
===================================================================
--- clang/lib/CodeGen/CGExprAgg.cpp
+++ clang/lib/CodeGen/CGExprAgg.cpp
@@ -127,6 +127,11 @@
   }
 
   void VisitConstantExpr(ConstantExpr *E) {
+    if (llvm::Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) {
+      CGF.EmitAggregateStore(Result, Dest.getAddress(),
+                             E->getType().isVolatileQualified());
+      return;
+    }
     return Visit(E->getSubExpr());
   }
 
@@ -1349,7 +1354,7 @@
 }
 
 void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
-  CGF.enterFullExpression(E);
+  CGF.enterExprWithCleanups(E);
   CodeGenFunction::RunCleanupsScope cleanups(CGF);
   Visit(E->getSubExpr());
 }
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1292,8 +1292,15 @@
     return EmitVAArgExprLValue(cast<VAArgExpr>(E));
   case Expr::DeclRefExprClass:
     return EmitDeclRefLValue(cast<DeclRefExpr>(E));
-  case Expr::ConstantExprClass:
+  case Expr::ConstantExprClass: {
+    const ConstantExpr *CE = cast<ConstantExpr>(E);
+    if (llvm::Value *Result = ConstantEmitter(*this).tryEmitConstantExpr(CE)) {
+      QualType RetType = cast<CallExpr>(CE->getSubExpr()->IgnoreImplicit())
+                             ->getCallReturnType(getContext());
+      return MakeNaturalAlignAddrLValue(Result, RetType);
+    }
     return EmitLValue(cast<ConstantExpr>(E)->getSubExpr());
+  }
   case Expr::ParenExprClass:
     return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
   case Expr::GenericSelectionExprClass:
@@ -1320,7 +1327,7 @@
 
   case Expr::ExprWithCleanupsClass: {
     const auto *cleanups = cast<ExprWithCleanups>(E);
-    enterFullExpression(cleanups);
+    enterExprWithCleanups(cleanups);
     RunCleanupsScope Scope(*this);
     LValue LV = EmitLValue(cleanups->getSubExpr());
     if (LV.isSimple()) {
Index: clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- clang/lib/CodeGen/CGDecl.cpp
+++ clang/lib/CodeGen/CGDecl.cpp
@@ -762,9 +762,9 @@
 
   // If we're emitting a value with lifetime, we have to do the
   // initialization *before* we leave the cleanup scopes.
-  if (const FullExpr *fe = dyn_cast<FullExpr>(init)) {
-    enterFullExpression(fe);
-    init = fe->getSubExpr();
+  if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(init)) {
+    enterExprWithCleanups(EWC);
+    init = EWC->getSubExpr();
   }
   CodeGenFunction::RunCleanupsScope Scope(*this);
 
Index: clang/lib/CodeGen/CGCall.cpp
===================================================================
--- clang/lib/CodeGen/CGCall.cpp
+++ clang/lib/CodeGen/CGCall.cpp
@@ -1272,18 +1272,17 @@
 // store the elements rather than the aggregate to be more friendly to
 // fast-isel.
 // FIXME: Do we need to recurse here?
-static void BuildAggStore(CodeGenFunction &CGF, llvm::Value *Val,
-                          Address Dest, bool DestIsVolatile) {
+void CodeGenFunction::EmitAggregateStore(llvm::Value *Val, Address Dest,
+                                         bool DestIsVolatile) {
   // Prefer scalar stores to first-class aggregate stores.
-  if (llvm::StructType *STy =
-        dyn_cast<llvm::StructType>(Val->getType())) {
+  if (llvm::StructType *STy = dyn_cast<llvm::StructType>(Val->getType())) {
     for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
-      Address EltPtr = CGF.Builder.CreateStructGEP(Dest, i);
-      llvm::Value *Elt = CGF.Builder.CreateExtractValue(Val, i);
-      CGF.Builder.CreateStore(Elt, EltPtr, DestIsVolatile);
+      Address EltPtr = Builder.CreateStructGEP(Dest, i);
+      llvm::Value *Elt = Builder.CreateExtractValue(Val, i);
+      Builder.CreateStore(Elt, EltPtr, DestIsVolatile);
     }
   } else {
-    CGF.Builder.CreateStore(Val, Dest, DestIsVolatile);
+    Builder.CreateStore(Val, Dest, DestIsVolatile);
   }
 }
 
@@ -1334,7 +1333,7 @@
   // If store is legal, just bitcast the src pointer.
   if (SrcSize <= DstSize) {
     Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy);
-    BuildAggStore(CGF, Src, Dst, DstIsVolatile);
+    CGF.EmitAggregateStore(Src, Dst, DstIsVolatile);
   } else {
     // Otherwise do coercion through memory. This is stupid, but
     // simple.
@@ -5009,7 +5008,7 @@
             DestPtr = CreateMemTemp(RetTy, "agg.tmp");
             DestIsVolatile = false;
           }
-          BuildAggStore(*this, CI, DestPtr, DestIsVolatile);
+          EmitAggregateStore(CI, DestPtr, DestIsVolatile);
           return RValue::getAggregate(DestPtr);
         }
         case TEK_Scalar: {
Index: clang/lib/CodeGen/CGBlocks.cpp
===================================================================
--- clang/lib/CodeGen/CGBlocks.cpp
+++ clang/lib/CodeGen/CGBlocks.cpp
@@ -861,7 +861,7 @@
 
 /// Enter a full-expression with a non-trivial number of objects to
 /// clean up.
-void CodeGenFunction::enterNonTrivialFullExpression(const FullExpr *E) {
+void CodeGenFunction::enterNonTrivialExprWithCleanups(const FullExpr *E) {
   if (const auto EWC = dyn_cast<ExprWithCleanups>(E)) {
     assert(EWC->getNumObjects() != 0);
     for (const ExprWithCleanups::CleanupObject &C : EWC->getObjects())
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -9986,8 +9986,6 @@
   //                            Visitor Methods
   //===--------------------------------------------------------------------===//
 
-  bool VisitConstantExpr(const ConstantExpr *E);
-
   bool VisitIntegerLiteral(const IntegerLiteral *E) {
     return Success(E->getValue(), E);
   }
@@ -10768,13 +10766,6 @@
   return true;
 }
 
-bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) {
-  llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true);
-  if (E->getResultAPValueKind() != APValue::None)
-    return Success(E->getAPValueResult(), E);
-  return ExprEvaluatorBaseTy::VisitConstantExpr(E);
-}
-
 bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
   if (unsigned BuiltinOp = E->getBuiltinCallee())
     return VisitBuiltinCallExpr(E, BuiltinOp);
Index: clang/lib/AST/Expr.cpp
===================================================================
--- clang/lib/AST/Expr.cpp
+++ clang/lib/AST/Expr.cpp
@@ -272,6 +272,7 @@
   ConstantExprBits.ResultKind = StorageKind;
   ConstantExprBits.APValueKind = APValue::None;
   ConstantExprBits.HasCleanup = false;
+  ConstantExprBits.IsImmediateInvocation = false;
   if (StorageKind == ConstantExpr::RSK_APValue)
     ::new (getTrailingObjects<APValue>()) APValue();
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to