arphaman updated this revision to Diff 111956.
arphaman marked an inline comment as done.
arphaman added a comment.

- Get rid of the `AllowSideEffects` argument.
- Get rid of the old integer field evaluation code.


Repository:
  rL LLVM

https://reviews.llvm.org/D36876

Files:
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/CodeGen/CodeGenFunction.h
  test/CodeGenCXX/member-expr-references-variable.cpp
  test/CodeGenCXX/temporaries.cpp

Index: test/CodeGenCXX/temporaries.cpp
===================================================================
--- test/CodeGenCXX/temporaries.cpp
+++ test/CodeGenCXX/temporaries.cpp
@@ -673,18 +673,20 @@
     vi4b w;
   };
   // CHECK: alloca
-  // CHECK: extractelement
-  // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE_
+  // CHECK: store i32 0, i32* @_ZGRN6Vector1rE_
   // CHECK: store i32* @_ZGRN6Vector1rE_, i32** @_ZN6Vector1rE,
   int &&r = S().v[1];
 
   // CHECK: alloca
-  // CHECK: extractelement
-  // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1sE_
+  // CHECK: store i32 0, i32* @_ZGRN6Vector1sE_
   // CHECK: store i32* @_ZGRN6Vector1sE_, i32** @_ZN6Vector1sE,
   int &&s = S().w[1];
