diff options
| -rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 14 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 137 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 3 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/copy-assign-synthesis-2.cpp | 4 | 
4 files changed, 20 insertions, 138 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index ceff7508b25..3b97fcb1171 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -196,11 +196,6 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,    assert(MD->isInstance() &&           "Trying to emit a member call expr on a static method!"); -  // A call to a trivial destructor requires no code generation. -  if (const CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(MD)) -    if (Destructor->isTrivial()) -      return RValue::get(0); -    const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();    CallArgList Args; @@ -251,6 +246,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {    const MemberExpr *ME = cast<MemberExpr>(CE->getCallee());    const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); +  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext());    if (MD->isStatic()) {      // The method is static, emit it as we would a regular call. @@ -283,6 +279,8 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {    llvm::Value *Callee;    if (const CXXDestructorDecl *Destructor               = dyn_cast<CXXDestructorDecl>(MD)) { +    if (Destructor->isTrivial()) +      return RValue::get(0);      if (MD->isVirtual() && !ME->hasQualifier() &&           !canDevirtualizeMemberFunctionCalls(ME->getBase())) {        Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty);  @@ -684,6 +682,10 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,        EmitAggregateCopy(This, Src, Ty);        return;      } +  } else if (D->isTrivial()) { +    // FIXME: Track down why we're trying to generate calls to the trivial +    // default constructor! +    return;    }    llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); @@ -1327,6 +1329,7 @@ CodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor,                                                CXXCtorType Type,                                                llvm::Function *Fn,                                                const FunctionArgList &Args) { +  assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");    StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,                   SourceLocation());    EmitCtorPrologue(Ctor, Type); @@ -1356,6 +1359,7 @@ CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor,    const CXXRecordDecl *ClassDecl = Ctor->getParent();    assert(!ClassDecl->hasUserDeclaredCopyConstructor() &&        "SynthesizeCXXCopyConstructor - copy constructor has definition already"); +  assert(!Ctor->isTrivial() && "shouldn't need to generate trivial ctor");    StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args,                   SourceLocation()); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 6aff0e7476b..bbad876575d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -697,143 +697,20 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(const char *MangledName,      // A called constructor which has no definition or declaration need be      // synthesized.      else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { -      const CXXRecordDecl *ClassDecl = -        cast<CXXRecordDecl>(CD->getDeclContext()); -      if (CD->isCopyConstructor(getContext())) -        DeferredCopyConstructorToEmit(D); -      else if (!ClassDecl->hasUserDeclaredConstructor()) +      if (CD->isImplicit()) +        DeferredDeclsToEmit.push_back(D); +    } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) { +      if (DD->isImplicit()) +        DeferredDeclsToEmit.push_back(D); +    } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { +      if (MD->isCopyAssignment() && MD->isImplicit())          DeferredDeclsToEmit.push_back(D);      } -    else if (isa<CXXDestructorDecl>(FD)) -       DeferredDestructorToEmit(D); -    else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) -           if (MD->isCopyAssignment()) -             DeferredCopyAssignmentToEmit(D);    }    return F;  } -/// Defer definition of copy constructor(s) which need be implicitly defined. -void CodeGenModule::DeferredCopyConstructorToEmit(GlobalDecl CopyCtorDecl) { -  const CXXConstructorDecl *CD = -    cast<CXXConstructorDecl>(CopyCtorDecl.getDecl()); -  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); -  if (ClassDecl->hasTrivialCopyConstructor() || -      ClassDecl->hasUserDeclaredCopyConstructor()) -    return; - -  // First make sure all direct base classes and virtual bases and non-static -  // data mebers which need to have their copy constructors implicitly defined -  // are defined. 12.8.p7 -  for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); -       Base != ClassDecl->bases_end(); ++Base) { -    CXXRecordDecl *BaseClassDecl -      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    if (CXXConstructorDecl *BaseCopyCtor = -        BaseClassDecl->getCopyConstructor(Context, 0)) -      GetAddrOfCXXConstructor(BaseCopyCtor, Ctor_Complete); -  } - -  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), -       FieldEnd = ClassDecl->field_end(); -       Field != FieldEnd; ++Field) { -    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()); -      if (CXXConstructorDecl *FieldCopyCtor = -          FieldClassDecl->getCopyConstructor(Context, 0)) -        GetAddrOfCXXConstructor(FieldCopyCtor, Ctor_Complete); -    } -  } -  DeferredDeclsToEmit.push_back(CopyCtorDecl); -} - -/// Defer definition of copy assignments which need be implicitly defined. -void CodeGenModule::DeferredCopyAssignmentToEmit(GlobalDecl CopyAssignDecl) { -  const CXXMethodDecl *CD = cast<CXXMethodDecl>(CopyAssignDecl.getDecl()); -  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); - -  if (ClassDecl->hasTrivialCopyAssignment() || -      ClassDecl->hasUserDeclaredCopyAssignment()) -    return; - -  // First make sure all direct base classes and virtual bases and non-static -  // data mebers which need to have their copy assignments implicitly defined -  // are defined. 12.8.p12 -  for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); -       Base != ClassDecl->bases_end(); ++Base) { -    CXXRecordDecl *BaseClassDecl -      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    const CXXMethodDecl *MD = 0; -    if (!BaseClassDecl->hasTrivialCopyAssignment() && -        !BaseClassDecl->hasUserDeclaredCopyAssignment() && -        BaseClassDecl->hasConstCopyAssignment(getContext(), MD)) -      GetAddrOfFunction(MD, 0); -  } - -  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), -       FieldEnd = ClassDecl->field_end(); -       Field != FieldEnd; ++Field) { -    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()); -      const CXXMethodDecl *MD = 0; -      if (!FieldClassDecl->hasTrivialCopyAssignment() && -          !FieldClassDecl->hasUserDeclaredCopyAssignment() && -          FieldClassDecl->hasConstCopyAssignment(getContext(), MD)) -          GetAddrOfFunction(MD, 0); -    } -  } -  DeferredDeclsToEmit.push_back(CopyAssignDecl); -} - -void CodeGenModule::DeferredDestructorToEmit(GlobalDecl DtorDecl) { -  const CXXDestructorDecl *DD = cast<CXXDestructorDecl>(DtorDecl.getDecl()); -  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext()); -  if (ClassDecl->hasTrivialDestructor() || -      ClassDecl->hasUserDeclaredDestructor()) -    return; - -  for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); -       Base != ClassDecl->bases_end(); ++Base) { -    CXXRecordDecl *BaseClassDecl -      = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); -    if (const CXXDestructorDecl *BaseDtor = -          BaseClassDecl->getDestructor(Context)) -      GetAddrOfCXXDestructor(BaseDtor, Dtor_Complete); -  } - -  for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), -       FieldEnd = ClassDecl->field_end(); -       Field != FieldEnd; ++Field) { -    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()); -      if (const CXXDestructorDecl *FieldDtor = -            FieldClassDecl->getDestructor(Context)) -        GetAddrOfCXXDestructor(FieldDtor, Dtor_Complete); -    } -  } -  DeferredDeclsToEmit.push_back(DtorDecl); -} - -  /// GetAddrOfFunction - Return the address of the given function.  If Ty is  /// non-null, then this function will use the specified type if it has to  /// create it (this occurs when we see a definition of the function). diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 5c3e633daa2..78bc4ed845d 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -428,9 +428,6 @@ private:    llvm::Constant *GetOrCreateLLVMGlobal(const char *MangledName,                                          const llvm::PointerType *PTy,                                          const VarDecl *D); -  void DeferredCopyConstructorToEmit(GlobalDecl D); -  void DeferredCopyAssignmentToEmit(GlobalDecl D); -  void DeferredDestructorToEmit(GlobalDecl D);    /// SetCommonAttributes - Set attributes which are common to any    /// form of a global definition (alias, Objective-C method, diff --git a/clang/test/CodeGenCXX/copy-assign-synthesis-2.cpp b/clang/test/CodeGenCXX/copy-assign-synthesis-2.cpp new file mode 100644 index 00000000000..60d52f57de9 --- /dev/null +++ b/clang/test/CodeGenCXX/copy-assign-synthesis-2.cpp @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm %s -o - | FileCheck %s +struct A {}; +A& (A::*x)(const A&) = &A::operator=; +// CHECK: define linkonce_odr %struct.A* @_ZN1AaSERKS_  | 

