wchilders created this revision.
wchilders added reviewers: void, Tyker, rsmith.
Herald added subscribers: cfe-commits, jfb.
Herald added a project: clang.
wchilders added inline comments.

================
Comment at: clang/lib/CodeGen/CGStmt.cpp:1095
+    // preventing the cached results from being used.
+    if (!isa<ConstantExpr>(fe)) {
+      enterFullExpression(fe);
----------------
This one is a bit weird, I think the comment explains it well, but I feel there 
should be a better way to handle this or if there are similar issues lurking 
elsewhere.


This patch allows code gen to use `APValue` Results from `ConstantExpr`s.

There are some outstanding concerns I'll mark with inline comments.

This is the codegen "sister patch" of: https://reviews.llvm.org/D76438


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D76443

Files:
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CGExprAgg.cpp
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/lib/CodeGen/CGExprScalar.cpp
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.h

Index: clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- clang/lib/CodeGen/CodeGenModule.h
+++ clang/lib/CodeGen/CodeGenModule.h
@@ -1390,6 +1390,21 @@
   /// \param QT is the clang QualType of the null pointer.
   llvm::Constant *getNullPointer(llvm::PointerType *T, QualType QT);
 
+  /// Try to emit the given expression as a constant; returns 0 if the
+  /// expression cannot be emitted as a constant.
+  llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
+                                   CodeGenFunction *CGF = nullptr);
+
+  /// Emit the given constant value as a constant, in the type's scalar
+  /// representation.
+  llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType,
+                                    CodeGenFunction *CGF = nullptr);
+
+  /// Emit the given constant value as a constant, in the type's memory
+  /// representation.
+  llvm::Constant *EmitConstantValueForMemory(const APValue &Value,
+                                             QualType DestType,
+                                             CodeGenFunction *CGF = nullptr);
 private:
   llvm::Constant *GetOrCreateLLVMFunction(
       StringRef MangledName, llvm::Type *Ty, GlobalDecl D, bool ForVTable,
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2289,6 +2289,8 @@
                             TBAAAccessInfo *TBAAInfo = nullptr);
   LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy);
 
+  llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType);
+
   /// CreateTempAlloca - This creates an alloca and inserts it into the entry
   /// block if \p ArraySize is nullptr, otherwise inserts it at the current
   /// insertion point of the builder. The caller is responsible for setting an
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2529,3 +2529,9 @@
 
   return llvm::DebugLoc();
 }
+
+
+llvm::Constant *CodeGenFunction::EmitConstantValue(const APValue& Value,
+                                                   QualType DestType) {
+  return CGM.EmitConstantValue(Value, DestType, this);
+}
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -1089,8 +1089,13 @@
   // 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();
+    // Constant expressions will emit their cached APValues, so
+    // we don't want to handle this here, as it will unwrap them,
+    // preventing the cached results from being used.
+    if (!isa<ConstantExpr>(fe)) {
+      enterFullExpression(fe);
+      RV = fe->getSubExpr();
+    }
   }
 
   // FIXME: Clean this up by using an LValue for ReturnTemp,
