|
@@ -22,6 +22,7 @@
|
|
|
#include "clang/AST/DeclTemplate.h"
|
|
|
#include "clang/AST/EvaluatedExprVisitor.h"
|
|
|
#include "clang/AST/ExprCXX.h"
|
|
|
+#include "clang/AST/NonTrivialTypeVisitor.h"
|
|
|
#include "clang/AST/StmtCXX.h"
|
|
|
#include "clang/Basic/Builtins.h"
|
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
|
@@ -6612,6 +6613,11 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
|
|
|
|
|
if (D.isInvalidType())
|
|
|
NewVD->setInvalidDecl();
|
|
|
+
|
|
|
+ if (NewVD->getType().hasNonTrivialToPrimitiveDestructCUnion() &&
|
|
|
+ NewVD->hasLocalStorage())
|
|
|
+ checkNonTrivialCUnion(NewVD->getType(), NewVD->getLocation(),
|
|
|
+ NTCUC_AutoVar, NTCUK_Destruct);
|
|
|
} else {
|
|
|
bool Invalid = false;
|
|
|
|
|
@@ -9061,6 +9067,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|
|
<< FunctionType::getNameForCallConv(CC);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ if (NewFD->getReturnType().hasNonTrivialToPrimitiveDestructCUnion() ||
|
|
|
+ NewFD->getReturnType().hasNonTrivialToPrimitiveCopyCUnion())
|
|
|
+ checkNonTrivialCUnion(NewFD->getReturnType(),
|
|
|
+ NewFD->getReturnTypeSourceRange().getBegin(),
|
|
|
+ NTCUC_FunctionReturn, NTCUK_Destruct|NTCUK_Copy);
|
|
|
} else {
|
|
|
// C++11 [replacement.functions]p3:
|
|
|
// The program's definitions shall not be specified as inline.
|
|
@@ -11207,6 +11219,264 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
|
|
|
return VDecl->isInvalidDecl();
|
|
|
}
|
|
|
|
|
|
+void Sema::checkNonTrivialCUnionInInitializer(const Expr *Init,
|
|
|
+ SourceLocation Loc) {
|
|
|
+ if (auto *CE = dyn_cast<ConstantExpr>(Init))
|
|
|
+ Init = CE->getSubExpr();
|
|
|
+
|
|
|
+ QualType InitType = Init->getType();
|
|
|
+ assert((InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
|
|
|
+ InitType.hasNonTrivialToPrimitiveCopyCUnion()) &&
|
|
|
+ "shouldn't be called if type doesn't have a non-trivial C struct");
|
|
|
+ if (auto *ILE = dyn_cast<InitListExpr>(Init)) {
|
|
|
+ for (auto I : ILE->inits()) {
|
|
|
+ if (!I->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion() &&
|
|
|
+ !I->getType().hasNonTrivialToPrimitiveCopyCUnion())
|
|
|
+ continue;
|
|
|
+ SourceLocation SL = I->getExprLoc();
|
|
|
+ checkNonTrivialCUnionInInitializer(I, SL.isValid() ? SL : Loc);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (isa<ImplicitValueInitExpr>(Init)) {
|
|
|
+ if (InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion())
|
|
|
+ checkNonTrivialCUnion(InitType, Loc, NTCUC_DefaultInitializedObject,
|
|
|
+ NTCUK_Init);
|
|
|
+ } else {
|
|
|
+ // Assume all other explicit initializers involving copying some existing
|
|
|
+ // object.
|
|
|
+ // TODO: ignore any explicit initializers where we can guarantee
|
|
|
+ // copy-elision.
|
|
|
+ if (InitType.hasNonTrivialToPrimitiveCopyCUnion())
|
|
|
+ checkNonTrivialCUnion(InitType, Loc, NTCUC_CopyInit, NTCUK_Copy);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+namespace {
|
|
|
+
|
|
|
+struct DiagNonTrivalCUnionDefaultInitializeVisitor
|
|
|
+ : DefaultInitializedTypeVisitor<DiagNonTrivalCUnionDefaultInitializeVisitor,
|
|
|
+ void> {
|
|
|
+ using Super =
|
|
|
+ DefaultInitializedTypeVisitor<DiagNonTrivalCUnionDefaultInitializeVisitor,
|
|
|
+ void>;
|
|
|
+
|
|
|
+ DiagNonTrivalCUnionDefaultInitializeVisitor(
|
|
|
+ QualType OrigTy, SourceLocation OrigLoc,
|
|
|
+ Sema::NonTrivialCUnionContext UseContext, Sema &S)
|
|
|
+ : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {}
|
|
|
+
|
|
|
+ void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType QT,
|
|
|
+ const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ if (const auto *AT = S.Context.getAsArrayType(QT))
|
|
|
+ return this->asDerived().visit(S.Context.getBaseElementType(AT), FD,
|
|
|
+ InNonTrivialUnion);
|
|
|
+ return Super::visitWithKind(PDIK, QT, FD, InNonTrivialUnion);
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
|
|
|
+ bool InNonTrivialUnion) {
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 1 << 0 << QT << FD->getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 1 << 0 << QT << FD->getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
|
|
|
+ if (RD->isUnion()) {
|
|
|
+ if (OrigLoc.isValid()) {
|
|
|
+ bool IsUnion = false;
|
|
|
+ if (auto *OrigRD = OrigTy->getAsRecordDecl())
|
|
|
+ IsUnion = OrigRD->isUnion();
|
|
|
+ S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context)
|
|
|
+ << 0 << OrigTy << IsUnion << UseContext;
|
|
|
+ // Reset OrigLoc so that this diagnostic is emitted only once.
|
|
|
+ OrigLoc = SourceLocation();
|
|
|
+ }
|
|
|
+ InNonTrivialUnion = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(RD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 0 << 0 << QT.getUnqualifiedType() << "";
|
|
|
+
|
|
|
+ for (const FieldDecl *FD : RD->fields())
|
|
|
+ asDerived().visit(FD->getType(), FD, InNonTrivialUnion);
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {}
|
|
|
+
|
|
|
+ // The non-trivial C union type or the struct/union type that contains a
|
|
|
+ // non-trivial C union.
|
|
|
+ QualType OrigTy;
|
|
|
+ SourceLocation OrigLoc;
|
|
|
+ Sema::NonTrivialCUnionContext UseContext;
|
|
|
+ Sema &S;
|
|
|
+};
|
|
|
+
|
|
|
+struct DiagNonTrivalCUnionDestructedTypeVisitor
|
|
|
+ : DestructedTypeVisitor<DiagNonTrivalCUnionDestructedTypeVisitor, void> {
|
|
|
+ using Super =
|
|
|
+ DestructedTypeVisitor<DiagNonTrivalCUnionDestructedTypeVisitor, void>;
|
|
|
+
|
|
|
+ DiagNonTrivalCUnionDestructedTypeVisitor(
|
|
|
+ QualType OrigTy, SourceLocation OrigLoc,
|
|
|
+ Sema::NonTrivialCUnionContext UseContext, Sema &S)
|
|
|
+ : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {}
|
|
|
+
|
|
|
+ void visitWithKind(QualType::DestructionKind DK, QualType QT,
|
|
|
+ const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ if (const auto *AT = S.Context.getAsArrayType(QT))
|
|
|
+ return this->asDerived().visit(S.Context.getBaseElementType(AT), FD,
|
|
|
+ InNonTrivialUnion);
|
|
|
+ return Super::visitWithKind(DK, QT, FD, InNonTrivialUnion);
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
|
|
|
+ bool InNonTrivialUnion) {
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 1 << 1 << QT << FD->getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 1 << 1 << QT << FD->getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
|
|
|
+ if (RD->isUnion()) {
|
|
|
+ if (OrigLoc.isValid()) {
|
|
|
+ bool IsUnion = false;
|
|
|
+ if (auto *OrigRD = OrigTy->getAsRecordDecl())
|
|
|
+ IsUnion = OrigRD->isUnion();
|
|
|
+ S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context)
|
|
|
+ << 1 << OrigTy << IsUnion << UseContext;
|
|
|
+ // Reset OrigLoc so that this diagnostic is emitted only once.
|
|
|
+ OrigLoc = SourceLocation();
|
|
|
+ }
|
|
|
+ InNonTrivialUnion = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(RD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 0 << 1 << QT.getUnqualifiedType() << "";
|
|
|
+
|
|
|
+ for (const FieldDecl *FD : RD->fields())
|
|
|
+ asDerived().visit(FD->getType(), FD, InNonTrivialUnion);
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {}
|
|
|
+ void visitCXXDestructor(QualType QT, const FieldDecl *FD,
|
|
|
+ bool InNonTrivialUnion) {}
|
|
|
+
|
|
|
+ // The non-trivial C union type or the struct/union type that contains a
|
|
|
+ // non-trivial C union.
|
|
|
+ QualType OrigTy;
|
|
|
+ SourceLocation OrigLoc;
|
|
|
+ Sema::NonTrivialCUnionContext UseContext;
|
|
|
+ Sema &S;
|
|
|
+};
|
|
|
+
|
|
|
+struct DiagNonTrivalCUnionCopyVisitor
|
|
|
+ : CopiedTypeVisitor<DiagNonTrivalCUnionCopyVisitor, false, void> {
|
|
|
+ using Super = CopiedTypeVisitor<DiagNonTrivalCUnionCopyVisitor, false, void>;
|
|
|
+
|
|
|
+ DiagNonTrivalCUnionCopyVisitor(QualType OrigTy, SourceLocation OrigLoc,
|
|
|
+ Sema::NonTrivialCUnionContext UseContext,
|
|
|
+ Sema &S)
|
|
|
+ : OrigTy(OrigTy), OrigLoc(OrigLoc), UseContext(UseContext), S(S) {}
|
|
|
+
|
|
|
+ void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType QT,
|
|
|
+ const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ if (const auto *AT = S.Context.getAsArrayType(QT))
|
|
|
+ return this->asDerived().visit(S.Context.getBaseElementType(AT), FD,
|
|
|
+ InNonTrivialUnion);
|
|
|
+ return Super::visitWithKind(PCK, QT, FD, InNonTrivialUnion);
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitARCStrong(QualType QT, const FieldDecl *FD,
|
|
|
+ bool InNonTrivialUnion) {
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 1 << 2 << QT << FD->getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitARCWeak(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 1 << 2 << QT << FD->getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ void visitStruct(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
|
|
|
+ const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
|
|
|
+ if (RD->isUnion()) {
|
|
|
+ if (OrigLoc.isValid()) {
|
|
|
+ bool IsUnion = false;
|
|
|
+ if (auto *OrigRD = OrigTy->getAsRecordDecl())
|
|
|
+ IsUnion = OrigRD->isUnion();
|
|
|
+ S.Diag(OrigLoc, diag::err_non_trivial_c_union_in_invalid_context)
|
|
|
+ << 2 << OrigTy << IsUnion << UseContext;
|
|
|
+ // Reset OrigLoc so that this diagnostic is emitted only once.
|
|
|
+ OrigLoc = SourceLocation();
|
|
|
+ }
|
|
|
+ InNonTrivialUnion = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (InNonTrivialUnion)
|
|
|
+ S.Diag(RD->getLocation(), diag::note_non_trivial_c_union)
|
|
|
+ << 0 << 2 << QT.getUnqualifiedType() << "";
|
|
|
+
|
|
|
+ for (const FieldDecl *FD : RD->fields())
|
|
|
+ asDerived().visit(FD->getType(), FD, InNonTrivialUnion);
|
|
|
+ }
|
|
|
+
|
|
|
+ void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT,
|
|
|
+ const FieldDecl *FD, bool InNonTrivialUnion) {}
|
|
|
+ void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {}
|
|
|
+ void visitVolatileTrivial(QualType QT, const FieldDecl *FD,
|
|
|
+ bool InNonTrivialUnion) {}
|
|
|
+
|
|
|
+ // The non-trivial C union type or the struct/union type that contains a
|
|
|
+ // non-trivial C union.
|
|
|
+ QualType OrigTy;
|
|
|
+ SourceLocation OrigLoc;
|
|
|
+ Sema::NonTrivialCUnionContext UseContext;
|
|
|
+ Sema &S;
|
|
|
+};
|
|
|
+
|
|
|
+} // namespace
|
|
|
+
|
|
|
+void Sema::checkNonTrivialCUnion(QualType QT, SourceLocation Loc,
|
|
|
+ NonTrivialCUnionContext UseContext,
|
|
|
+ unsigned NonTrivialKind) {
|
|
|
+ assert((QT.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
|
|
|
+ QT.hasNonTrivialToPrimitiveDestructCUnion() ||
|
|
|
+ QT.hasNonTrivialToPrimitiveCopyCUnion()) &&
|
|
|
+ "shouldn't be called if type doesn't have a non-trivial C union");
|
|
|
+
|
|
|
+ if ((NonTrivialKind & NTCUK_Init) &&
|
|
|
+ QT.hasNonTrivialToPrimitiveDefaultInitializeCUnion())
|
|
|
+ DiagNonTrivalCUnionDefaultInitializeVisitor(QT, Loc, UseContext, *this)
|
|
|
+ .visit(QT, nullptr, false);
|
|
|
+ if ((NonTrivialKind & NTCUK_Destruct) &&
|
|
|
+ QT.hasNonTrivialToPrimitiveDestructCUnion())
|
|
|
+ DiagNonTrivalCUnionDestructedTypeVisitor(QT, Loc, UseContext, *this)
|
|
|
+ .visit(QT, nullptr, false);
|
|
|
+ if ((NonTrivialKind & NTCUK_Copy) && QT.hasNonTrivialToPrimitiveCopyCUnion())
|
|
|
+ DiagNonTrivalCUnionCopyVisitor(QT, Loc, UseContext, *this)
|
|
|
+ .visit(QT, nullptr, false);
|
|
|
+}
|
|
|
+
|
|
|
/// AddInitializerToDecl - Adds the initializer Init to the
|
|
|
/// declaration dcl. If DirectInit is true, this is C++ direct
|
|
|
/// initialization rather than copy initialization.
|
|
@@ -11615,6 +11885,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
|
|
|
CheckForConstantInitializer(Init, DclT);
|
|
|
}
|
|
|
|
|
|
+ QualType InitType = Init->getType();
|
|
|
+ if (!InitType.isNull() &&
|
|
|
+ (InitType.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
|
|
|
+ InitType.hasNonTrivialToPrimitiveCopyCUnion()))
|
|
|
+ checkNonTrivialCUnionInInitializer(Init, Init->getExprLoc());
|
|
|
+
|
|
|
// We will represent direct-initialization similarly to copy-initialization:
|
|
|
// int x(1); -as-> int x = 1;
|
|
|
// ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
|
|
@@ -11739,7 +12015,14 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- switch (Var->isThisDeclarationADefinition()) {
|
|
|
+ VarDecl::DefinitionKind DefKind = Var->isThisDeclarationADefinition();
|
|
|
+ if (!Var->isInvalidDecl() && DefKind != VarDecl::DeclarationOnly &&
|
|
|
+ Var->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion())
|
|
|
+ checkNonTrivialCUnion(Var->getType(), Var->getLocation(),
|
|
|
+ NTCUC_DefaultInitializedObject, NTCUK_Init);
|
|
|
+
|
|
|
+
|
|
|
+ switch (DefKind) {
|
|
|
case VarDecl::Definition:
|
|
|
if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
|
|
|
break;
|
|
@@ -12829,6 +13112,11 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
|
|
|
if (auto *LSI = getEnclosingLambda())
|
|
|
LSI->LocalPacks.push_back(New);
|
|
|
|
|
|
+ if (New->getType().hasNonTrivialToPrimitiveDestructCUnion() ||
|
|
|
+ New->getType().hasNonTrivialToPrimitiveCopyCUnion())
|
|
|
+ checkNonTrivialCUnion(New->getType(), New->getLocation(),
|
|
|
+ NTCUC_FunctionParam, NTCUK_Destruct|NTCUK_Copy);
|
|
|
+
|
|
|
// Parameters can not be abstract class types.
|
|
|
// For record types, this is done by the AbstractClassUsageDiagnoser once
|
|
|
// the class has been completely parsed.
|
|
@@ -16077,7 +16365,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|
|
// Verify that all the fields are okay.
|
|
|
SmallVector<FieldDecl*, 32> RecFields;
|
|
|
|
|
|
- bool ObjCFieldLifetimeErrReported = false;
|
|
|
for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
|
|
|
i != end; ++i) {
|
|
|
FieldDecl *FD = cast<FieldDecl>(*i);
|
|
@@ -16216,38 +16503,12 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|
|
Record->setHasObjectMember(true);
|
|
|
if (Record && FDTTy->getDecl()->hasVolatileMember())
|
|
|
Record->setHasVolatileMember(true);
|
|
|
- if (Record && Record->isUnion() &&
|
|
|
- FD->getType().isNonTrivialPrimitiveCType(Context))
|
|
|
- Diag(FD->getLocation(),
|
|
|
- diag::err_nontrivial_primitive_type_in_union);
|
|
|
} else if (FDTy->isObjCObjectType()) {
|
|
|
/// A field cannot be an Objective-c object
|
|
|
Diag(FD->getLocation(), diag::err_statically_allocated_object)
|
|
|
<< FixItHint::CreateInsertion(FD->getLocation(), "*");
|
|
|
QualType T = Context.getObjCObjectPointerType(FD->getType());
|
|
|
FD->setType(T);
|
|
|
- } else if (getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
|
|
|
- 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.
|
|
|
- // FIXME: that's really not sufficient; we need to make the type
|
|
|
- // itself invalid to, say, initialize or copy.
|
|
|
- QualType T = FD->getType();
|
|
|
- if (T.hasNonTrivialObjCLifetime()) {
|
|
|
- SourceLocation loc = FD->getLocation();
|
|
|
- if (getSourceManager().isInSystemHeader(loc)) {
|
|
|
- if (!FD->hasAttr<UnavailableAttr>()) {
|
|
|
- FD->addAttr(UnavailableAttr::CreateImplicit(Context, "",
|
|
|
- UnavailableAttr::IR_ARCFieldWithOwnership, loc));
|
|
|
- }
|
|
|
- } else {
|
|
|
- Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag)
|
|
|
- << T->isBlockPointerType() << Record->getTagKind();
|
|
|
- }
|
|
|
- ObjCFieldLifetimeErrReported = true;
|
|
|
- }
|
|
|
} else if (getLangOpts().ObjC &&
|
|
|
getLangOpts().getGC() != LangOptions::NonGC &&
|
|
|
Record && !Record->hasObjectMember()) {
|
|
@@ -16267,14 +16528,23 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|
|
|
|
|
if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr<UnavailableAttr>()) {
|
|
|
QualType FT = FD->getType();
|
|
|
- if (FT.isNonTrivialToPrimitiveDefaultInitialize())
|
|
|
+ if (FT.isNonTrivialToPrimitiveDefaultInitialize()) {
|
|
|
Record->setNonTrivialToPrimitiveDefaultInitialize(true);
|
|
|
+ if (FT.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
|
|
|
+ Record->isUnion())
|
|
|
+ Record->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(true);
|
|
|
+ }
|
|
|
QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy();
|
|
|
- if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial)
|
|
|
+ if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial) {
|
|
|
Record->setNonTrivialToPrimitiveCopy(true);
|
|
|
+ if (FT.hasNonTrivialToPrimitiveCopyCUnion() || Record->isUnion())
|
|
|
+ Record->setHasNonTrivialToPrimitiveCopyCUnion(true);
|
|
|
+ }
|
|
|
if (FT.isDestructedType()) {
|
|
|
Record->setNonTrivialToPrimitiveDestroy(true);
|
|
|
Record->setParamDestroyedInCallee(true);
|
|
|
+ if (FT.hasNonTrivialToPrimitiveDestructCUnion() || Record->isUnion())
|
|
|
+ Record->setHasNonTrivialToPrimitiveDestructCUnion(true);
|
|
|
}
|
|
|
|
|
|
if (const auto *RT = FT->getAs<RecordType>()) {
|