summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp3
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp40
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;
OpenPOWER on IntegriCloud