[cfe-commits] r131276 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/CodeGen/CGBlocks.cpp lib/CodeGen/CodeGenModule.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp test/CodeGenCXX/global-llvm-constant.cpp

Douglas Gregor dgregor at apple.com
Thu May 12 18:05:07 PDT 2011


Author: dgregor
Date: Thu May 12 20:05:07 2011
New Revision: 131276

URL: http://llvm.org/viewvc/llvm-project?rev=131276&view=rev
Log:
When determining whether we can make a declaration into a global
constant, also consider whether it's a class type that has any mutable
fields. If so, it can't be a global constant.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/CodeGenCXX/global-llvm-constant.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=131276&r1=131275&r2=131276&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu May 12 20:05:07 2011
@@ -337,6 +337,9 @@
     /// HasPublicFields - True when there are private non-static data members.
     bool HasPublicFields : 1;
 
+    /// \brief True if this class (or any subobject) has mutable fields.
+    bool HasMutableFields : 1;
+    
     /// HasTrivialDefaultConstructor - True when, if this class has a default
     /// constructor, this default constructor is trivial.
     ///
@@ -822,6 +825,10 @@
   /// (C++ [class]p7)
   bool isStandardLayout() const { return data().IsStandardLayout; }
 
+  /// \brief Whether this class, or any of its class subobjects, contains a
+  /// mutable field.
+  bool hasMutableFields() const { return data().HasMutableFields; }
+  
   // hasTrivialDefaultConstructor - Whether this class has a trivial default
   // constructor
   // (C++0x [class.ctor]p5)

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=131276&r1=131275&r2=131276&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu May 12 20:05:07 2011
@@ -33,7 +33,7 @@
     Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
     Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
     HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
-    HasTrivialDefaultConstructor(true),
+    HasMutableFields(false), HasTrivialDefaultConstructor(true),
     HasConstExprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true),
     HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
     HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
@@ -225,6 +225,10 @@
     //   have trivial destructors.
     if (!BaseClassDecl->hasTrivialDestructor())
       data().HasTrivialDestructor = false;
+    
+    // Keep track of the presence of mutable fields.
+    if (BaseClassDecl->hasMutableFields())
+      data().HasMutableFields = true;
   }
   
   if (VBases.empty())
@@ -688,6 +692,10 @@
          data().HasPublicFields) > 1)
       data().IsStandardLayout = false;
 
+    // Keep track of the presence of mutable fields.
+    if (Field->isMutable())
+      data().HasMutableFields = true;
+    
     // C++0x [class]p9:
     //   A POD struct is a class that is both a trivial class and a 
     //   standard-layout class, and has no non-static data members of type 
@@ -779,6 +787,10 @@
             }
           }
         }
+        
+        // Keep track of the presence of mutable fields.
+        if (FieldRec->hasMutableFields())
+          data().HasMutableFields = true;
       }
     }
 

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=131276&r1=131275&r2=131276&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu May 12 20:05:07 2011
@@ -189,23 +189,6 @@
   }
 }
 
-/// Determines if the given record type has a mutable field.
-static bool hasMutableField(const CXXRecordDecl *record) {
-  for (CXXRecordDecl::field_iterator
-         i = record->field_begin(), e = record->field_end(); i != e; ++i)
-    if ((*i)->isMutable())
-      return true;
-
-  for (CXXRecordDecl::base_class_const_iterator
-         i = record->bases_begin(), e = record->bases_end(); i != e; ++i) {
-    const RecordType *record = i->getType()->castAs<RecordType>();
-    if (hasMutableField(cast<CXXRecordDecl>(record->getDecl())))
-      return true;
-  }
-
-  return false;
-}
-
 /// Determines if the given type is safe for constant capture in C++.
 static bool isSafeForCXXConstantCapture(QualType type) {
   const RecordType *recordType =
@@ -222,7 +205,7 @@
 
   // Otherwise, we just have to make sure there aren't any mutable
   // fields that might have changed since initialization.
-  return !hasMutableField(record);
+  return !record->hasMutableFields();
 }
 
 /// It is illegal to modify a const object after initialization.

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=131276&r1=131275&r2=131276&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu May 12 20:05:07 2011
@@ -946,7 +946,9 @@
   if (Context.getLangOptions().CPlusPlus) {
     if (const RecordType *Record 
           = Context.getBaseElementType(D->getType())->getAs<RecordType>())
-      return ConstantInit && cast<CXXRecordDecl>(Record->getDecl())->isPOD();
+      return ConstantInit && 
+             cast<CXXRecordDecl>(Record->getDecl())->isPOD() &&
+             !cast<CXXRecordDecl>(Record->getDecl())->hasMutableFields();
   }
   
   return true;

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=131276&r1=131275&r2=131276&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu May 12 20:05:07 2011
@@ -860,6 +860,7 @@
   Data.HasPrivateFields = Record[Idx++];
   Data.HasProtectedFields = Record[Idx++];
   Data.HasPublicFields = Record[Idx++];
+  Data.HasMutableFields = Record[Idx++];
   Data.HasTrivialDefaultConstructor = Record[Idx++];
   Data.HasConstExprNonCopyMoveConstructor = Record[Idx++];
   Data.HasTrivialCopyConstructor = Record[Idx++];

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=131276&r1=131275&r2=131276&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu May 12 20:05:07 2011
@@ -3818,6 +3818,7 @@
   Record.push_back(Data.HasPrivateFields);
   Record.push_back(Data.HasProtectedFields);
   Record.push_back(Data.HasPublicFields);
+  Record.push_back(Data.HasMutableFields);
   Record.push_back(Data.HasTrivialDefaultConstructor);
   Record.push_back(Data.HasConstExprNonCopyMoveConstructor);
   Record.push_back(Data.HasTrivialCopyConstructor);

Modified: cfe/trunk/test/CodeGenCXX/global-llvm-constant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/global-llvm-constant.cpp?rev=131276&r1=131275&r2=131276&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/global-llvm-constant.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/global-llvm-constant.cpp Thu May 12 20:05:07 2011
@@ -18,3 +18,15 @@
 // CHECK: @x2 = constant
 extern const X x2;
 const X x2 = { &add };
+
+struct X1 {
+  mutable int i;
+};
+
+struct X2 {
+  X1 array[3];
+};
+
+// CHECK: @x2b = global
+extern const X2 x2b;
+const X2 x2b = { { { 1 }, { 2 }, { 3 } } };





More information about the cfe-commits mailing list