Author: rsmith Date: Thu Feb 23 19:29:42 2017 New Revision: 296067 URL: http://llvm.org/viewvc/llvm-project?rev=296067&view=rev Log: Refactor computation of exception specification for special members to remove some of the repetition.
Modified: cfe/trunk/include/clang/AST/DeclCXX.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=296067&r1=296066&r2=296067&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Feb 23 19:29:42 2017 @@ -203,6 +203,11 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } + /// \brief Get the location at which the base class type was written. + SourceLocation getBaseTypeLoc() const LLVM_READONLY { + return BaseTypeInfo->getTypeLoc().getLocStart(); + } + /// \brief Determines whether the base class is a virtual base class (or not). bool isVirtual() const { return Virtual; } Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=296067&r1=296066&r2=296067&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Feb 23 19:29:42 2017 @@ -6091,27 +6091,34 @@ static bool defaultedSpecialMemberIsCons } static Sema::ImplicitExceptionSpecification +ComputeDefaultedSpecialMemberExceptionSpec( + Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, + Sema::InheritedConstructorInfo *ICI); + +static Sema::ImplicitExceptionSpecification computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) { - switch (S.getSpecialMember(MD)) { + switch (auto CSM = S.getSpecialMember(MD)) { case Sema::CXXDefaultConstructor: - return S.ComputeDefaultedDefaultCtorExceptionSpec(Loc, MD); + return ComputeDefaultedSpecialMemberExceptionSpec( + S, Loc, MD, Sema::CXXDefaultConstructor, nullptr); case Sema::CXXCopyConstructor: - return S.ComputeDefaultedCopyCtorExceptionSpec(MD); case Sema::CXXCopyAssignment: - return S.ComputeDefaultedCopyAssignmentExceptionSpec(MD); case Sema::CXXMoveConstructor: - return S.ComputeDefaultedMoveCtorExceptionSpec(MD); case Sema::CXXMoveAssignment: - return S.ComputeDefaultedMoveAssignmentExceptionSpec(MD); case Sema::CXXDestructor: - return S.ComputeDefaultedDtorExceptionSpec(MD); + return ComputeDefaultedSpecialMemberExceptionSpec( + S, MD->getLocation(), MD, CSM, nullptr); case Sema::CXXInvalid: break; } - assert(cast<CXXConstructorDecl>(MD)->getInheritedConstructor() && + + auto *CD = cast<CXXConstructorDecl>(MD); + assert(CD->getInheritedConstructor() && "only special members have implicit exception specs"); - return S.ComputeInheritingCtorExceptionSpec(Loc, - cast<CXXConstructorDecl>(MD)); + Sema::InheritedConstructorInfo ICI( + S, Loc, CD->getInheritedConstructor().getShadowDecl()); + return ComputeDefaultedSpecialMemberExceptionSpec( + S, Loc, CD, Sema::CXXDefaultConstructor, &ICI); } static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S, @@ -10036,123 +10043,143 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope return AliasDecl; } -Sema::ImplicitExceptionSpecification -Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, - CXXMethodDecl *MD) { - CXXRecordDecl *ClassDecl = MD->getParent(); +namespace { +struct SpecialMemberExceptionSpecInfo { + Sema &S; + CXXMethodDecl *MD; + Sema::CXXSpecialMember CSM; + Sema::InheritedConstructorInfo *ICI; - // C++ [except.spec]p14: - // An implicitly declared special member function (Clause 12) shall have an - // exception-specification. [...] - ImplicitExceptionSpecification ExceptSpec(*this); - if (ClassDecl->isInvalidDecl()) - return ExceptSpec; + SourceLocation Loc; + Sema::ImplicitExceptionSpecification ExceptSpec; - // Direct base-class constructors. - for (const auto &B : ClassDecl->bases()) { - if (B.isVirtual()) // Handled below. - continue; - - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) { - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); - // If this is a deleted function, add it anyway. This might be conformant - // with the standard. This might not. I'm not sure. It might not matter. - if (Constructor) - ExceptSpec.CalledDecl(B.getLocStart(), Constructor); - } - } + bool ConstArg = false; - // Virtual base-class constructors. - for (const auto &B : ClassDecl->vbases()) { - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) { - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); - // If this is a deleted function, add it anyway. This might be conformant - // with the standard. This might not. I'm not sure. It might not matter. - if (Constructor) - ExceptSpec.CalledDecl(B.getLocStart(), Constructor); + SpecialMemberExceptionSpecInfo(Sema &S, CXXMethodDecl *MD, + Sema::CXXSpecialMember CSM, + Sema::InheritedConstructorInfo *ICI, + SourceLocation Loc) + : S(S), MD(MD), CSM(CSM), ICI(ICI), Loc(Loc), ExceptSpec(S) { + if (MD->getNumParams()) { + if (const ReferenceType *RT = + MD->getParamDecl(0)->getType()->getAs<ReferenceType>()) + ConstArg = RT->getPointeeType().isConstQualified(); } } - // Field constructors. - for (auto *F : ClassDecl->fields()) { - if (F->hasInClassInitializer()) { - Expr *E = F->getInClassInitializer(); - if (!E) - // FIXME: It's a little wasteful to build and throw away a - // CXXDefaultInitExpr here. - E = BuildCXXDefaultInitExpr(Loc, F).get(); - if (E) - ExceptSpec.CalledExpr(E); - } else if (const RecordType *RecordTy - = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { - CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); - CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl); - // If this is a deleted function, add it anyway. This might be conformant - // with the standard. This might not. I'm not sure. It might not matter. - // In particular, the problem is that this function never gets called. It - // might just be ill-formed because this function attempts to refer to - // a deleted function here. - if (Constructor) - ExceptSpec.CalledDecl(F->getLocation(), Constructor); - } + typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject; + static SourceLocation getSubobjectLoc(Subobject Subobj) { + if (auto *B = Subobj.dyn_cast<CXXBaseSpecifier*>()) + return B->getBaseTypeLoc(); + else + return Subobj.get<FieldDecl*>()->getLocation(); } - return ExceptSpec; -} - -Sema::ImplicitExceptionSpecification -Sema::ComputeInheritingCtorExceptionSpec(SourceLocation Loc, - CXXConstructorDecl *CD) { - CXXRecordDecl *ClassDecl = CD->getParent(); + Sema::SpecialMemberOverloadResult *lookupIn(CXXRecordDecl *Class, + unsigned Quals, bool IsMutable) { + return lookupCallFromSpecialMember(S, Class, CSM, Quals, + ConstArg && !IsMutable); + } - // C++ [except.spec]p14: - // An inheriting constructor [...] shall have an exception-specification. [...] - ImplicitExceptionSpecification ExceptSpec(*this); - if (ClassDecl->isInvalidDecl()) - return ExceptSpec; + void visitBase(CXXBaseSpecifier *Base); + void visitField(FieldDecl *FD); - auto Inherited = CD->getInheritedConstructor(); - InheritedConstructorInfo ICI(*this, Loc, Inherited.getShadowDecl()); + void visitClassSubobject(CXXRecordDecl *Class, Subobject Subobj, + unsigned Quals); - // Direct and virtual base-class constructors. - for (bool VBase : {false, true}) { - for (CXXBaseSpecifier &B : - VBase ? ClassDecl->vbases() : ClassDecl->bases()) { - // Don't visit direct vbases twice. - if (B.isVirtual() != VBase) - continue; + void visitSubobjectCall(Subobject Subobj, + Sema::SpecialMemberOverloadResult *SMOR); + void visitSubobjectCall(Subobject Subobj, CXXMethodDecl *MD); +}; +} - CXXRecordDecl *BaseClass = B.getType()->getAsCXXRecordDecl(); - if (!BaseClass) - continue; +void SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) { + auto *RT = Base->getType()->getAs<RecordType>(); + if (!RT) + return; - CXXConstructorDecl *Constructor = - ICI.findConstructorForBase(BaseClass, Inherited.getConstructor()) - .first; - if (!Constructor) - Constructor = LookupDefaultConstructor(BaseClass); - if (Constructor) - ExceptSpec.CalledDecl(B.getLocStart(), Constructor); - } + auto *BaseClass = cast<CXXRecordDecl>(RT->getDecl()); + if (ICI) { + assert(CSM == Sema::CXXDefaultConstructor); + if (auto *BaseCtor = ICI->findConstructorForBase( + BaseClass, cast<CXXConstructorDecl>(MD) + ->getInheritedConstructor() + .getConstructor()) + .first) + return visitSubobjectCall(Base, BaseCtor); + } + + visitClassSubobject(BaseClass, Base, 0); +} + +void SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) { + if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) { + Expr *E = FD->getInClassInitializer(); + if (!E) + // FIXME: It's a little wasteful to build and throw away a + // CXXDefaultInitExpr here. + // FIXME: We should have a single context note pointing at Loc, and + // this location should be MD->getLocation() instead, since that's + // the location where we actually use the default init expression. + E = S.BuildCXXDefaultInitExpr(Loc, FD).get(); + if (E) + ExceptSpec.CalledExpr(E); + } else if (auto *RT = S.Context.getBaseElementType(FD->getType()) + ->getAs<RecordType>()) { + visitClassSubobject(cast<CXXRecordDecl>(RT->getDecl()), FD, + FD->getType().getCVRQualifiers()); } +} + +void SpecialMemberExceptionSpecInfo::visitClassSubobject(CXXRecordDecl *Class, + Subobject Subobj, + unsigned Quals) { + FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); + bool IsMutable = Field && Field->isMutable(); + visitSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable)); +} + +void SpecialMemberExceptionSpecInfo::visitSubobjectCall( + Subobject Subobj, Sema::SpecialMemberOverloadResult *SMOR) { + // Note, if lookup fails, it doesn't matter what exception specification we + // choose because the special member will be deleted. + if (CXXMethodDecl *MD = SMOR->getMethod()) + visitSubobjectCall(Subobj, MD); +} + +void SpecialMemberExceptionSpecInfo::visitSubobjectCall(Subobject Subobj, + CXXMethodDecl *MD) { + ExceptSpec.CalledDecl(getSubobjectLoc(Subobj), MD); +} + +static Sema::ImplicitExceptionSpecification +ComputeDefaultedSpecialMemberExceptionSpec( + Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, + Sema::InheritedConstructorInfo *ICI) { + CXXRecordDecl *ClassDecl = MD->getParent(); + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, Loc); + if (ClassDecl->isInvalidDecl()) + return Info.ExceptSpec; + + // Direct base-class constructors. + for (auto &B : ClassDecl->bases()) + if (!B.isVirtual()) // Handled below. + Info.visitBase(&B); + + // Virtual base-class constructors. + // FIXME: Implement potentially-constructed subobjects rule. + for (auto &B : ClassDecl->vbases()) + Info.visitBase(&B); // Field constructors. - for (const auto *F : ClassDecl->fields()) { - if (F->hasInClassInitializer()) { - if (Expr *E = F->getInClassInitializer()) - ExceptSpec.CalledExpr(E); - } else if (const RecordType *RecordTy - = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { - CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); - CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl); - if (Constructor) - ExceptSpec.CalledDecl(F->getLocation(), Constructor); - } - } + for (auto *F : ClassDecl->fields()) + Info.visitField(F); - return ExceptSpec; + return Info.ExceptSpec; } namespace { @@ -10497,45 +10524,6 @@ void Sema::DefineInheritingConstructor(S DiagnoseUninitializedFields(*this, Constructor); } -Sema::ImplicitExceptionSpecification -Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) { - CXXRecordDecl *ClassDecl = MD->getParent(); - - // C++ [except.spec]p14: - // An implicitly declared special member function (Clause 12) shall have - // an exception-specification. - ImplicitExceptionSpecification ExceptSpec(*this); - if (ClassDecl->isInvalidDecl()) - return ExceptSpec; - - // Direct base-class destructors. - for (const auto &B : ClassDecl->bases()) { - if (B.isVirtual()) // Handled below. - continue; - - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) - ExceptSpec.CalledDecl(B.getLocStart(), - LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl()))); - } - - // Virtual base-class destructors. - for (const auto &B : ClassDecl->vbases()) { - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) - ExceptSpec.CalledDecl(B.getLocStart(), - LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl()))); - } - - // Field destructors. - for (const auto *F : ClassDecl->fields()) { - if (const RecordType *RecordTy - = Context.getBaseElementType(F->getType())->getAs<RecordType>()) - ExceptSpec.CalledDecl(F->getLocation(), - LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl()))); - } - - return ExceptSpec; -} - CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // C++ [class.dtor]p2: // If a class has no user-declared destructor, a destructor is @@ -11122,62 +11110,6 @@ buildSingleCopyAssign(Sema &S, SourceLoc return Result; } -Sema::ImplicitExceptionSpecification -Sema::ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD) { - CXXRecordDecl *ClassDecl = MD->getParent(); - - ImplicitExceptionSpecification ExceptSpec(*this); - if (ClassDecl->isInvalidDecl()) - return ExceptSpec; - - const FunctionProtoType *T = MD->getType()->castAs<FunctionProtoType>(); - assert(T->getNumParams() == 1 && "not a copy assignment op"); - unsigned ArgQuals = - T->getParamType(0).getNonReferenceType().getCVRQualifiers(); - - // C++ [except.spec]p14: - // An implicitly declared special member function (Clause 12) shall have an - // exception-specification. [...] - - // It is unspecified whether or not an implicit copy assignment operator - // attempts to deduplicate calls to assignment operators of virtual bases are - // made. As such, this exception specification is effectively unspecified. - // Based on a similar decision made for constness in C++0x, we're erring on - // the side of assuming such calls to be made regardless of whether they - // actually happen. - for (const auto &Base : ClassDecl->bases()) { - if (Base.isVirtual()) - continue; - - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl, - ArgQuals, false, 0)) - ExceptSpec.CalledDecl(Base.getLocStart(), CopyAssign); - } - - for (const auto &Base : ClassDecl->vbases()) { - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl, - ArgQuals, false, 0)) - ExceptSpec.CalledDecl(Base.getLocStart(), CopyAssign); - } - - for (const auto *Field : ClassDecl->fields()) { - QualType FieldType = Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { - if (CXXMethodDecl *CopyAssign = - LookupCopyingAssignment(FieldClassDecl, - ArgQuals | FieldType.getCVRQualifiers(), - false, 0)) - ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign); - } - } - - return ExceptSpec; -} - CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // Note: The following rules are largely analoguous to the copy // constructor rules. Note that virtual bases are not taken into account @@ -11521,59 +11453,6 @@ void Sema::DefineImplicitCopyAssignment( } } -Sema::ImplicitExceptionSpecification -Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD) { - CXXRecordDecl *ClassDecl = MD->getParent(); - - ImplicitExceptionSpecification ExceptSpec(*this); - if (ClassDecl->isInvalidDecl()) - return ExceptSpec; - - // C++0x [except.spec]p14: - // An implicitly declared special member function (Clause 12) shall have an - // exception-specification. [...] - - // It is unspecified whether or not an implicit move assignment operator - // attempts to deduplicate calls to assignment operators of virtual bases are - // made. As such, this exception specification is effectively unspecified. - // Based on a similar decision made for constness in C++0x, we're erring on - // the side of assuming such calls to be made regardless of whether they - // actually happen. - // Note that a move constructor is not implicitly declared when there are - // virtual bases, but it can still be user-declared and explicitly defaulted. - for (const auto &Base : ClassDecl->bases()) { - if (Base.isVirtual()) - continue; - - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl, - 0, false, 0)) - ExceptSpec.CalledDecl(Base.getLocStart(), MoveAssign); - } - - for (const auto &Base : ClassDecl->vbases()) { - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl, - 0, false, 0)) - ExceptSpec.CalledDecl(Base.getLocStart(), MoveAssign); - } - - for (const auto *Field : ClassDecl->fields()) { - QualType FieldType = Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { - if (CXXMethodDecl *MoveAssign = - LookupMovingAssignment(FieldClassDecl, - FieldType.getCVRQualifiers(), - false, 0)) - ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign); - } - } - - return ExceptSpec; -} - CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { assert(ClassDecl->needsImplicitMoveAssignment()); @@ -11958,52 +11837,6 @@ void Sema::DefineImplicitMoveAssignment( } } -Sema::ImplicitExceptionSpecification -Sema::ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD) { - CXXRecordDecl *ClassDecl = MD->getParent(); - - ImplicitExceptionSpecification ExceptSpec(*this); - if (ClassDecl->isInvalidDecl()) - return ExceptSpec; - - const FunctionProtoType *T = MD->getType()->castAs<FunctionProtoType>(); - assert(T->getNumParams() >= 1 && "not a copy ctor"); - unsigned Quals = T->getParamType(0).getNonReferenceType().getCVRQualifiers(); - - // C++ [except.spec]p14: - // An implicitly declared special member function (Clause 12) shall have an - // exception-specification. [...] - for (const auto &Base : ClassDecl->bases()) { - // Virtual bases are handled below. - if (Base.isVirtual()) - continue; - - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - if (CXXConstructorDecl *CopyConstructor = - LookupCopyingConstructor(BaseClassDecl, Quals)) - ExceptSpec.CalledDecl(Base.getLocStart(), CopyConstructor); - } - for (const auto &Base : ClassDecl->vbases()) { - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); - if (CXXConstructorDecl *CopyConstructor = - LookupCopyingConstructor(BaseClassDecl, Quals)) - ExceptSpec.CalledDecl(Base.getLocStart(), CopyConstructor); - } - for (const auto *Field : ClassDecl->fields()) { - QualType FieldType = Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { - if (CXXConstructorDecl *CopyConstructor = - LookupCopyingConstructor(FieldClassDecl, - Quals | FieldType.getCVRQualifiers())) - ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor); - } - } - - return ExceptSpec; -} - CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( CXXRecordDecl *ClassDecl) { // C++ [class.copy]p4: @@ -12131,65 +11964,6 @@ void Sema::DefineImplicitCopyConstructor } } -Sema::ImplicitExceptionSpecification -Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD) { - CXXRecordDecl *ClassDecl = MD->getParent(); - - // C++ [except.spec]p14: - // An implicitly declared special member function (Clause 12) shall have an - // exception-specification. [...] - ImplicitExceptionSpecification ExceptSpec(*this); - if (ClassDecl->isInvalidDecl()) - return ExceptSpec; - - // Direct base-class constructors. - for (const auto &B : ClassDecl->bases()) { - if (B.isVirtual()) // Handled below. - continue; - - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) { - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - CXXConstructorDecl *Constructor = - LookupMovingConstructor(BaseClassDecl, 0); - // If this is a deleted function, add it anyway. This might be conformant - // with the standard. This might not. I'm not sure. It might not matter. - if (Constructor) - ExceptSpec.CalledDecl(B.getLocStart(), Constructor); - } - } - - // Virtual base-class constructors. - for (const auto &B : ClassDecl->vbases()) { - if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) { - CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - CXXConstructorDecl *Constructor = - LookupMovingConstructor(BaseClassDecl, 0); - // If this is a deleted function, add it anyway. This might be conformant - // with the standard. This might not. I'm not sure. It might not matter. - if (Constructor) - ExceptSpec.CalledDecl(B.getLocStart(), Constructor); - } - } - - // Field constructors. - for (const auto *F : ClassDecl->fields()) { - QualType FieldType = Context.getBaseElementType(F->getType()); - if (CXXRecordDecl *FieldRecDecl = FieldType->getAsCXXRecordDecl()) { - CXXConstructorDecl *Constructor = - LookupMovingConstructor(FieldRecDecl, FieldType.getCVRQualifiers()); - // If this is a deleted function, add it anyway. This might be conformant - // with the standard. This might not. I'm not sure. It might not matter. - // In particular, the problem is that this function never gets called. It - // might just be ill-formed because this function attempts to refer to - // a deleted function here. - if (Constructor) - ExceptSpec.CalledDecl(F->getLocation(), Constructor); - } - } - - return ExceptSpec; -} - CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( CXXRecordDecl *ClassDecl) { assert(ClassDecl->needsImplicitMoveConstructor()); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits