[cfe-commits] r150793 - in /cfe/trunk: lib/CodeGen/CGDecl.cpp lib/CodeGen/CodeGenModule.cpp lib/CodeGen/CodeGenModule.h test/CodeGenCXX/static-mutable.cpp

Richard Smith richard-llvm at metafoo.co.uk
Thu Feb 16 22:48:11 PST 2012


Author: rsmith
Date: Fri Feb 17 00:48:11 2012
New Revision: 150793

URL: http://llvm.org/viewvc/llvm-project?rev=150793&view=rev
Log:
Bug fix: do not emit static const local variables with mutable members
as constants.

Refactor and simplify all the separate checks for whether a type can be
emitted as a constant.

Added:
    cfe/trunk/test/CodeGenCXX/static-mutable.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=150793&r1=150792&r2=150793&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Feb 17 00:48:11 2012
@@ -255,14 +255,13 @@
     OldGV->eraseFromParent();
   }
 
+  GV->setConstant(CGM.isTypeConstant(D.getType(), true));
   GV->setInitializer(Init);
 
   if (hasNontrivialDestruction(D.getType())) {
     // We have a constant initializer, but a nontrivial destructor. We still
     // need to perform a guarded "initialization" in order to register the
-    // destructor. Since we're running a destructor on this variable, it can't
-    // be a constant even if it's const.
-    GV->setConstant(false);
+    // destructor.
     EmitCXXGuardedInit(D, GV, /*PerformInit*/false);
   }
 
@@ -775,7 +774,7 @@
       // If this value is a POD array or struct with a statically
       // determinable constant initializer, there are optimizations we can do.
       //
-      // TODO: we should constant-evaluate any variable of literal type
+      // 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
@@ -789,17 +788,13 @@
         // 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 && Ty.isConstQualified() &&
-            !NRVO && !isByRef && Ty->isLiteralType()) {
-          CXXRecordDecl *RD =
-            Ty->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
-          if (!RD || !RD->hasMutableFields()) {
-            EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
-
-            emission.Address = 0; // signal this condition to later callbacks
-            assert(emission.wasEmittedAsGlobal());
-            return emission;
-          }
+        if (CGM.getCodeGenOpts().MergeAllConstants && !NRVO && !isByRef &&
+            CGM.isTypeConstant(Ty, true)) {
+          EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
+
+          emission.Address = 0; // signal this condition to later callbacks
+          assert(emission.wasEmittedAsGlobal());
+          return emission;
         }
 
         // Otherwise, tell the initialization code that we're in this case.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=150793&r1=150792&r2=150793&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Fri Feb 17 00:48:11 2012
@@ -1101,18 +1101,23 @@
                                  ExtraAttrs);
 }
 
-static bool DeclIsConstantGlobal(ASTContext &Context, const VarDecl *D,
-                                 bool ConstantInit) {
-  if (!D->getType().isConstant(Context) && !D->getType()->isReferenceType())
+/// isTypeConstant - Determine whether an object of this type can be emitted
+/// as a constant.
+///
+/// If ExcludeCtor is true, the duration when the object's constructor runs
+/// will not be considered. The caller will need to verify that the object is
+/// not written to during its construction.
+bool CodeGenModule::isTypeConstant(QualType Ty, bool ExcludeCtor) {
+  if (!Ty.isConstant(Context) && !Ty->isReferenceType())
     return false;
-  
+
   if (Context.getLangOptions().CPlusPlus) {
-    if (const RecordType *Record 
-          = Context.getBaseElementType(D->getType())->getAs<RecordType>())
-      return ConstantInit && 
-             !cast<CXXRecordDecl>(Record->getDecl())->hasMutableFields();
+    if (const CXXRecordDecl *Record
+          = Context.getBaseElementType(Ty)->getAsCXXRecordDecl())
+      return ExcludeCtor && !Record->hasMutableFields() &&
+             Record->hasTrivialDestructor();
   }
-  
+
   return true;
 }
 
@@ -1169,7 +1174,7 @@
   if (D) {
     // FIXME: This code is overly simple and should be merged with other global
     // handling.
-    GV->setConstant(DeclIsConstantGlobal(Context, D, false));
+    GV->setConstant(isTypeConstant(D->getType(), false));
 
     // Set linkage and visibility in case we never see a definition.
     NamedDecl::LinkageInfo LV = D->getLinkageAndVisibility();
@@ -1450,13 +1455,11 @@
   GV->setInitializer(Init);
 
   // If it is safe to mark the global 'constant', do so now.
-  GV->setConstant(false);
-  if (!NeedsGlobalCtor && !NeedsGlobalDtor &&
-      DeclIsConstantGlobal(Context, D, true))
-    GV->setConstant(true);
+  GV->setConstant(!NeedsGlobalCtor && !NeedsGlobalDtor &&
+                  isTypeConstant(D->getType(), true));
 
   GV->setAlignment(getContext().getDeclAlign(D).getQuantity());
-  
+
   // Set the llvm linkage type as appropriate.
   llvm::GlobalValue::LinkageTypes Linkage = 
     GetLLVMLinkageVarDefinition(D, GV);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=150793&r1=150792&r2=150793&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri Feb 17 00:48:11 2012
@@ -448,6 +448,8 @@
 
   llvm::MDNode *getTBAAInfo(QualType QTy);
 
+  bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor);
+
   static void DecorateInstruction(llvm::Instruction *Inst,
                                   llvm::MDNode *TBAAInfo);
 

Added: cfe/trunk/test/CodeGenCXX/static-mutable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/static-mutable.cpp?rev=150793&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/static-mutable.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/static-mutable.cpp Fri Feb 17 00:48:11 2012
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 %s -triple=i686-linux-gnu -emit-llvm -o - | FileCheck %s
+
+struct S {
+  mutable int n;
+};
+int f() {
+  // The purpose of this test is to ensure that this variable is a global
+  // not a constant.
+  // CHECK: @_ZZ1fvE1s = internal global {{.*}} { i32 12 }
+  static const S s = { 12 };
+  return ++s.n;
+}





More information about the cfe-commits mailing list