-  // FIXME PR16204: The following code leads to an assertion in Sema.
-  //int &&s = S().w.y;
+
+  // CHECK: alloca
+  // CHECK: extractelement
+  // CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector2s2E_
+  // CHECK: store i32* @_ZGRN6Vector2s2E_, i32** @_ZN6Vector2s2E,
+  int &&s2 = S().w.y;
 }
 
 namespace ImplicitTemporaryCleanup {
Index: test/CodeGenCXX/member-expr-references-variable.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/member-expr-references-variable.cpp
@@ -0,0 +1,82 @@
+// RUN: %clang_cc1 -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+struct Struct {
+   constexpr static const char *name = "foo";
+
+   constexpr static __complex float complexValue = 42.0;
+
+   Struct();
+   Struct(int x);
+};
+
+void use(int n, const char *c);
+
+Struct *getPtr();
+
+// CHECK: @[[STR:.*]] = private unnamed_addr constant [4 x i8] c"foo\00", align 1
+
+void scalarStaticVariableInMemberExpr(Struct *ptr, Struct &ref) {
+  use(1, Struct::name);
+// CHECK: call void @_Z3useiPKc(i32 1, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  Struct s;
+  use(2, s.name);
+// CHECK: call void @_Z3useiPKc(i32 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(3, ptr->name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 3, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(4, ref.name);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: call void @_Z3useiPKc(i32 4, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(5, Struct(2).name);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: call void @_Z3useiPKc(i32 5, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+  use(6, getPtr()->name);
+// CHECK: call %struct.Struct* @_Z6getPtrv()
+// CHECK: call void @_Z3useiPKc(i32 6, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[STR]], i32 0, i32 0))
+}
+
+void use(int n, __complex float v);
+
+void complexStaticVariableInMemberExpr(Struct *ptr, Struct &ref) {
+  use(1, Struct::complexValue);
+// CHECK: store float 4.200000e+01, float* %[[coerce0:.*]].{{.*}}, align 4
+// CHECK: store float 0.000000e+00, float* %[[coerce0]].{{.*}}, align 4
+// CHECK: %[[cast0:.*]] = bitcast { float, float }* %[[coerce0]] to <2 x float>*
+// CHECK: %[[vector0:.*]] = load <2 x float>, <2 x float>* %[[cast0]], align 4
+// CHECK: call void @_Z3useiCf(i32 1, <2 x float> %[[vector0]])
+  Struct s;
+  use(2, s.complexValue);
+// CHECK: store float 4.200000e+01, float* %[[coerce1:.*]].{{.*}}, align 4
+// CHECK: store float 0.000000e+00, float* %[[coerce1]].{{.*}}, align 4
+// CHECK: %[[cast1:.*]] = bitcast { float, float }* %[[coerce1]] to <2 x float>*
+// CHECK: %[[vector1:.*]] = load <2 x float>, <2 x float>* %[[cast1]], align 4
+// CHECK: call void @_Z3useiCf(i32 2, <2 x float> %[[vector1]])
+  use(3, ptr->complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.200000e+01, float* %[[coerce2:.*]].{{.*}}, align 4
+// CHECK: store float 0.000000e+00, float* %[[coerce2]].{{.*}}, align 4
+// CHECK: %[[cast2:.*]] = bitcast { float, float }* %[[coerce2]] to <2 x float>*
+// CHECK: %[[vector2:.*]] = load <2 x float>, <2 x float>* %[[cast2]], align 4
+// CHECK: call void @_Z3useiCf(i32 3, <2 x float> %[[vector2]])
+  use(4, ref.complexValue);
+// CHECK: load %struct.Struct*, %struct.Struct** %{{.*}}, align 8
+// CHECK: store float 4.200000e+01, float* %[[coerce3:.*]].{{.*}}, align 4
+// CHECK: store float 0.000000e+00, float* %[[coerce3]].{{.*}}, align 4
+// CHECK: %[[cast3:.*]] = bitcast { float, float }* %[[coerce3]] to <2 x float>*
+// CHECK: %[[vector3:.*]] = load <2 x float>, <2 x float>* %[[cast3]], align 4
+// CHECK: call void @_Z3useiCf(i32 4, <2 x float> %[[vector3]])
+  use(5, Struct(2).complexValue);
+// CHECK: call void @_ZN6StructC1Ei(%struct.Struct* %{{.*}}, i32 2)
+// CHECK: store float 4.200000e+01, float* %[[coerce4:.*]].{{.*}}, align 4
+// CHECK: store float 0.000000e+00, float* %[[coerce4]].{{.*}}, align 4
+// CHECK: %[[cast4:.*]] = bitcast { float, float }* %[[coerce4]] to <2 x float>*
+// CHECK: %[[vector4:.*]] = load <2 x float>, <2 x float>* %[[cast4]], align 4
+// CHECK: call void @_Z3useiCf(i32 5, <2 x float> %[[vector4]])
+  use(6, getPtr()->complexValue);
+// CHECK: call %struct.Struct* @_Z6getPtrv()
+// CHECK: store float 4.200000e+01, float* %[[coerce5:.*]].{{.*}}, align 4
+// CHECK: store float 0.000000e+00, float* %[[coerce5]].{{.*}}, align 4
+// CHECK: %[[cast5:.*]] = bitcast { float, float }* %[[coerce5]] to <2 x float>*
+// CHECK: %[[vector5:.*]] = load <2 x float>, <2 x float>* %[[cast5]], align 4
+// CHECK: call void @_Z3useiCf(i32 6, <2 x float> %[[vector5]])
+}
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -3158,7 +3158,8 @@
     }
   };
 
-  ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr);
+  ConstantEmission tryEmitDeclRefOrMemberExprAsConstant(Expr *E,
+                                                        ValueDecl *Value);
 
   RValue EmitPseudoObjectRValue(const PseudoObjectExpr *e,
                                 AggValueSlot slot = AggValueSlot::ignored());
@@ -3190,7 +3191,7 @@
   LValue EmitStmtExprLValue(const StmtExpr *E);
   LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E);
   LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E);
-  void   EmitDeclRefExprDbgValue(const DeclRefExpr *E, const APValue &Init);
+  void   EmitDeclRefOrMemberExprDbgValue(const Expr *E, const APValue &Init);
 
   //===--------------------------------------------------------------------===//
   //                         Scalar Expression Emission
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -2007,12 +2007,17 @@
   return EmitLValue(E).getAddress();
 }
 
-void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E,
-                                              const APValue &Init) {
+void CodeGenFunction::EmitDeclRefOrMemberExprDbgValue(const Expr *E,
+                                                      const APValue &Init) {
+  const ValueDecl *VD;
+  if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
+    VD = DRE->getDecl();
+  else
+    VD = cast<MemberExpr>(E)->getMemberDecl();
   assert(!Init.isUninit() && "Invalid DeclRefExpr initializer!");
   if (CGDebugInfo *Dbg = getDebugInfo())
     if (CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo)
-      Dbg->EmitGlobalVariable(E->getDecl(), Init);
+      Dbg->EmitGlobalVariable(VD, Init);
 }
 
 CodeGenFunction::PeepholeProtection
Index: lib/CodeGen/CGExprScalar.cpp
===================================================================
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -429,13 +429,20 @@
   }
 
   // l-values.
