[cfe-commits] r78700 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/CodeGen/CGCXX.cpp lib/CodeGen/CodeGenModule.cpp lib/Sema/SemaDeclCXX.cpp test/CodeGenCXX/copy-constructor-synthesis.cpp

Fariborz Jahanian fjahanian at apple.com
Tue Aug 11 11:49:55 PDT 2009


Author: fjahanian
Date: Tue Aug 11 13:49:54 2009
New Revision: 78700

URL: http://llvm.org/viewvc/llvm-project?rev=78700&view=rev
Log:
ir-gen support for anonymous union data member
copying in copy constructors and used in
default constructor's initializer list.


Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=78700&r1=78699&r2=78700&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Aug 11 13:49:54 2009
@@ -779,9 +779,28 @@
   Stmt **Args;
   unsigned NumArgs;
   
-  /// CtorToCall - For a base or member needing a constructor for their
-  /// initialization, this is the constructor to call.
-  CXXConstructorDecl *CtorToCall;
+  union {
+    /// CtorToCall - For a base or member needing a constructor for their
+    /// initialization, this is the constructor to call.
+    CXXConstructorDecl *CtorToCall;
+  
+    /// AnonUnionMember - When 'BaseOrMember' is class's anonymous union
+    /// data member, this field holds the FieldDecl for the member of the
+    /// anonymous union being initialized.
+    /// @code
+    /// struct X {
+    ///   X() : au_i1(123) {}
+    ///   union {
+    ///     int au_i1;
+    ///     float au_f1;
+    ///   };
+    /// };
+    /// @endcode
+    /// In above example, BaseOrMember holds the field decl. for anonymous union
+    /// and AnonUnionMember holds field decl for au_i1.
+    ///
+    FieldDecl *AnonUnionMember;
+  };
   
   /// IdLoc - Location of the id in ctor-initializer list.
   SourceLocation IdLoc;
@@ -854,6 +873,17 @@
       return 0;
   }
 
+  void setMember(FieldDecl * anonUnionField) {
+    BaseOrMember = reinterpret_cast<uintptr_t>(anonUnionField);
+  }
+  
+  FieldDecl *getAnonUnionMember() const {
+    return AnonUnionMember;
+  }
+  void setAnonUnionMember(FieldDecl *anonMember) {
+    AnonUnionMember = anonMember;
+  }
+  
   const CXXConstructorDecl *getConstructor() const { return CtorToCall; }
   
   SourceLocation getSourceLocation() const { return IdLoc; }

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=78700&r1=78699&r2=78700&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Aug 11 13:49:54 2009
@@ -643,6 +643,11 @@
         for(RecordDecl::field_iterator FA = FieldClassDecl->field_begin(),
             EA = FieldClassDecl->field_end(); FA != EA; FA++) {
           if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(*FA)) {
+            // 'Member' is the anonymous union field and 'AnonUnionMember' is
+            // set to the anonymous union data member used in the initializer
+            // list.
+            Value->setMember(*Field);
+            Value->setAnonUnionMember(*FA);
             AllToInit.push_back(Value);
             break;
           }

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=78700&r1=78699&r2=78700&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Tue Aug 11 13:49:54 2009
@@ -874,8 +874,7 @@
     // FIXME. How about copying arrays!
     assert(!getContext().getAsArrayType(FieldType) &&
            "FIXME. Copying arrays NYI");
-    assert(!Field->isAnonymousStructOrUnion() &&
-           "FIXME. anonymous data member NYI in copy constructor synthesis");
+    
     if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
       CXXRecordDecl *FieldClassDecl
         = cast<CXXRecordDecl>(FieldClassType->getDecl());
@@ -924,23 +923,25 @@
       QualType FieldType = getContext().getCanonicalType((Field)->getType());
       assert(!getContext().getAsArrayType(FieldType) 
              && "FIXME. Field arrays initialization unsupported");
