[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