-  Value *VisitDeclRefExpr(DeclRefExpr *E) {
-    if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
+  Value *tryEmitDeclRefOrMemberExprAsConstant(Expr *E, ValueDecl *VD) {
+    if (CodeGenFunction::ConstantEmission result =
+            CGF.tryEmitDeclRefOrMemberExprAsConstant(E, VD)) {
       if (result.isReference())
         return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
                                 E->getExprLoc());
       return result.getValue();
     }
+    return nullptr;
+  }
+
+  Value *VisitDeclRefExpr(DeclRefExpr *E) {
+    if (Value *V = tryEmitDeclRefOrMemberExprAsConstant(E, E->getDecl()))
+      return V;
     return EmitLoadOfLValue(E);
   }
 
@@ -1299,13 +1306,12 @@
 }
 
 Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
-  llvm::APSInt Value;
-  if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
+  if (Value *V = tryEmitDeclRefOrMemberExprAsConstant(E, E->getMemberDecl())) {
     if (E->isArrow())
       CGF.EmitScalarExpr(E->getBase());
     else
       EmitLValue(E->getBase());
-    return Builder.getInt(Value);
+    return V;
   }
 
   return EmitLoadOfLValue(E);
@@ -1778,7 +1784,7 @@
   }
 
   case CK_IntToOCLSampler:
-    return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF);
+    return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF);
 
   } // end of switch
 
Index: lib/CodeGen/CGExprComplex.cpp
===================================================================
--- lib/CodeGen/CGExprComplex.cpp
+++ lib/CodeGen/CGExprComplex.cpp
@@ -122,16 +122,25 @@
 
 
   // l-values.
-  ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
-    if (CodeGenFunction::ConstantEmission result = CGF.tryEmitAsConstant(E)) {
+  Optional<ComplexPairTy> tryEmitDeclRefOrMemberExprAsConstant(Expr *E,
+                                                               ValueDecl *VD) {
+    if (CodeGenFunction::ConstantEmission result =
+            CGF.tryEmitDeclRefOrMemberExprAsConstant(E, VD)) {
       if (result.isReference())
         return EmitLoadOfLValue(result.getReferenceLValue(CGF, E),
                                 E->getExprLoc());
 
       llvm::Constant *pair = result.getValue();
       return ComplexPairTy(pair->getAggregateElement(0U),
                            pair->getAggregateElement(1U));
     }
+    return None;
+  }
+
+  ComplexPairTy VisitDeclRefExpr(DeclRefExpr *E) {
+    auto Constant = tryEmitDeclRefOrMemberExprAsConstant(E, E->getDecl());
+    if (Constant)
+      return *Constant;
     return EmitLoadOfLValue(E);
   }
   ComplexPairTy VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
@@ -141,7 +150,18 @@
     return CGF.EmitObjCMessageExpr(E).getComplexVal();
   }
   ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); }
