diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 40 |
2 files changed, 39 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5b6fd880ca8..c8a69c4d537 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15923,7 +15923,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && - Record && !ObjCFieldLifetimeErrReported && Record->isUnion()) { + Record && !ObjCFieldLifetimeErrReported && Record->isUnion() && + !getLangOpts().CPlusPlus) { // It's an error in ARC or Weak if a field has lifetime. // We don't want to report this in a system header, though, // so we just make the field unavailable. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index de87f985d68..c54e700f51c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -6891,6 +6891,8 @@ struct SpecialMemberDeletionInfo return ICI ? Sema::CXXInvalid : CSM; } + bool shouldDeleteForVariantObjCPtrMember(FieldDecl *FD, QualType FieldType); + bool visitBase(CXXBaseSpecifier *Base) { return shouldDeleteForBase(Base); } bool visitField(FieldDecl *Field) { return shouldDeleteForField(Field); } @@ -6962,13 +6964,14 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( S.Diag(Field->getLocation(), diag::note_deleted_special_member_class_subobject) << getEffectiveCSM() << MD->getParent() << /*IsField*/true - << Field << DiagKind << IsDtorCallInCtor; + << Field << DiagKind << IsDtorCallInCtor << /*IsObjCPtr*/false; } else { CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>(); S.Diag(Base->getBeginLoc(), diag::note_deleted_special_member_class_subobject) << getEffectiveCSM() << MD->getParent() << /*IsField*/ false - << Base->getType() << DiagKind << IsDtorCallInCtor; + << Base->getType() << DiagKind << IsDtorCallInCtor + << /*IsObjCPtr*/false; } if (DiagKind == 1) @@ -7020,6 +7023,30 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( return false; } +bool SpecialMemberDeletionInfo::shouldDeleteForVariantObjCPtrMember( + FieldDecl *FD, QualType FieldType) { + // The defaulted special functions are defined as deleted if this is a variant + // member with a non-trivial ownership type, e.g., ObjC __strong or __weak + // type under ARC. + if (!FieldType.hasNonTrivialObjCLifetime()) + return false; + + // Don't make the defaulted default constructor defined as deleted if the + // member has an in-class initializer. + if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) + return false; + + if (Diagnose) { + auto *ParentClass = cast<CXXRecordDecl>(FD->getParent()); + S.Diag(FD->getLocation(), + diag::note_deleted_special_member_class_subobject) + << getEffectiveCSM() << ParentClass << /*IsField*/true + << FD << 4 << /*IsDtorCallInCtor*/false << /*IsObjCPtr*/true; + } + + return true; +} + /// Check whether we should delete a special member function due to the class /// having a particular direct or virtual base class. bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { @@ -7040,7 +7067,8 @@ bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { S.Diag(Base->getBeginLoc(), diag::note_deleted_special_member_class_subobject) << getEffectiveCSM() << MD->getParent() << /*IsField*/ false - << Base->getType() << /*Deleted*/ 1 << /*IsDtorCallInCtor*/ false; + << Base->getType() << /*Deleted*/ 1 << /*IsDtorCallInCtor*/ false + << /*IsObjCPtr*/false; S.NoteDeletedFunction(BaseCtor); } return BaseCtor->isDeleted(); @@ -7054,6 +7082,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { QualType FieldType = S.Context.getBaseElementType(FD->getType()); CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + if (inUnion() && shouldDeleteForVariantObjCPtrMember(FD, FieldType)) + return true; + if (CSM == Sema::CXXDefaultConstructor) { // For a default constructor, all references must be initialized in-class // and, if a union, it must have a non-const member. @@ -7115,6 +7146,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { for (auto *UI : FieldRecord->fields()) { QualType UnionFieldType = S.Context.getBaseElementType(UI->getType()); + if (shouldDeleteForVariantObjCPtrMember(&*UI, UnionFieldType)) + return true; + if (!UnionFieldType.isConstQualified()) AllVariantFieldsAreConst = false; |