]> granicus.if.org Git - clang/commitdiff
In C++, allow us to emit a global as 'constant' even if it has class
authorDouglas Gregor <dgregor@apple.com>
Sat, 7 May 2011 22:06:45 +0000 (22:06 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 7 May 2011 22:06:45 +0000 (22:06 +0000)
type, so long as it is known to have a constant initializer and the
class type is a POD class. Fixes <rdar://problem/9306265>.

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

lib/CodeGen/CodeGenModule.cpp
test/CodeGenCXX/global-llvm-constant.cpp

index 2ccd6a782c28559ce8e6f71f22660110a2e894f2..d99230b556ec76cf0b4a0b4ed3fade8a379bbcc2 100644 (file)
@@ -938,14 +938,17 @@ CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,
   return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false);
 }
 
-static bool DeclIsConstantGlobal(ASTContext &Context, const VarDecl *D) {
+static bool DeclIsConstantGlobal(ASTContext &Context, const VarDecl *D,
+                                 bool ConstantInit) {
   if (!D->getType().isConstant(Context) && !D->getType()->isReferenceType())
     return false;
-  if (Context.getLangOptions().CPlusPlus &&
-      Context.getBaseElementType(D->getType())->getAs<RecordType>()) {
-    // FIXME: We should do something fancier here!
-    return false;
+  
+  if (Context.getLangOptions().CPlusPlus) {
+    if (const RecordType *Record 
+          = Context.getBaseElementType(D->getType())->getAs<RecordType>())
+      return ConstantInit && cast<CXXRecordDecl>(Record->getDecl())->isPOD();
   }
+  
   return true;
 }
 
@@ -1002,7 +1005,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(llvm::StringRef MangledName,
   if (D) {
     // FIXME: This code is overly simple and should be merged with other global
     // handling.
-    GV->setConstant(DeclIsConstantGlobal(Context, D));
+    GV->setConstant(DeclIsConstantGlobal(Context, D, false));
 
     // Set linkage and visibility in case we never see a definition.
     NamedDecl::LinkageInfo LV = D->getLinkageAndVisibility();
@@ -1284,7 +1287,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
 
   // If it is safe to mark the global 'constant', do so now.
   GV->setConstant(false);
-  if (!NonConstInit && DeclIsConstantGlobal(Context, D))
+  if (!NonConstInit && DeclIsConstantGlobal(Context, D, true))
     GV->setConstant(true);
 
   GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
index ef1dcf0c59bf2bc1dad415364ea2a43df3740615..b23337d634cbe8ff3f6699b664ebc2b4fe6ca60a 100644 (file)
@@ -8,3 +8,13 @@ struct A {
 const A x;
 
 // CHECK: @_ZL1x = internal global
+
+struct X {
+  int (*fp)(int, int);
+};
+
+int add(int x, int y) { return x + y; }
+
+// CHECK: @x2 = constant
+extern const X x2;
+const X x2 = { &add };