Index: clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- clang/lib/CodeGen/CGExprScalar.cpp
+++ clang/lib/CodeGen/CGExprScalar.cpp
@@ -433,7 +433,12 @@
   Value *VisitExpr(Expr *S);
 
   Value *VisitConstantExpr(ConstantExpr *E) {
-    return Visit(E->getSubExpr());
+    if (E->hasAPValueResult()) {
+      assert(!E->getType()->isVoidType());
+      return CGF.EmitConstantValue(E->getAPValueResult(), E->getType());
+    } else {
+      return Visit(E->getSubExpr());
+    }
   }
   Value *VisitParenExpr(ParenExpr *PE) {
     return Visit(PE->getSubExpr());
Index: clang/lib/CodeGen/CGExprConstant.cpp
===================================================================
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -1312,6 +1312,138 @@
   llvm::Type *ConvertType(QualType T) {
     return CGM.getTypes().ConvertType(T);
   }
+
+public:
+  ConstantAddress EmitLValue(APValue::LValueBase LVBase) {
+    if (const ValueDecl *Decl = LVBase.dyn_cast<const ValueDecl*>()) {
+      if (Decl->hasAttr<WeakRefAttr>())
+        return CGM.GetWeakRefReference(Decl);
+      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
+        return ConstantAddress(CGM.GetAddrOfFunction(FD), CharUnits::One());
+      if (const VarDecl* VD = dyn_cast<VarDecl>(Decl)) {
+        // We can never refer to a variable with local storage.
+        if (!VD->hasLocalStorage()) {
+          CharUnits Align = CGM.getContext().getDeclAlign(VD);
+          if (VD->isFileVarDecl() || VD->hasExternalStorage())
+            return ConstantAddress(CGM.GetAddrOfGlobalVar(VD), Align);
+          else if (VD->isLocalVarDecl()) {
+            auto Ptr = CGM.getOrCreateStaticVarDecl(
+                *VD, CGM.getLLVMLinkageVarDefinition(VD, /*isConstant=*/false));
+            return ConstantAddress(Ptr, Align);
+          }
+        }
+      }
+      return ConstantAddress::invalid();
+    }
+
+    Expr *E = const_cast<Expr*>(LVBase.get<const Expr*>());
+    switch (E->getStmtClass()) {
+    default: break;
+    case Expr::CompoundLiteralExprClass: {
+      CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
+      CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType());
+      if (llvm::GlobalVariable *Addr =
+          CGM.getAddrOfConstantCompoundLiteralIfEmitted(CLE))
+        return ConstantAddress(Addr, Align);
+
+      llvm::Constant* C = CGM.EmitConstantExpr(CLE->getInitializer(),
+                                               CLE->getType(), Emitter.CGF);
+      // FIXME: "Leaked" on failure.
+      if (!C) return ConstantAddress::invalid();
+
+      auto GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
+                                         E->getType().isConstant(CGM.getContext()),
+                                         llvm::GlobalValue::InternalLinkage,
+                                         C, ".compoundliteral", nullptr,
+                                         llvm::GlobalVariable::NotThreadLocal,
+                                         CGM.getContext().getTargetAddressSpace(E->getType()));
+      GV->setAlignment(Align.getAsAlign());
+      CGM.setAddrOfConstantCompoundLiteral(CLE, GV);
+      return ConstantAddress(GV, Align);
+    }
+    case Expr::StringLiteralClass:
+      return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
+    case Expr::ObjCEncodeExprClass:
+      return CGM.GetAddrOfConstantStringFromObjCEncode(cast<ObjCEncodeExpr>(E));
+    case Expr::ObjCStringLiteralClass: {
+      ObjCStringLiteral* SL = cast<ObjCStringLiteral>(E);
+      ConstantAddress C =
+          CGM.getObjCRuntime().GenerateConstantString(SL->getString());
+      return C.getElementBitCast(ConvertType(E->getType()));
+    }
+    case Expr::PredefinedExprClass: {
+      PredefinedExpr::IdentKind Kind = cast<PredefinedExpr>(E)->getIdentKind();
+      if (Emitter.CGF) {
+        LValue Res = Emitter.CGF->EmitPredefinedLValue(cast<PredefinedExpr>(E));
+        return cast<ConstantAddress>(Res.getAddress(*Emitter.CGF));
+      } else if (Kind == PredefinedExpr::PrettyFunction) {
+        return CGM.GetAddrOfConstantCString("top level", ".tmp");
+      }
+
+      return CGM.GetAddrOfConstantCString("", ".tmp");
+    }
+    case Expr::AddrLabelExprClass: {
+      assert(Emitter.CGF && "Invalid address of label expression outside function.");
+      llvm::Constant *Ptr =
+        Emitter.CGF->GetAddrOfLabel(cast<AddrLabelExpr>(E)->getLabel());
+      Ptr = llvm::ConstantExpr::getBitCast(Ptr, ConvertType(E->getType()));
+      return ConstantAddress(Ptr, CharUnits::One());
+    }
+    case Expr::CallExprClass: {
+      CallExpr* CE = cast<CallExpr>(E);
+      unsigned builtin = CE->getBuiltinCallee();
+      if (builtin !=
+          Builtin::BI__builtin___CFStringMakeConstantString &&
+          builtin !=
+          Builtin::BI__builtin___NSStringMakeConstantString)
+        break;
+      const Expr *Arg = CE->getArg(0)->IgnoreParenCasts();
+      const StringLiteral *Literal = cast<StringLiteral>(Arg);
+      if (builtin ==
+          Builtin::BI__builtin___NSStringMakeConstantString) {
+        return CGM.getObjCRuntime().GenerateConstantString(Literal);
+      }
+      // FIXME: need to deal with UCN conversion issues.
+      return CGM.GetAddrOfConstantCFString(Literal);
+    }
+    case Expr::BlockExprClass: {
+      StringRef FunctionName;
+      if (Emitter.CGF)
+        FunctionName = Emitter.CGF->CurFn->getName();
+      else
+        FunctionName = "global";
+
+      // This is not really an l-value.
+      llvm::Constant *Ptr =
+        CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName);
+      return ConstantAddress(Ptr, CGM.getPointerAlign());
+    }
+    case Expr::CXXTypeidExprClass: {
+      CXXTypeidExpr *Typeid = cast<CXXTypeidExpr>(E);
+      QualType T;
+      if (Typeid->isTypeOperand())
+        T = Typeid->getTypeOperand(CGM.getContext());
+      else
+        T = Typeid->getExprOperand()->getType();
+      return ConstantAddress(CGM.GetAddrOfRTTIDescriptor(T),
+                             CGM.getPointerAlign());
+    }
+    case Expr::CXXUuidofExprClass: {
+      return CGM.GetAddrOfUuidDescriptor(cast<CXXUuidofExpr>(E));
+    }
+    case Expr::MaterializeTemporaryExprClass: {
+      MaterializeTemporaryExpr *MTE = cast<MaterializeTemporaryExpr>(E);
+      assert(MTE->getStorageDuration() == SD_Static);
+      SmallVector<const Expr *, 2> CommaLHSs;
+      SmallVector<SubobjectAdjustment, 2> Adjustments;
+      const Expr *Inner = MTE->getSubExpr()
+                       ->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
+      return CGM.GetAddrOfGlobalTemporary(MTE, Inner);
+    }
+    }
+
+    return ConstantAddress::invalid();
+  }
 };
 
 }  // end anonymous namespace.
