[cfe-commits] r78861 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/CodeGen/CGCXX.cpp lib/CodeGen/CodeGenFunction.h lib/Sema/SemaDeclCXX.cpp

Fariborz Jahanian fjahanian at apple.com
Wed Aug 12 16:34:46 PDT 2009


Author: fjahanian
Date: Wed Aug 12 18:34:46 2009
New Revision: 78861

URL: http://llvm.org/viewvc/llvm-project?rev=78861&view=rev
Log:
More toward synthesizing copy assignments. SWIP.


Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Aug 12 18:34:46 2009
@@ -493,7 +493,9 @@
 
   /// hasConstCopyAssignment - Determines whether this class has a
   /// copy assignment operator that accepts a const-qualified argument.
-  bool hasConstCopyAssignment(ASTContext &Context) const;
+  /// It returns its decl in MD if found.
+  bool hasConstCopyAssignment(ASTContext &Context, 
+                              const CXXMethodDecl *&MD) const;
 
   /// addedConstructor - Notify the class that another constructor has
   /// been added. This routine helps maintain information about the

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Aug 12 18:34:46 2009
@@ -168,7 +168,8 @@
   return 0;
 }
 
-bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
+bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context,
+                                           const CXXMethodDecl *& MD) const {
   QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
     const_cast<CXXRecordDecl*>(this)));
   DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
@@ -200,7 +201,7 @@
     }
     if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType)
       continue;
-
+    MD = Method;
     // We have a single argument of type cv X or cv X&, i.e. we've found the
     // copy assignment operator. Return whether it accepts const arguments.
     return AcceptsConst;

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

==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Wed Aug 12 18:34:46 2009
@@ -822,6 +822,46 @@
   }
 }
 
+/// EmitClassCopyAssignment - This routine generates code to copy assign a class
+/// object from SrcValue to DestValue. Assignment can be either a bitwise 
+/// assignment of via an assignment operator call.
+void CodeGenFunction::EmitClassCopyAssignment(
+                                        llvm::Value *Dest, llvm::Value *Src,
+                                        const CXXRecordDecl *ClassDecl, 
+                                        const CXXRecordDecl *BaseClassDecl, 
+                                        QualType Ty) {
+  if (ClassDecl) {
+    Dest = AddressCXXOfBaseClass(Dest, ClassDecl, BaseClassDecl);
+    Src = AddressCXXOfBaseClass(Src, ClassDecl, BaseClassDecl) ;
+  }
+  if (BaseClassDecl->hasTrivialCopyAssignment()) {
+    EmitAggregateCopy(Dest, Src, Ty);
+    return;
+  }
+  
+  const CXXMethodDecl *MD = 0;
+  if (BaseClassDecl->hasConstCopyAssignment(getContext(), MD)) {
+    const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
+    const llvm::Type *Ty = 
+      CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 
+                                     FPT->isVariadic());
+    llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty);
+    
+    CallArgList CallArgs;
+    // Push the this (Dest) ptr.
+    CallArgs.push_back(std::make_pair(RValue::get(Dest),
+                                      MD->getThisType(getContext())));
+    
+    // Push the Src ptr.
+    CallArgs.push_back(std::make_pair(RValue::get(Src),
+                                      MD->getParamDecl(0)->getType()));
+    QualType ResultType = 
+      MD->getType()->getAsFunctionType()->getResultType();
+    EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
+             Callee, CallArgs, MD);
+  }
+}
+
 /// SynthesizeDefaultConstructor - synthesize a default constructor
 void 
 CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *CD,
@@ -916,19 +956,71 @@
 /// the base-specifier-list, and then the immediate nonstatic data members of X 
 /// are assigned, in the order in which they were declared in the class 
 /// definition.Each subobject is assigned in the manner appropriate to its type:
-/// — if the subobject is of class type, the copy assignment operator for the 
-///   class is used (as if by explicit qual- ification; that is, ignoring any 
+///   if the subobject is of class type, the copy assignment operator for the 
+///   class is used (as if by explicit qualification; that is, ignoring any 
 ///   possible virtual overriding functions in more derived classes);
-/// — if the subobject is an array, each element is assigned, in the manner 
+///
+///   if the subobject is an array, each element is assigned, in the manner 
 ///   appropriate to the element type;
-/// — if the subobject is of scalar type, the built-in assignment operator is 
+///
+///   if the subobject is of scalar type, the built-in assignment operator is 
 ///   used.
 void CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD,
                                                   const FunctionDecl *FD,
                                                   llvm::Function *Fn,
                                                   const FunctionArgList &Args) {
+
+  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
+  assert(!ClassDecl->hasUserDeclaredCopyAssignment() &&
+         "SynthesizeCXXCopyAssignment - copy assignment has user declaration");
   StartFunction(FD, FD->getResultType(), Fn, Args, SourceLocation());
   
+  FunctionArgList::const_iterator i = Args.begin();
+  const VarDecl *ThisArg = i->first;
+  llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg);
+  llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this");
+  const VarDecl *SrcArg = (i+1)->first;
+  llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg);
+  llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj);
+  
+  for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin();
+       Base != ClassDecl->bases_end(); ++Base) {
+    // FIXME. copy assignment of virtual base NYI
+    if (Base->isVirtual())
+      continue;
+    
+    CXXRecordDecl *BaseClassDecl
+      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
+    EmitClassCopyAssignment(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl,
+                            Base->getType());
+  }
+  
+  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
+       FieldEnd = ClassDecl->field_end();
+       Field != FieldEnd; ++Field) {
+    QualType FieldType = getContext().getCanonicalType((*Field)->getType());
+    
+    // FIXME. How about copy assignment of  arrays!
+    assert(!getContext().getAsArrayType(FieldType) &&
+           "FIXME. Copy assignment of arrays NYI");
+    
+    if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
+      CXXRecordDecl *FieldClassDecl
+      = cast<CXXRecordDecl>(FieldClassType->getDecl());
+      LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0);
+      LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0);
+      
+      EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(), 
+                              0 /*ClassDecl*/, FieldClassDecl, FieldType);
+      continue;
+    }
+    // Do a built-in assignment of scalar data members.
+    LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0);
+    LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0);
+    RValue RVRHS = EmitLoadOfLValue(RHS, FieldType);
+    EmitStoreThroughLValue(RVRHS, LHS, FieldType);
+  }  
+  
   FinishFunction();
 }  
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=78861&r1=78860&r2=78861&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Aug 12 18:34:46 2009
@@ -575,6 +575,11 @@
                                const CXXRecordDecl *BaseClassDecl,
                                QualType Ty);
   
+  void EmitClassCopyAssignment(llvm::Value *DestValue, llvm::Value *SrcValue,
+                               const CXXRecordDecl *ClassDecl, 
+                               const CXXRecordDecl *BaseClassDecl,
+                               QualType Ty);
+  
   void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, 
                               llvm::Value *This,
                               CallExpr::const_arg_iterator ArgBeg,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Aug 12 18:34:46 2009
@@ -1398,7 +1398,9 @@
          HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) {
       const CXXRecordDecl *BaseClassDecl
         = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
-      HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context);
+      const CXXMethodDecl *MD = 0;
+      HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context, 
+                                                                     MD);
     }
 
     //       -- for all the nonstatic data members of X that are of a class
@@ -1414,8 +1416,9 @@
       if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) {
         const CXXRecordDecl *FieldClassDecl
           = cast<CXXRecordDecl>(FieldClassType->getDecl());
+        const CXXMethodDecl *MD = 0;
         HasConstCopyAssignment
-          = FieldClassDecl->hasConstCopyAssignment(Context);
+          = FieldClassDecl->hasConstCopyAssignment(Context, MD);
       }
     }
 





More information about the cfe-commits mailing list