Hi rsmith,

The limitation to POD types stems from the times when our constant emission
logic was way less sophisticated and much more buggy. Emit all constant
initializers as LLVM constants.

This reuses the logic for static vars, so assert that we don't accidentally
introduce a static initializer. I tried to cover the issues mentioned in the
commit with additional test cases.

http://reviews.llvm.org/D8137

Files:
  lib/CodeGen/CGDecl.cpp
  test/CodeGenCXX/const-init-cxx11.cpp
  test/CodeGenCXX/const-init.cpp
  test/CodeGenCXX/member-init-anon-union.cpp
  test/CodeGenCXX/microsoft-interface.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -886,24 +886,17 @@
 
     // If this value is an array or struct with a statically determinable
     // constant initializer, there are optimizations we can do.
-    //
-    // TODO: We should constant-evaluate the initializer of any variable,
-    // as long as it is initialized by a constant expression. Currently,
-    // isConstantInitializer produces wrong answers for structs with
-    // reference or bitfield members, and a few other cases, and checking
-    // for POD-ness protects us from some of these.
     if (D.getInit() && (Ty->isArrayType() || Ty->isRecordType()) &&
         (D.isConstexpr() ||
-         ((Ty.isPODType(getContext()) ||
-           getContext().getBaseElementType(Ty)->isObjCObjectPointerType()) &&
-          D.getInit()->isConstantInitializer(getContext(), false)))) {
-
+         D.getInit()->isConstantInitializer(getContext(), false))) {
       // If the variable's a const type, and it's neither an NRVO
       // candidate nor a __block variable and has no mutable members,
       // emit it as a global instead.
       if (CGM.getCodeGenOpts().MergeAllConstants && !NRVO && !isByRef &&
           CGM.isTypeConstant(Ty, true)) {
         EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
+        assert(cast<llvm::GlobalVariable>(LocalDeclMap[&D])->isConstant() &&
+               "Constant initializer not emitted as constant!");
 
         emission.Address = nullptr; // signal this condition to later callbacks
         assert(emission.wasEmittedAsGlobal());
Index: test/CodeGenCXX/const-init-cxx11.cpp
===================================================================
--- test/CodeGenCXX/const-init-cxx11.cpp
+++ test/CodeGenCXX/const-init-cxx11.cpp
@@ -605,6 +605,21 @@
 const char *f() { return &X::p; }
 }
 
+namespace ConstExprArray {
+  class C {
+    int x;
+  public:
+    constexpr C(int x) : x(x) {}
+  };
+  void f(const C *);
+  void g() {
+// CHECK-LABEL: _ZN14ConstExprArray1gEv
+// CHECK: call void @_ZN14ConstExprArray1fEPKNS_1CE{{.*}}@_ZZN14ConstExprArray1gEvE2Cs
+    const C Cs[] = {1, 2, 3, 4};
+    f(Cs);
+  }
+}
+
 // VirtualMembers::TemplateClass::templateMethod() must be defined in this TU,
 // not just declared.
 // CHECK: define linkonce_odr void @_ZN14VirtualMembers13TemplateClassIiE14templateMethodEv(%"struct.VirtualMembers::TemplateClass"* %this)
Index: test/CodeGenCXX/const-init.cpp
===================================================================
--- test/CodeGenCXX/const-init.cpp
+++ test/CodeGenCXX/const-init.cpp
@@ -76,3 +76,24 @@
 int arr[2];
 // CHECK: @pastEnd = constant i32* bitcast (i8* getelementptr (i8* bitcast ([2 x i32]* @arr to i8*), i64 8) to i32*)
 int &pastEnd = arr[2];
+
+struct RefMember {
+  int &Ref;
+};
+
+RefMember initRefMember() {
+  // CHECK: {{.*}}RefMemberInit{{.*}} = {{.*}}constant{{.*}}@arr
+  RefMember RefMemberInit = { arr[0] };
+  return RefMemberInit;
+}
+
+struct BitFieldMember {
+  int a : 1;
+  int b : 3;
+};
+
+BitFieldMember initBitFieldMember() {
+  // CHECK: {{.*}}BitFieldMemberInit{{.*}} = {{.*}}constant{{.*}}i8 5
+  BitFieldMember BitFieldMemberInit = { 1, 2 };
+  return BitFieldMemberInit;
+}
Index: test/CodeGenCXX/member-init-anon-union.cpp
===================================================================
--- test/CodeGenCXX/member-init-anon-union.cpp
+++ test/CodeGenCXX/member-init-anon-union.cpp
@@ -19,7 +19,7 @@
 int g() {
   union {
     int a;
-    int b = 81;
+    int b = make_a();
   };
   // CHECK-LABEL: define {{.*}}_Z1gv
   // CHECK-NOT: }
@@ -49,7 +49,8 @@
 
 // CHECK: define {{.*}}@"[[CONSTRUCT_LOCAL]]C2Ev"
 // CHECK-NOT: }
-// CHECK: store i32 81
+// CHECK: call {{.*}}@_Z6make_a
+// CHECK: store i32
 
 // CHECK-LABEL: define {{.*}} @_ZN1BC2Ev(
 // CHECK: call void @_ZN1AC1Ev(
Index: test/CodeGenCXX/microsoft-interface.cpp
===================================================================
--- test/CodeGenCXX/microsoft-interface.cpp
+++ test/CodeGenCXX/microsoft-interface.cpp
@@ -7,6 +7,7 @@
 };
 
 struct S : I {
+  mutable int i; // Prevent constant folding.
   virtual int test() override {
     return I::test();
   }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to