]> granicus.if.org Git - clang/commitdiff
CodeGen: Correctly initialize bitfields with non-constant initializers
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 14 Mar 2015 22:24:38 +0000 (22:24 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 14 Mar 2015 22:24:38 +0000 (22:24 +0000)
It is possible to construct an initializer for a bitfield which is not
constant.  Instead of emitting code to initialize the field before the
execution of main, clang would crash.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@232285 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprConstant.cpp
test/CodeGenCXX/const-init.cpp

index 54f7eee6791e648cbe038047f6ee1af75da3f50f..7406354bdc82efd9b0d93e7847c549c0d5909ce7 100644 (file)
@@ -383,14 +383,19 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) {
 
     if (!EltInit)
       return false;
-    
+
     if (!Field->isBitField()) {
       // Handle non-bitfield members.
       AppendField(*Field, Layout.getFieldOffset(FieldNo), EltInit);
     } else {
       // Otherwise we have a bitfield.
-      AppendBitField(*Field, Layout.getFieldOffset(FieldNo),
-                     cast<llvm::ConstantInt>(EltInit));
+      if (auto *CI = dyn_cast<llvm::ConstantInt>(EltInit)) {
+        AppendBitField(*Field, Layout.getFieldOffset(FieldNo), CI);
+      } else {
+        // We are trying to initialize a bitfield with a non-trivial constant,
+        // this must require run-time code.
+        return false;
+      }
     }
   }
 
index 3dc8f67303001c047e6667c01fd84900e3dd5db0..deb923a708905ff663603d258405f4075fcf9e4f 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: not %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
 
 // CHECK: @a = global i32 10
 int a = 10;
@@ -76,3 +76,10 @@ int &i = reinterpret_cast<int&>(PR9558);
 int arr[2];
 // CHECK: @pastEnd = constant i32* bitcast (i8* getelementptr (i8, i8* bitcast ([2 x i32]* @arr to i8*), i64 8) to i32*)
 int &pastEnd = arr[2];
+
+struct X {
+  long n : 8;
+};
+long k;
+X x = {(long)&k};
+// CHECK: store i8 ptrtoint (i64* @k to i8), i8* getelementptr inbounds (%struct.X, %struct.X* @x, i32 0, i32 0)