aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp42
1 files changed, 30 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index d27f767..215431c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -9546,14 +9546,32 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
CXXMethodDecl *Decl = SMOR.getMethod();
FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
- int DiagKind = -1;
-
- if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
- DiagKind = !Decl ? 0 : 1;
- else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
- DiagKind = 2;
+ enum {
+ NotSet = -1,
+ NoDecl,
+ DeletedDecl,
+ MultipleDecl,
+ InaccessibleDecl,
+ NonTrivialDecl
+ } DiagKind = NotSet;
+
+ if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
+ if (CSM == CXXSpecialMemberKind::DefaultConstructor && Field &&
+ Field->getParent()->isUnion()) {
+ // [class.default.ctor]p2:
+ // A defaulted default constructor for class X is defined as deleted if
+ // - X is a union that has a variant member with a non-trivial default
+ // constructor and no variant member of X has a default member
+ // initializer
+ const auto *RD = cast<CXXRecordDecl>(Field->getParent());
+ if (RD->hasInClassInitializer())
+ return false;
+ }
+ DiagKind = !Decl ? NoDecl : DeletedDecl;
+ } else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+ DiagKind = MultipleDecl;
else if (!isAccessible(Subobj, Decl))
- DiagKind = 3;
+ DiagKind = InaccessibleDecl;
else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
!Decl->isTrivial()) {
// A member of a union must have a trivial corresponding special member.
@@ -9569,13 +9587,13 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
// initializer
const auto *RD = cast<CXXRecordDecl>(Field->getParent());
if (!RD->hasInClassInitializer())
- DiagKind = 4;
+ DiagKind = NonTrivialDecl;
} else {
- DiagKind = 4;
+ DiagKind = NonTrivialDecl;
}
}
- if (DiagKind == -1)
+ if (DiagKind == NotSet)
return false;
if (Diagnose) {
@@ -9593,9 +9611,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
<< /*IsObjCPtr*/ false;
}
- if (DiagKind == 1)
+ if (DiagKind == DeletedDecl)
S.NoteDeletedFunction(Decl);
- // FIXME: Explain inaccessibility if DiagKind == 3.
+ // FIXME: Explain inaccessibility if DiagKind == InaccessibleDecl.
}
return true;