-  ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); }
+  ComplexPairTy VisitMemberExpr(MemberExpr *ME) {
+    auto Constant =
+        tryEmitDeclRefOrMemberExprAsConstant(ME, ME->getMemberDecl());
+    if (Constant) {
+      if (ME->isArrow())
+        CGF.EmitScalarExpr(ME->getBase());
+      else
+        CGF.EmitLValue(ME->getBase());
+      return *Constant;
+    }
+    return EmitLoadOfLValue(ME);
+  }
   ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) {
     if (E->isGLValue())
       return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E), E->getExprLoc());
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp
+++ lib/CodeGen/CGExprAgg.cpp
@@ -132,8 +132,8 @@
     // actively preventing us from listing variables in the captures
     // list of a block.
     if (E->getDecl()->getType()->isReferenceType()) {
-      if (CodeGenFunction::ConstantEmission result
-            = CGF.tryEmitAsConstant(E)) {
+      if (CodeGenFunction::ConstantEmission result =
+              CGF.tryEmitDeclRefOrMemberExprAsConstant(E, E->getDecl())) {
         EmitFinalDestCopy(E->getType(), result.getReferenceLValue(CGF, E));
         return;
       }
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -1277,17 +1277,22 @@
 /// in a block or lambda, which means const int variables or constexpr
 /// literals or similar.
 CodeGenFunction::ConstantEmission
-CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
-  ValueDecl *value = refExpr->getDecl();
+CodeGenFunction::tryEmitDeclRefOrMemberExprAsConstant(Expr *E,
+                                                      ValueDecl *Value) {
+  assert((isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) && "invalid expr");
+  bool AllowSideEffects = true;
 
   // The value needs to be an enum constant or a constant variable.
   ConstantEmissionKind CEK;
-  if (isa<ParmVarDecl>(value)) {
+  if (isa<ParmVarDecl>(Value)) {
     CEK = CEK_None;
-  } else if (auto *var = dyn_cast<VarDecl>(value)) {
+  } else if (auto *var = dyn_cast<VarDecl>(Value)) {
     CEK = checkVarTypeForConstantEmission(var->getType());
-  } else if (isa<EnumConstantDecl>(value)) {
+  } else if (isa<EnumConstantDecl>(Value)) {
     CEK = CEK_AsValueOnly;
+  } else if (isa<FieldDecl>(Value) && isa<MemberExpr>(E)) {
+    CEK = CEK_AsValueOnly;
+    AllowSideEffects = false;
   } else {
     CEK = CEK_None;
   }
@@ -1298,38 +1303,39 @@
   QualType resultType;
 
   // It's best to evaluate all the way as an r-value if that's permitted.
-  if (CEK != CEK_AsReferenceOnly &&
-      refExpr->EvaluateAsRValue(result, getContext())) {
+  if (CEK != CEK_AsReferenceOnly && E->EvaluateAsRValue(result, getContext())) {
     resultIsReference = false;
-    resultType = refExpr->getType();
+    resultType = E->getType();
 
-  // Otherwise, try to evaluate as an l-value.
+    // Otherwise, try to evaluate as an l-value.
   } else if (CEK != CEK_AsValueOnly &&
-             refExpr->EvaluateAsLValue(result, getContext())) {
+             E->EvaluateAsLValue(result, getContext())) {
     resultIsReference = true;
-    resultType = value->getType();
+    resultType = Value->getType();
 
-  // Failure.
+    // Failure.
   } else {
     return ConstantEmission();
   }
 
   // In any case, if the initializer has side-effects, abandon ship.
-  if (result.HasSideEffects)
+  if (result.HasSideEffects && !AllowSideEffects) {
+    assert(!isa<DeclRefExpr>(E) && "declrefs should not have side effects");
     return ConstantEmission();
+  }
 
   // Emit as a constant.
-  auto C = ConstantEmitter(*this).emitAbstract(refExpr->getLocation(),
-                                               result.Val, resultType);
+  auto C = ConstantEmitter(*this).emitAbstract(E->getExprLoc(), result.Val,
+                                               resultType);
 
   // Make sure we emit a debug reference to the global variable.
   // This should probably fire even for
-  if (isa<VarDecl>(value)) {
-    if (!getContext().DeclMustBeEmitted(cast<VarDecl>(value)))
-      EmitDeclRefExprDbgValue(refExpr, result.Val);
-  } else {
-    assert(isa<EnumConstantDecl>(value));
-    EmitDeclRefExprDbgValue(refExpr, result.Val);
+  if (isa<VarDecl>(Value)) {
+    if (!getContext().DeclMustBeEmitted(cast<VarDecl>(Value)))
+      EmitDeclRefOrMemberExprDbgValue(E, result.Val);
+  } else if (!isa<FieldDecl>(Value)) {
+    assert(isa<EnumConstantDecl>(Value));
+    EmitDeclRefOrMemberExprDbgValue(E, result.Val);
   }
 
   // If we emitted a reference constant, we need to dereference that.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to