-      DeclContext *Ctx = Field->getDeclContext();
-      RecordDecl *Record = cast<RecordDecl>(Ctx);
-      assert(!Record->isAnonymousStructOrUnion() &&
-             "FIXME. anonymous union initializer NYI in default constructor");
-      (void)Record;
       
       LoadOfThis = LoadCXXThis();
       LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
       if (FieldType->getAs<RecordType>()) {
-        
+        if (!Field->isAnonymousStructOrUnion()) {
           assert(Member->getConstructor() && 
                  "EmitCtorPrologue - no constructor to initialize member");
           EmitCXXConstructorCall(Member->getConstructor(),
                                  Ctor_Complete, LHS.getAddress(),
                                  Member->const_arg_begin(), 
                                  Member->const_arg_end());
-        continue;
+          continue;
+        }
+        else {
+          // Initializing an anonymous union data member.
+          FieldDecl *anonMember = Member->getAnonUnionMember();
+          LHS = EmitLValueForField(LHS.getAddress(), anonMember, false, 0);
+          FieldType = anonMember->getType();
+        }
       }
       
       assert(Member->getNumArgs() == 1 && "Initializer count must be 1 only");

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=78700&r1=78699&r2=78700&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Aug 11 13:49:54 2009
@@ -699,14 +699,14 @@
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
        FieldEnd = ClassDecl->field_end();
        Field != FieldEnd; ++Field) {
-    assert(!(*Field)->isAnonymousStructOrUnion() &&
-           "FIXME. Anonymous union NYI - DeferredCopyConstructorToEmit");
     QualType FieldType = Context.getCanonicalType((*Field)->getType());
     if (const ArrayType *Array = Context.getAsArrayType(FieldType))
       FieldType = Array->getElementType();
     if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+      if ((*Field)->isAnonymousStructOrUnion())
+        continue;
       CXXRecordDecl *FieldClassDecl
-      = cast<CXXRecordDecl>(FieldClassType->getDecl());
+        = cast<CXXRecordDecl>(FieldClassType->getDecl());
       if (CXXConstructorDecl *FieldCopyCtor = 
           FieldClassDecl->getCopyConstructor(Context, 0))
         GetAddrOfCXXConstructor(FieldCopyCtor, Ctor_Complete);

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=78700&r1=78699&r2=78700&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Aug 11 13:49:54 2009
@@ -880,10 +880,16 @@
   return static_cast<void *>(Field);
 }
 
-static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member) {
+static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member, 
+                             bool MemberMaybeAnon=false) {
   // For fields injected into the class via declaration of an anonymous union,
   // use its anonymous union class declaration as the unique key.
   if (FieldDecl *Field = Member->getMember()) {
+    // After BuildBaseOrMemberInitializers call, Field is the anonymous union
+    // data member of the class. Data member used in the initializer list is 
+    // in AnonUnionMember field.
+    if (MemberMaybeAnon && Field->isAnonymousStructOrUnion())
+      Field = Member->getAnonUnionMember();
     if (Field->getDeclContext()->isRecord()) {
       RecordDecl *RD = cast<RecordDecl>(Field->getDeclContext());
       if (RD->isAnonymousStructOrUnion())
@@ -973,7 +979,7 @@
     for (unsigned i = 0; i < NumMemInits; i++) {
       CXXBaseOrMemberInitializer *Member = 
         static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]);
-      void *MemberInCtorList = GetKeyForMember(Member);
+      void *MemberInCtorList = GetKeyForMember(Member, true);
 
       for (; curIndex < Last; curIndex++)
         if (MemberInCtorList == AllBaseOrMembers[curIndex])

Modified: cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp?rev=78700&r1=78699&r2=78700&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/copy-constructor-synthesis.cpp Tue Aug 11 13:49:54 2009
@@ -26,12 +26,15 @@
 
 
 struct X  : M, N, P { // ...
-	X() : f1(1.0), d1(2.0), i1(3), name("HELLO"), bf1(0xff), bf2(0xabcd) {}
+	X() : f1(1.0), d1(2.0), i1(3), name("HELLO"), bf1(0xff), bf2(0xabcd),
+              au_i1(1234), au1_4("MASKED") {}
         P p0;
 	void pr() { printf("iM = %d iN = %d, m1.iM = %d\n", iM, iN, m1.iM); 
                     printf("im = %d p0.iP = %d, p1.iP = %d\n", iP, p0.iP, p1.iP); 
                     printf("f1 = %f  d1 = %f  i1 = %d name(%s) \n", f1, d1, i1, name);
 		    printf("bf1 = %x  bf2 = %x\n", bf1, bf2);
+		    printf("au_i2 = %d\n", au_i2); 
+                    printf("au1_1 = %s\n", au1_1); 
                    }
 	M m1;
         P p1;
@@ -41,6 +44,17 @@
 	const char *name;
 	unsigned bf1 : 8;
         unsigned bf2 : 16;
+
+	union {
+          int au_i1;
+          int au_i2;
+        };
+        union {
+          const char * au1_1;
+          float au1_2;
+          int au1_3;
+          const char * au1_4;
+        };
 };
 
 int main()





More information about the cfe-commits mailing list