|
@@ -22,7 +22,6 @@
|
|
#include "clang/AST/DeclTemplate.h"
|
|
#include "clang/AST/DeclTemplate.h"
|
|
#include "clang/AST/EvaluatedExprVisitor.h"
|
|
#include "clang/AST/EvaluatedExprVisitor.h"
|
|
#include "clang/AST/ExprCXX.h"
|
|
#include "clang/AST/ExprCXX.h"
|
|
-#include "clang/AST/NonTrivialTypeVisitor.h"
|
|
|
|
#include "clang/AST/StmtCXX.h"
|
|
#include "clang/AST/StmtCXX.h"
|
|
#include "clang/Basic/Builtins.h"
|
|
#include "clang/Basic/Builtins.h"
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
|
@@ -6505,11 +6504,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
|
|
|
|
|
if (D.isInvalidType())
|
|
if (D.isInvalidType())
|
|
NewVD->setInvalidDecl();
|
|
NewVD->setInvalidDecl();
|
|
-
|
|
|
|
- if (NewVD->getType().hasNonTrivialToPrimitiveDestructCUnion() &&
|
|
|
|
- NewVD->hasLocalStorage())
|
|
|
|
- checkNonTrivialCUnion(NewVD->getType(), NewVD->getLocation(),
|
|
|
|
- NTCUC_AutoVar, NTCUK_Destruct);
|
|
|
|
} else {
|
|
} else {
|
|
bool Invalid = false;
|
|
bool Invalid = false;
|
|
|
|
|
|
@@ -8932,12 +8926,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|
<< FunctionType::getNameForCallConv(CC);
|
|
<< FunctionType::getNameForCallConv(CC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- if (NewFD->getReturnType().hasNonTrivialToPrimitiveDestructCUnion() ||
|
|
|
|
- NewFD->getReturnType().hasNonTrivialToPrimitiveCopyCUnion())
|
|
|
|
- checkNonTrivialCUnion(NewFD->getReturnType(),
|
|
|
|
- NewFD->getReturnTypeSourceRange().getBegin(),
|
|
|
|
- NTCUC_FunctionReturn, NTCUK_Destruct|NTCUK_Copy);
|
|
|
|
} else {
|
|
} else {
|
|
// C++11 [replacement.functions]p3:
|
|
// C++11 [replacement.functions]p3:
|
|
// The program's definitions shall not be specified as inline.
|
|
// The program's definitions shall not be specified as inline.
|
|
@@ -11084,264 +11072,6 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
|
|
return VDecl->isInvalidDecl();
|
|
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
|
|
/// AddInitializerToDecl - Adds the initializer Init to the
|
|
/// declaration dcl. If DirectInit is true, this is C++ direct
|
|
/// declaration dcl. If DirectInit is true, this is C++ direct
|
|
/// initialization rather than copy initialization.
|
|
/// initialization rather than copy initialization.
|
|
@@ -11747,12 +11477,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
|
|
CheckForConstantInitializer(Init, DclT);
|
|
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:
|
|
// We will represent direct-initialization similarly to copy-initialization:
|
|
// int x(1); -as-> int x = 1;
|
|
// int x(1); -as-> int x = 1;
|
|
// ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
|
|
// ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c);
|
|
@@ -11877,14 +11601,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- 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) {
|
|
|
|
|
|
+ switch (Var->isThisDeclarationADefinition()) {
|
|
case VarDecl::Definition:
|
|
case VarDecl::Definition:
|
|
if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
|
|
if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
|
|
break;
|
|
break;
|
|
@@ -12977,11 +12694,6 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
|
|
Context.getAdjustedParameterType(T),
|
|
Context.getAdjustedParameterType(T),
|
|
TSInfo, SC, nullptr);
|
|
TSInfo, SC, nullptr);
|
|
|
|
|
|
- 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.
|
|
// Parameters can not be abstract class types.
|
|
// For record types, this is done by the AbstractClassUsageDiagnoser once
|
|
// For record types, this is done by the AbstractClassUsageDiagnoser once
|
|
// the class has been completely parsed.
|
|
// the class has been completely parsed.
|
|
@@ -16228,6 +15940,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|
// Verify that all the fields are okay.
|
|
// Verify that all the fields are okay.
|
|
SmallVector<FieldDecl*, 32> RecFields;
|
|
SmallVector<FieldDecl*, 32> RecFields;
|
|
|
|
|
|
|
|
+ bool ObjCFieldLifetimeErrReported = false;
|
|
for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
|
|
for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
|
|
i != end; ++i) {
|
|
i != end; ++i) {
|
|
FieldDecl *FD = cast<FieldDecl>(*i);
|
|
FieldDecl *FD = cast<FieldDecl>(*i);
|
|
@@ -16366,12 +16079,38 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|
Record->setHasObjectMember(true);
|
|
Record->setHasObjectMember(true);
|
|
if (Record && FDTTy->getDecl()->hasVolatileMember())
|
|
if (Record && FDTTy->getDecl()->hasVolatileMember())
|
|
Record->setHasVolatileMember(true);
|
|
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()) {
|
|
} else if (FDTy->isObjCObjectType()) {
|
|
/// A field cannot be an Objective-c object
|
|
/// A field cannot be an Objective-c object
|
|
Diag(FD->getLocation(), diag::err_statically_allocated_object)
|
|
Diag(FD->getLocation(), diag::err_statically_allocated_object)
|
|
<< FixItHint::CreateInsertion(FD->getLocation(), "*");
|
|
<< FixItHint::CreateInsertion(FD->getLocation(), "*");
|
|
QualType T = Context.getObjCObjectPointerType(FD->getType());
|
|
QualType T = Context.getObjCObjectPointerType(FD->getType());
|
|
FD->setType(T);
|
|
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 &&
|
|
} else if (getLangOpts().ObjC &&
|
|
getLangOpts().getGC() != LangOptions::NonGC &&
|
|
getLangOpts().getGC() != LangOptions::NonGC &&
|
|
Record && !Record->hasObjectMember()) {
|
|
Record && !Record->hasObjectMember()) {
|
|
@@ -16391,23 +16130,14 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
|
|
|
|
|
|
if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr<UnavailableAttr>()) {
|
|
if (Record && !getLangOpts().CPlusPlus && !FD->hasAttr<UnavailableAttr>()) {
|
|
QualType FT = FD->getType();
|
|
QualType FT = FD->getType();
|
|
- if (FT.isNonTrivialToPrimitiveDefaultInitialize()) {
|
|
|
|
|
|
+ if (FT.isNonTrivialToPrimitiveDefaultInitialize())
|
|
Record->setNonTrivialToPrimitiveDefaultInitialize(true);
|
|
Record->setNonTrivialToPrimitiveDefaultInitialize(true);
|
|
- if (FT.hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
|
|
|
|
- Record->isUnion())
|
|
|
|
- Record->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(true);
|
|
|
|
- }
|
|
|
|
QualType::PrimitiveCopyKind PCK = FT.isNonTrivialToPrimitiveCopy();
|
|
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);
|
|
Record->setNonTrivialToPrimitiveCopy(true);
|
|
- if (FT.hasNonTrivialToPrimitiveCopyCUnion() || Record->isUnion())
|
|
|
|
- Record->setHasNonTrivialToPrimitiveCopyCUnion(true);
|
|
|
|
- }
|
|
|
|
if (FT.isDestructedType()) {
|
|
if (FT.isDestructedType()) {
|
|
Record->setNonTrivialToPrimitiveDestroy(true);
|
|
Record->setNonTrivialToPrimitiveDestroy(true);
|
|
Record->setParamDestroyedInCallee(true);
|
|
Record->setParamDestroyedInCallee(true);
|
|
- if (FT.hasNonTrivialToPrimitiveDestructCUnion() || Record->isUnion())
|
|
|
|
- Record->setHasNonTrivialToPrimitiveDestructCUnion(true);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (const auto *RT = FT->getAs<RecordType>()) {
|
|
if (const auto *RT = FT->getAs<RecordType>()) {
|