@@ -1708,6 +1840,263 @@
   return getTargetCodeGenInfo().getNullPointer(*this, T, QT);
 }
 
+llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E,
+                                                QualType DestType,
+                                                CodeGenFunction *CGF) {
+  Expr::EvalResult Result;
+  bool Success = false;
+
+  if (DestType->isReferenceType())
+    Success = E->EvaluateAsLValue(Result, Context);
+  else
+    Success = E->EvaluateAsRValue(Result, Context);
+
+  llvm::Constant *C = nullptr;
+  if (Success && !Result.HasSideEffects)
+    C = EmitConstantValue(Result.Val, DestType, CGF);
+  else {
+    ConstantEmitter Emitter(*this, CGF);
+    // FIXME: Is this a DestType?
+    C = ConstExprEmitter(Emitter).Visit(const_cast<Expr*>(E), DestType);
+  }
+
+  if (C && C->getType()->isIntegerTy(1)) {
+    llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
+    C = llvm::ConstantExpr::getZExt(C, BoolTy);
+  }
+  return C;
+}
+
+llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,
+                                                 QualType DestType,
+                                                 CodeGenFunction *CGF) {
+  // For an _Atomic-qualified constant, we may need to add tail padding.
+  if (auto *AT = DestType->getAs<AtomicType>()) {
+    QualType InnerType = AT->getValueType();
+    auto *Inner = EmitConstantValue(Value, InnerType, CGF);
+
+    uint64_t InnerSize = Context.getTypeSize(InnerType);
+    uint64_t OuterSize = Context.getTypeSize(DestType);
+    if (InnerSize == OuterSize)
+      return Inner;
+
+    assert(InnerSize < OuterSize && "emitted over-large constant for atomic");
+    llvm::Constant *Elts[] = {
+      Inner,
+      llvm::ConstantAggregateZero::get(
+          llvm::ArrayType::get(Int8Ty, (OuterSize - InnerSize) / 8))
+    };
+    return llvm::ConstantStruct::getAnon(Elts);
+  }
+
+  switch (Value.getKind()) {
+  case APValue::None:
+  case APValue::Indeterminate:
+  case APValue::FixedPoint:
+    llvm_unreachable("Unsupported value type.");
+  case APValue::LValue: {
+    llvm::Type *DestTy = getTypes().ConvertTypeForMem(DestType);
+    llvm::Constant *Offset =
+      llvm::ConstantInt::get(Int64Ty, Value.getLValueOffset().getQuantity());
+
+    llvm::Constant *C = nullptr;
+
+    if (APValue::LValueBase LVBase = Value.getLValueBase()) {
+      // An array can be represented as an lvalue referring to the base.
+      if (isa<llvm::ArrayType>(DestTy)) {
+        assert(Offset->isNullValue() && "offset on array initializer");
+        ConstantEmitter Emitter(*this, CGF);
+        /// FIXME: Is this the right ParamTy?
+        return ConstExprEmitter(Emitter).Visit(
+          const_cast<Expr*>(LVBase.get<const Expr*>()), DestType);
+      }
+
+      ConstantEmitter Emitter(*this, CGF);
+      C = ConstExprEmitter(Emitter).EmitLValue(LVBase).getPointer();
+
+      // Apply offset if necessary.
+      if (!Offset->isNullValue()) {
+        unsigned AS = C->getType()->getPointerAddressSpace();
+        llvm::Type *CharPtrTy = Int8Ty->getPointerTo(AS);
+        llvm::Constant *Casted = llvm::ConstantExpr::getBitCast(C, CharPtrTy);
+        Casted = llvm::ConstantExpr::getGetElementPtr(Int8Ty, Casted, Offset);
+        C = llvm::ConstantExpr::getPointerCast(Casted, C->getType());
+      }
+
+      // Convert to the appropriate type; this could be an lvalue for
+      // an integer.
+      if (isa<llvm::PointerType>(DestTy))
+        return llvm::ConstantExpr::getPointerCast(C, DestTy);
+
+      return llvm::ConstantExpr::getPtrToInt(C, DestTy);
+    } else {
+      C = Offset;
+
+      // Convert to the appropriate type; this could be an lvalue for
+      // an integer.
+      if (auto PT = dyn_cast<llvm::PointerType>(DestTy)) {
+        if (Value.isNullPointer())
+          return getNullPointer(PT, DestType);
+        // Convert the integer to a pointer-sized integer before converting it
+        // to a pointer.
+        C = llvm::ConstantExpr::getIntegerCast(
+            C, getDataLayout().getIntPtrType(DestTy),
+            /*isSigned=*/false);
+        return llvm::ConstantExpr::getIntToPtr(C, DestTy);
+      }
+
+      // If the types don't match this should only be a truncate.
+      if (C->getType() != DestTy)
+        return llvm::ConstantExpr::getTrunc(C, DestTy);
+
+      return C;
+    }
+  }
+  case APValue::Int:
+    return llvm::ConstantInt::get(VMContext, Value.getInt());
+  case APValue::ComplexInt: {
+    llvm::Constant *Complex[2];
+
+    Complex[0] = llvm::ConstantInt::get(VMContext,
+                                        Value.getComplexIntReal());
+    Complex[1] = llvm::ConstantInt::get(VMContext,
+                                        Value.getComplexIntImag());
+
+    // FIXME: the target may want to specify that this is packed.
+    llvm::StructType *STy =
+        llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType());
+    return llvm::ConstantStruct::get(STy, Complex);
+  }
+  case APValue::Float: {
+    const llvm::APFloat &Init = Value.getFloat();
+    if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
+        !Context.getLangOpts().NativeHalfType &&
+        !Context.getLangOpts().HalfArgsAndReturns)
+      return llvm::ConstantInt::get(VMContext, Init.bitcastToAPInt());
+    else
+      return llvm::ConstantFP::get(VMContext, Init);
+  }
+  case APValue::ComplexFloat: {
+    llvm::Constant *Complex[2];
+
+    Complex[0] = llvm::ConstantFP::get(VMContext,
+                                       Value.getComplexFloatReal());
+    Complex[1] = llvm::ConstantFP::get(VMContext,
+                                       Value.getComplexFloatImag());
+
+    // FIXME: the target may want to specify that this is packed.
+    llvm::StructType *STy =
+        llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType());
+    return llvm::ConstantStruct::get(STy, Complex);
+  }
+  case APValue::Vector: {
+    unsigned NumElts = Value.getVectorLength();
+    SmallVector<llvm::Constant *, 4> Inits(NumElts);
+
+    for (unsigned I = 0; I != NumElts; ++I) {
+      const APValue &Elt = Value.getVectorElt(I);
+      if (Elt.isInt())
+        Inits[I] = llvm::ConstantInt::get(VMContext, Elt.getInt());
+      else if (Elt.isFloat())
+        Inits[I] = llvm::ConstantFP::get(VMContext, Elt.getFloat());
+      else
+        llvm_unreachable("unsupported vector element type");
+    }
+    return llvm::ConstantVector::get(Inits);
+  }
+  case APValue::AddrLabelDiff: {
+    const AddrLabelExpr *LHSExpr = Value.getAddrLabelDiffLHS();
+    const AddrLabelExpr *RHSExpr = Value.getAddrLabelDiffRHS();
+    llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF);
+    llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF);
+
+    // Compute difference
+    llvm::Type *ResultType = getTypes().ConvertType(DestType);
+    LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy);
+    RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
+    llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
+
+    // LLVM is a bit sensitive about the exact format of the
+    // address-of-label difference; make sure to truncate after
+    // the subtraction.
+    return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
+  }
+  case APValue::Struct:
+  case APValue::Union:
+  {
+    ConstantEmitter Emitter(*this, CGF);
+    return ConstStructBuilder::BuildStruct(Emitter, Value, DestType);
+  }
+  case APValue::Array: {
+    const ArrayType *CAT = Context.getAsArrayType(DestType);
+    unsigned NumElements = Value.getArraySize();
+    unsigned NumInitElts = Value.getArrayInitializedElts();
+
+    // Emit array filler, if there is one.
+    llvm::Constant *Filler = nullptr;
+    if (Value.hasArrayFiller())
+      Filler = EmitConstantValueForMemory(Value.getArrayFiller(),
+                                          CAT->getElementType(), CGF);
+
+    // Emit initializer elements.
+    llvm::Type *CommonElementType =
+        getTypes().ConvertType(CAT->getElementType());
+
+    // Try to use a ConstantAggregateZero if we can.
+    if (Filler && Filler->isNullValue() && !NumInitElts) {
+      llvm::ArrayType *AType =
+          llvm::ArrayType::get(CommonElementType, NumElements);
+      return llvm::ConstantAggregateZero::get(AType);
+    }
+
+    std::vector<llvm::Constant*> Elts;
+    Elts.reserve(NumElements);
+    for (unsigned I = 0; I < NumElements; ++I) {
+      llvm::Constant *C = Filler;
+      if (I < NumInitElts)
+        C = EmitConstantValueForMemory(Value.getArrayInitializedElt(I),
+                                       CAT->getElementType(), CGF);
+      else
+        assert(Filler && "Missing filler for implicit elements of initializer");
+      if (I == 0)
+        CommonElementType = C->getType();
+      else if (C->getType() != CommonElementType)
+        CommonElementType = nullptr;
+      Elts.push_back(C);
+    }
+
+    if (!CommonElementType) {
+      // FIXME: Try to avoid packing the array
+      std::vector<llvm::Type*> Types;
+      Types.reserve(NumElements);
+      for (unsigned i = 0, e = Elts.size(); i < e; ++i)
+        Types.push_back(Elts[i]->getType());
+      llvm::StructType *SType = llvm::StructType::get(VMContext, Types, true);
+      return llvm::ConstantStruct::get(SType, Elts);
+    }
+
+    llvm::ArrayType *AType =
+      llvm::ArrayType::get(CommonElementType, NumElements);
+    return llvm::ConstantArray::get(AType, Elts);
+  }
+  case APValue::MemberPointer:
+    return getCXXABI().EmitMemberPointer(Value, DestType);
+  }
+  llvm_unreachable("Unknown APValue kind");
+}
+
+llvm::Constant *
+CodeGenModule::EmitConstantValueForMemory(const APValue &Value,
+                                          QualType DestType,
+                                          CodeGenFunction *CGF) {
+  llvm::Constant *C = EmitConstantValue(Value, DestType, CGF);
+  if (C->getType()->isIntegerTy(1)) {
+    llvm::Type *BoolTy = getTypes().ConvertTypeForMem(DestType);
+    C = llvm::ConstantExpr::getZExt(C, BoolTy);
+  }
+  return C;
+}
+
 namespace {
 /// A struct which can be used to peephole certain kinds of finalization
 /// that normally happen during l-value emission.
Index: clang/lib/CodeGen/CGExprAgg.cpp
===================================================================
--- clang/lib/CodeGen/CGExprAgg.cpp
+++ clang/lib/CodeGen/CGExprAgg.cpp
@@ -126,7 +126,17 @@
   }
 
   void VisitConstantExpr(ConstantExpr *E) {
-    return Visit(E->getSubExpr());
+    if (E->hasAPValueResult()) {
+      // Create a temporary for the value and store the constant.
+      llvm::Constant *Const = CGF.EmitConstantValue(
+          E->getAPValueResult(), E->getType());
+      Address Addr = CGF.CreateMemTemp(E->getType());
+      CGF.InitTempAlloca(Addr, Const);
+      RValue RV = RValue::getAggregate(Addr);
+      EmitFinalDestCopy(E->getType(), RV);
+    } else {
+      Visit(E->getSubExpr());
+    }
   }
 
   // l-values.
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1284,8 +1284,19 @@
     return EmitVAArgExprLValue(cast<VAArgExpr>(E));
   case Expr::DeclRefExprClass:
     return EmitDeclRefLValue(cast<DeclRefExpr>(E));
-  case Expr::ConstantExprClass:
-    return EmitLValue(cast<ConstantExpr>(E)->getSubExpr());
+  case Expr::ConstantExprClass: {
+    const ConstantExpr *CE = cast<ConstantExpr>(E);
+
+    if (CE->hasAPValueResult()) {
+      QualType T = getContext().getPointerType(CE->getType());
+      llvm::Constant *C = EmitConstantValue(CE->getAPValueResult(), T);
+      ConstantAddress Addr(C, getContext().getTypeAlignInChars(T));
+      LValueBaseInfo BI;
+      return LValue::MakeAddr(Addr, T, getContext(), BI, TBAAAccessInfo());
+    }
+
+    return EmitLValue(CE->getSubExpr());
+  }
   case Expr::ParenExprClass:
     return EmitLValue(cast<ParenExpr>(E)->getSubExpr());
   case Expr::GenericSelectionExprClass:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to