r367076 - Revert "[Sema] Diagnose default-initialization, destruction, and copying of"
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 25 17:02:18 PDT 2019
Author: ahatanak
Date: Thu Jul 25 17:02:17 2019
New Revision: 367076
URL: http://llvm.org/viewvc/llvm-project?rev=367076&view=rev
Log:
Revert "[Sema] Diagnose default-initialization, destruction, and copying of"
This reverts commit r365985.
Prior to r365985, clang used to mark C union fields that have
non-trivial ObjC ownership qualifiers as unavailable if the union was
declared in a system header. r365985 stopped doing so, which caused the
swift compiler to crash when it tried to import a non-trivial union.
I have a patch that fixes the crash (https://reviews.llvm.org/D65256),
but I'm temporarily reverting the original patch until we can decide on
whether it's taking the right approach.
Added:
cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h
Removed:
cfe/trunk/test/PCH/non-trivial-c-union.m
cfe/trunk/test/SemaObjC/non-trivial-c-union.m
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/DeclBase.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m
cfe/trunk/test/SemaObjC/arc-decls.m
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Jul 25 17:02:17 2019
@@ -3746,30 +3746,6 @@ public:
RecordDeclBits.NonTrivialToPrimitiveDestroy = V;
}
- bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const {
- return RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion;
- }
-
- void setHasNonTrivialToPrimitiveDefaultInitializeCUnion(bool V) {
- RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion = V;
- }
-
- bool hasNonTrivialToPrimitiveDestructCUnion() const {
- return RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion;
- }
-
- void setHasNonTrivialToPrimitiveDestructCUnion(bool V) {
- RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion = V;
- }
-
- bool hasNonTrivialToPrimitiveCopyCUnion() const {
- return RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion;
- }
-
- void setHasNonTrivialToPrimitiveCopyCUnion(bool V) {
- RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion = V;
- }
-
/// Determine whether this class can be passed in registers. In C++ mode,
/// it must have at least one trivial, non-deleted copy or move constructor.
/// FIXME: This should be set as part of completeDefinition.
Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Thu Jul 25 17:02:17 2019
@@ -1440,13 +1440,6 @@ class DeclContext {
uint64_t NonTrivialToPrimitiveCopy : 1;
uint64_t NonTrivialToPrimitiveDestroy : 1;
- /// The following bits indicate whether this is or contains a C union that
- /// is non-trivial to default-initialize, destruct, or copy. These bits
- /// imply the associated basic non-triviality predicates declared above.
- uint64_t HasNonTrivialToPrimitiveDefaultInitializeCUnion : 1;
- uint64_t HasNonTrivialToPrimitiveDestructCUnion : 1;
- uint64_t HasNonTrivialToPrimitiveCopyCUnion : 1;
-
/// Indicates whether this struct is destroyed in the callee.
uint64_t ParamDestroyedInCallee : 1;
@@ -1455,7 +1448,7 @@ class DeclContext {
};
/// Number of non-inherited bits in RecordDeclBitfields.
- enum { NumRecordDeclBits = 14 };
+ enum { NumRecordDeclBits = 11 };
/// Stores the bits used by OMPDeclareReductionDecl.
/// If modified NumOMPDeclareReductionDeclBits and the accessor
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Jul 25 17:02:17 2019
@@ -1130,6 +1130,12 @@ public:
};
/// Check if this is a non-trivial type that would cause a C struct
+ /// transitively containing this type to be non-trivial. This function can be
+ /// used to determine whether a field of this type can be declared inside a C
+ /// union.
+ bool isNonTrivialPrimitiveCType(const ASTContext &Ctx) const;
+
+ /// Check if this is a non-trivial type that would cause a C struct
/// transitively containing this type to be non-trivial to copy and return the
/// kind.
PrimitiveCopyKind isNonTrivialToPrimitiveCopy() const;
@@ -1158,22 +1164,6 @@ public:
return isDestructedTypeImpl(*this);
}
- /// Check if this is or contains a C union that is non-trivial to
- /// default-initialize, which is a union that has a member that is non-trivial
- /// to default-initialize. If this returns true,
- /// isNonTrivialToPrimitiveDefaultInitialize returns PDIK_Struct.
- bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const;
-
- /// Check if this is or contains a C union that is non-trivial to destruct,
- /// which is a union that has a member that is non-trivial to destruct. If
- /// this returns true, isDestructedType returns DK_nontrivial_c_struct.
- bool hasNonTrivialToPrimitiveDestructCUnion() const;
-
- /// Check if this is or contains a C union that is non-trivial to copy, which
- /// is a union that has a member that is non-trivial to copy. If this returns
- /// true, isNonTrivialToPrimitiveCopy returns PCK_Struct.
- bool hasNonTrivialToPrimitiveCopyCUnion() const;
-
/// Determine whether expressions of the given type are forbidden
/// from being lvalues in C.
///
@@ -1246,11 +1236,6 @@ private:
const ASTContext &C);
static QualType IgnoreParens(QualType T);
static DestructionKind isDestructedTypeImpl(QualType type);
-
- /// Check if \param RD is or contains a non-trivial C union.
- static bool hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD);
- static bool hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD);
- static bool hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD);
};
} // namespace clang
@@ -6264,24 +6249,6 @@ inline Qualifiers::GC QualType::getObjCG
return getQualifiers().getObjCGCAttr();
}
-inline bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion() const {
- if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
- return hasNonTrivialToPrimitiveDefaultInitializeCUnion(RD);
- return false;
-}
-
-inline bool QualType::hasNonTrivialToPrimitiveDestructCUnion() const {
- if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
- return hasNonTrivialToPrimitiveDestructCUnion(RD);
- return false;
-}
-
-inline bool QualType::hasNonTrivialToPrimitiveCopyCUnion() const {
- if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
- return hasNonTrivialToPrimitiveCopyCUnion(RD);
- return false;
-}
-
inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
if (const auto *PT = t.getAs<PointerType>()) {
if (const auto *FT = PT->getPointeeType()->getAs<FunctionType>())
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 25 17:02:17 2019
@@ -620,23 +620,8 @@ def warn_cstruct_memaccess : Warning<
InGroup<NonTrivialMemaccess>;
def note_nontrivial_field : Note<
"field is non-trivial to %select{copy|default-initialize}0">;
-def err_non_trivial_c_union_in_invalid_context : Error<
- "cannot %select{"
- "use type %1 for a function/method parameter|"
- "use type %1 for function/method return|"
- "default-initialize an object of type %1|"
- "declare an automatic variable of type %1|"
- "copy-initialize an object of type %1|"
- "assign to a variable of type %1|"
- "construct an automatic compound literal of type %1|"
- "capture a variable of type %1|"
- "cannot use volatile type %1 where it causes an lvalue-to-rvalue conversion"
- "}3 "
- "since it %select{contains|is}2 a union that is non-trivial to "
- "%select{default-initialize|destruct|copy}0">;
-def note_non_trivial_c_union : Note<
- "%select{%2 has subobjects that are|%3 has type %2 that is}0 "
- "non-trivial to %select{default-initialize|destruct|copy}1">;
+def err_nontrivial_primitive_type_in_union : Error<
+ "non-trivial C types are disallowed in union">;
def warn_dyn_class_memaccess : Warning<
"%select{destination for|source of|first operand of|second operand of}0 this "
"%1 call is a pointer to %select{|class containing a }2dynamic class %3; "
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jul 25 17:02:17 2019
@@ -2114,48 +2114,6 @@ public:
bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
SourceLocation EqualLoc);
- // Contexts where using non-trivial C union types can be disallowed. This is
- // passed to err_non_trivial_c_union_in_invalid_context.
- enum NonTrivialCUnionContext {
- // Function parameter.
- NTCUC_FunctionParam,
- // Function return.
- NTCUC_FunctionReturn,
- // Default-initialized object.
- NTCUC_DefaultInitializedObject,
- // Variable with automatic storage duration.
- NTCUC_AutoVar,
- // Initializer expression that might copy from another object.
- NTCUC_CopyInit,
- // Assignment.
- NTCUC_Assignment,
- // Compound literal.
- NTCUC_CompoundLiteral,
- // Block capture.
- NTCUC_BlockCapture,
- // lvalue-to-rvalue conversion of volatile type.
- NTCUC_LValueToRValueVolatile,
- };
-
- /// Emit diagnostics if the initializer or any of its explicit or
- /// implicitly-generated subexpressions require copying or
- /// default-initializing a type that is or contains a C union type that is
- /// non-trivial to copy or default-initialize.
- void checkNonTrivialCUnionInInitializer(const Expr *Init, SourceLocation Loc);
-
- // These flags are passed to checkNonTrivialCUnion.
- enum NonTrivialCUnionKind {
- NTCUK_Init = 0x1,
- NTCUK_Destruct = 0x2,
- NTCUK_Copy = 0x4,
- };
-
- /// Emit diagnostics if a non-trivial C union type or a struct that contains
- /// a non-trivial C union is used in an invalid context.
- void checkNonTrivialCUnion(QualType QT, SourceLocation Loc,
- NonTrivialCUnionContext UseContext,
- unsigned NonTrivialKind);
-
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
void ActOnUninitializedDecl(Decl *dcl);
void ActOnInitializerError(Decl *Dcl);
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu Jul 25 17:02:17 2019
@@ -4252,9 +4252,6 @@ RecordDecl::RecordDecl(Kind DK, TagKind
setNonTrivialToPrimitiveDefaultInitialize(false);
setNonTrivialToPrimitiveCopy(false);
setNonTrivialToPrimitiveDestroy(false);
- setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false);
- setHasNonTrivialToPrimitiveDestructCUnion(false);
- setHasNonTrivialToPrimitiveCopyCUnion(false);
setParamDestroyedInCallee(false);
setArgPassingRestrictions(APK_CanPassInRegs);
}
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Thu Jul 25 17:02:17 2019
@@ -2276,16 +2276,60 @@ bool QualType::isNonWeakInMRRWithObjCWea
getObjCLifetime() != Qualifiers::OCL_Weak;
}
-bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD) {
- return RD->hasNonTrivialToPrimitiveDefaultInitializeCUnion();
-}
+namespace {
+// Helper class that determines whether this is a type that is non-trivial to
+// primitive copy or move, or is a struct type that has a field of such type.
+template <bool IsMove>
+struct IsNonTrivialCopyMoveVisitor
+ : CopiedTypeVisitor<IsNonTrivialCopyMoveVisitor<IsMove>, IsMove, bool> {
+ using Super =
+ CopiedTypeVisitor<IsNonTrivialCopyMoveVisitor<IsMove>, IsMove, bool>;
+ IsNonTrivialCopyMoveVisitor(const ASTContext &C) : Ctx(C) {}
+ void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT) {}
-bool QualType::hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD) {
- return RD->hasNonTrivialToPrimitiveDestructCUnion();
-}
+ bool visitWithKind(QualType::PrimitiveCopyKind PCK, QualType QT) {
+ if (const auto *AT = this->Ctx.getAsArrayType(QT))
+ return this->asDerived().visit(Ctx.getBaseElementType(AT));
+ return Super::visitWithKind(PCK, QT);
+ }
+
+ bool visitARCStrong(QualType QT) { return true; }
+ bool visitARCWeak(QualType QT) { return true; }
+ bool visitTrivial(QualType QT) { return false; }
+ // Volatile fields are considered trivial.
+ bool visitVolatileTrivial(QualType QT) { return false; }
+
+ bool visitStruct(QualType QT) {
+ const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
+ // We don't want to apply the C restriction in C++ because C++
+ // (1) can apply the restriction at a finer grain by banning copying or
+ // destroying the union, and
+ // (2) allows users to override these restrictions by declaring explicit
+ // constructors/etc, which we're not proposing to add to C.
+ if (isa<CXXRecordDecl>(RD))
+ return false;
+ for (const FieldDecl *FD : RD->fields())
+ if (this->asDerived().visit(FD->getType()))
+ return true;
+ return false;
+ }
+
+ const ASTContext &Ctx;
+};
+
+} // namespace
-bool QualType::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) {
- return RD->hasNonTrivialToPrimitiveCopyCUnion();
+bool QualType::isNonTrivialPrimitiveCType(const ASTContext &Ctx) const {
+ if (isNonTrivialToPrimitiveDefaultInitialize())
+ return true;
+ DestructionKind DK = isDestructedType();
+ if (DK != DK_none && DK != DK_cxx_destructor)
+ return true;
+ if (IsNonTrivialCopyMoveVisitor<false>(Ctx).visit(*this))
+ return true;
+ if (IsNonTrivialCopyMoveVisitor<true>(Ctx).visit(*this))
+ return true;
+ return false;
}
QualType::PrimitiveDefaultInitializeKind
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Jul 25 17:02:17 2019
@@ -1658,24 +1658,12 @@ static void markEscapingByrefs(const Fun
// Set the EscapingByref flag of __block variables captured by
// escaping blocks.
for (const BlockDecl *BD : FSI.Blocks) {
+ if (BD->doesNotEscape())
+ continue;
for (const BlockDecl::Capture &BC : BD->captures()) {
VarDecl *VD = BC.getVariable();
- if (VD->hasAttr<BlocksAttr>()) {
- // Nothing to do if this is a __block variable captured by a
- // non-escaping block.
- if (BD->doesNotEscape())
- continue;
+ if (VD->hasAttr<BlocksAttr>())
VD->setEscapingByref();
- }
- // Check whether the captured variable is or contains an object of
- // non-trivial C union type.
- QualType CapType = BC.getVariable()->getType();
- if (CapType.hasNonTrivialToPrimitiveDestructCUnion() ||
- CapType.hasNonTrivialToPrimitiveCopyCUnion())
- S.checkNonTrivialCUnion(BC.getVariable()->getType(),
- BD->getCaretLocation(),
- Sema::NTCUC_BlockCapture,
- Sema::NTCUK_Destruct|Sema::NTCUK_Copy);
}
}
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jul 25 17:02:17 2019
@@ -22,7 +22,6 @@
#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"
@@ -6505,11 +6504,6 @@ 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;
@@ -8932,12 +8926,6 @@ Sema::ActOnFunctionDeclarator(Scope *S,
<< 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.
@@ -11084,264 +11072,6 @@ bool Sema::DeduceVariableDeclarationType
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.
@@ -11747,12 +11477,6 @@ void Sema::AddInitializerToDecl(Decl *Re
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);
@@ -11877,14 +11601,7 @@ void Sema::ActOnUninitializedDecl(Decl *
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:
if (!Var->isStaticDataMember() || !Var->getAnyInitializer())
break;
@@ -12977,11 +12694,6 @@ ParmVarDecl *Sema::CheckParameter(DeclCo
Context.getAdjustedParameterType(T),
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.
// For record types, this is done by the AbstractClassUsageDiagnoser once
// the class has been completely parsed.
@@ -16228,6 +15940,7 @@ void Sema::ActOnFields(Scope *S, SourceL
// 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);
@@ -16366,12 +16079,38 @@ void Sema::ActOnFields(Scope *S, SourceL
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()) {
@@ -16391,23 +16130,14 @@ void Sema::ActOnFields(Scope *S, SourceL
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>()) {
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jul 25 17:02:17 2019
@@ -6076,7 +6076,7 @@ Sema::BuildCompoundLiteralExpr(SourceLoc
ILE->setInit(i, ConstantExpr::Create(Context, Init));
}
- auto *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
+ Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
VK, LiteralExpr, isFileScope);
if (isFileScope) {
if (!LiteralExpr->isTypeDependent() &&
@@ -6094,19 +6094,6 @@ Sema::BuildCompoundLiteralExpr(SourceLoc
return ExprError();
}
- // Compound literals that have automatic storage duration are destroyed at
- // the end of the scope. Emit diagnostics if it is or contains a C union type
- // that is non-trivial to destruct.
- if (!isFileScope)
- if (E->getType().hasNonTrivialToPrimitiveDestructCUnion())
- checkNonTrivialCUnion(E->getType(), E->getExprLoc(),
- NTCUC_CompoundLiteral, NTCUK_Destruct);
-
- if (E->getType().hasNonTrivialToPrimitiveDefaultInitializeCUnion() ||
- E->getType().hasNonTrivialToPrimitiveCopyCUnion())
- checkNonTrivialCUnionInInitializer(E->getInitializer(),
- E->getInitializer()->getExprLoc());
-
return MaybeBindToTemporary(E);
}
@@ -12556,10 +12543,6 @@ ExprResult Sema::CreateBuiltinBinOp(Sour
if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
if (VD->hasLocalStorage() && getCurScope()->isDeclScope(VD))
BE->getBlockDecl()->setCanAvoidCopyToHeap();
-
- if (LHS.get()->getType().hasNonTrivialToPrimitiveCopyCUnion())
- checkNonTrivialCUnion(LHS.get()->getType(), LHS.get()->getExprLoc(),
- NTCUC_Assignment, NTCUK_Copy);
}
RecordModifiableNonNullParam(*this, LHS.get());
break;
@@ -13972,11 +13955,6 @@ ExprResult Sema::ActOnBlockStmtExpr(Sour
!BD->isDependentContext())
computeNRVO(Body, BSI);
- if (RetTy.hasNonTrivialToPrimitiveDestructCUnion() ||
- RetTy.hasNonTrivialToPrimitiveCopyCUnion())
- checkNonTrivialCUnion(RetTy, BD->getCaretLocation(), NTCUC_FunctionReturn,
- NTCUK_Destruct|NTCUK_Copy);
-
PopDeclContext();
// Pop the block scope now but keep it alive to the end of this function.
@@ -16228,15 +16206,6 @@ static ExprResult rebuildPotentialResult
}
ExprResult Sema::CheckLValueToRValueConversionOperand(Expr *E) {
- // Check whether the operand is or contains an object of non-trivial C union
- // type.
- if (E->getType().isVolatileQualified() &&
- (E->getType().hasNonTrivialToPrimitiveDestructCUnion() ||
- E->getType().hasNonTrivialToPrimitiveCopyCUnion()))
- checkNonTrivialCUnion(E->getType(), E->getExprLoc(),
- Sema::NTCUC_LValueToRValueVolatile,
- NTCUK_Destruct|NTCUK_Copy);
-
// C++2a [basic.def.odr]p4:
// [...] an expression of non-volatile-qualified non-class type to which
// the lvalue-to-rvalue conversion is applied [...]
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Jul 25 17:02:17 2019
@@ -2456,11 +2456,6 @@ bool Sema::CheckFunctionReturnType(QualT
return true;
}
- if (T.hasNonTrivialToPrimitiveDestructCUnion() ||
- T.hasNonTrivialToPrimitiveCopyCUnion())
- checkNonTrivialCUnion(T, Loc, NTCUC_FunctionReturn,
- NTCUK_Destruct|NTCUK_Copy);
-
return false;
}
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Jul 25 17:02:17 2019
@@ -794,9 +794,6 @@ ASTDeclReader::VisitRecordDeclImpl(Recor
RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt());
RD->setNonTrivialToPrimitiveCopy(Record.readInt());
RD->setNonTrivialToPrimitiveDestroy(Record.readInt());
- RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(Record.readInt());
- RD->setHasNonTrivialToPrimitiveDestructCUnion(Record.readInt());
- RD->setHasNonTrivialToPrimitiveCopyCUnion(Record.readInt());
RD->setParamDestroyedInCallee(Record.readInt());
RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt());
return Redecl;
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Thu Jul 25 17:02:17 2019
@@ -476,9 +476,6 @@ void ASTDeclWriter::VisitRecordDecl(Reco
Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize());
Record.push_back(D->isNonTrivialToPrimitiveCopy());
Record.push_back(D->isNonTrivialToPrimitiveDestroy());
- Record.push_back(D->hasNonTrivialToPrimitiveDefaultInitializeCUnion());
- Record.push_back(D->hasNonTrivialToPrimitiveDestructCUnion());
- Record.push_back(D->hasNonTrivialToPrimitiveCopyCUnion());
Record.push_back(D->isParamDestroyedInCallee());
Record.push_back(D->getArgPassingRestrictions());
@@ -2002,12 +1999,6 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
// isNonTrivialToPrimitiveDestroy
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
- // hasNonTrivialToPrimitiveDefaultInitializeCUnion
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
- // hasNonTrivialToPrimitiveDestructCUnion
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
- // hasNonTrivialToPrimitiveCopyCUnion
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
// isParamDestroyedInCallee
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
// getArgPassingRestrictions
Added: cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h?rev=367076&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h (added)
+++ cfe/trunk/test/CodeGenObjC/Inputs/strong_in_union.h Thu Jul 25 17:02:17 2019
@@ -0,0 +1,10 @@
+#ifndef STRONG_IN_UNION_H
+#define STRONG_IN_UNION_H
+#pragma clang system_header
+
+typedef union {
+ id f0;
+ int *f1;
+} U;
+
+#endif // STRONG_IN_UNION_H
Modified: cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m (original)
+++ cfe/trunk/test/CodeGenObjC/strong-in-c-struct.m Thu Jul 25 17:02:17 2019
@@ -1,10 +1,11 @@
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -o %t %s
-// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT %s | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -emit-pch -I %S/Inputs -o %t %s
+// RUN: %clang_cc1 -triple arm64-apple-ios11 -fobjc-arc -fblocks -fobjc-runtime=ios-11.0 -include-pch %t -emit-llvm -o - -DUSESTRUCT -I %S/Inputs %s | FileCheck %s
#ifndef HEADER
#define HEADER
+#include "strong_in_union.h"
typedef void (^BlockTy)(void);
@@ -694,6 +695,14 @@ void test_copy_constructor_Bitfield1(Bit
Bitfield1 t = *a;
}
+// CHECK: define void @test_strong_in_union()
+// CHECK: alloca %{{.*}}
+// CHECK-NEXT: ret void
+
+void test_strong_in_union() {
+ U t;
+}
+
// CHECK: define void @test_copy_constructor_VolatileArray(
// CHECK: call void @__copy_constructor_8_8_s0_AB8s4n16_tv64w32_AE(
Removed: cfe/trunk/test/PCH/non-trivial-c-union.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/non-trivial-c-union.m?rev=367075&view=auto
==============================================================================
--- cfe/trunk/test/PCH/non-trivial-c-union.m (original)
+++ cfe/trunk/test/PCH/non-trivial-c-union.m (removed)
@@ -1,24 +0,0 @@
-// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -emit-pch -o %t.pch %s
-// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -include-pch %t.pch -verify %s
-
-#ifndef HEADER
-#define HEADER
-
-typedef union {
- id f0;
-} U0;
-
-#else
-
-// expected-note at -6 {{'U0' has subobjects that are non-trivial to destruct}}
-// expected-note at -7 {{'U0' has subobjects that are non-trivial to copy}}
-// expected-note at -8 {{'U0' has subobjects that are non-trivial to default-initialize}}
-// expected-note at -8 {{f0 has type '__strong id' that is non-trivial to destruct}}
-// expected-note at -9 {{f0 has type '__strong id' that is non-trivial to copy}}
-// expected-note at -10 {{f0 has type '__strong id' that is non-trivial to default-initialize}}
-
-U0 foo0(void); // expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}}
-
-U0 g0; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-
-#endif
Modified: cfe/trunk/test/SemaObjC/arc-decls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-decls.m?rev=367076&r1=367075&r2=367076&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-decls.m (original)
+++ cfe/trunk/test/SemaObjC/arc-decls.m Thu Jul 25 17:02:17 2019
@@ -8,7 +8,11 @@ struct A {
};
union u {
- id u;
+ id u; // expected-error {{ARC forbids Objective-C objects in union}}
+};
+
+union u_nontrivial_c {
+ struct A a; // expected-error {{non-trivial C types are disallowed in union}}
};
// Volatile fields are fine.
Removed: cfe/trunk/test/SemaObjC/non-trivial-c-union.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/non-trivial-c-union.m?rev=367075&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/non-trivial-c-union.m (original)
+++ cfe/trunk/test/SemaObjC/non-trivial-c-union.m (removed)
@@ -1,82 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -fblocks -fobjc-arc -fobjc-runtime-has-weak -verify %s
-
-typedef union { // expected-note 12 {{'U0' has subobjects that are non-trivial to default-initialize}} expected-note 36 {{'U0' has subobjects that are non-trivial to destruct}} expected-note 28 {{'U0' has subobjects that are non-trivial to copy}}
- id f0; // expected-note 12 {{f0 has type '__strong id' that is non-trivial to default-initialize}} expected-note 36 {{f0 has type '__strong id' that is non-trivial to destruct}} expected-note 28 {{f0 has type '__strong id' that is non-trivial to copy}}
- __weak id f1; // expected-note 12 {{f1 has type '__weak id' that is non-trivial to default-initialize}} expected-note 36 {{f1 has type '__weak id' that is non-trivial to destruct}} expected-note 28 {{f1 has type '__weak id' that is non-trivial to copy}}
-} U0;
-
-typedef struct {
- U0 f0;
- id f1;
-} S0;
-
-id g0;
-U0 ug0; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-U0 ug1 = { .f0 = 0 };
-S0 sg0; // expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}}
-S0 sg1 = { .f0 = {0}, .f1 = 0 };
-S0 sg2 = { .f1 = 0 }; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-
-U0 foo0(U0); // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}}
-S0 foo1(S0); // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}}
-
- at interface C
--(U0)m0:(U0)arg; // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}}
--(S0)m1:(S0)arg; // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}}
- at end
-
-void testBlockFunction(void) {
- (void)^(U0 a){ return ug0; }; // expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for a function/method parameter since it is a union that is non-trivial to copy}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to destruct}} expected-error {{cannot use type 'U0' for function/method return since it is a union that is non-trivial to copy}}
- (void)^(S0 a){ return sg0; }; // expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for a function/method parameter since it contains a union that is non-trivial to copy}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to destruct}} expected-error {{cannot use type 'S0' for function/method return since it contains a union that is non-trivial to copy}}
-}
-void testAutoVar(void) {
- U0 u0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
- U0 u1 = ug0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
- U0 u2 = { g0 }; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}}
- U0 u3 = { .f1 = g0 }; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}}
- S0 s0; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}}
- S0 s1 = sg0; // expected-error {{declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'S0' since it contains a union that is non-trivial to copy}}
- S0 s2 = { ug0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
- S0 s3 = { .f0 = ug0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
- S0 s4 = { .f1 = g0 }; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-}
-
-void testAssignment(void) {
- ug0 = ug1; // expected-error {{cannot assign to a variable of type 'U0' since it is a union that is non-trivial to copy}}
- sg0 = sg1; // expected-error {{cannot assign to a variable of type 'S0' since it contains a union that is non-trivial to copy}}
-}
-
-U0 ug2 = (U0){ .f1 = 0 }; // expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
-S0 sg3 = (S0){ .f0 = {0}, .f1 = 0 }; // expected-error {{cannot copy-initialize an object of type 'S0' since it contains a union that is non-trivial to copy}}
-S0 *sg4 = &(S0){ .f1 = 0 }; // expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-
-void testCompoundLiteral(void) {
- const U0 *t0 = &(U0){ .f0 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'U0' since it is a union that is non-trivial to destruct}}
- const U0 *t1 = &(U0){ .f1 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'U0' since it is a union that is non-trivial to destruct}}
- const S0 *t2 = &(S0){ .f0 = ug0 }; // expected-error {{cannot construct an automatic compound literal of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot copy-initialize an object of type 'U0' since it is a union that is non-trivial to copy}}
- const S0 *t3 = &(S0){ .f1 = g0 }; // expected-error {{cannot construct an automatic compound literal of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
-}
-
-typedef void (^BlockTy)(void);
-void escapingFunc(BlockTy);
-void noescapingFunc(__attribute__((noescape)) BlockTy);
-
-void testBlockCapture(void) {
- U0 t0; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
- S0 t1; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}}
- __block U0 t2; // expected-error {{cannot declare an automatic variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'U0' since it is a union that is non-trivial to default-initialize}}
- __block S0 t3; // expected-error {{cannot declare an automatic variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot default-initialize an object of type 'S0' since it contains a union that is non-trivial to default-initialize}}
-
- escapingFunc(^{ g0 = t0.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}}
- escapingFunc(^{ g0 = t1.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}}
- escapingFunc(^{ g0 = t2.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}}
- escapingFunc(^{ g0 = t3.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}}
- noescapingFunc(^{ g0 = t0.f0; }); // expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'U0' since it is a union that is non-trivial to copy}}
- noescapingFunc(^{ g0 = t1.f0.f0; }); // expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to destruct}} expected-error {{cannot capture a variable of type 'S0' since it contains a union that is non-trivial to copy}}
- noescapingFunc(^{ g0 = t2.f0; });
- noescapingFunc(^{ g0 = t3.f0.f0; });
-}
-
-void testVolatileLValueToRValue(volatile U0 *a) {
- (void)*a; // expected-error {{cannot use volatile type 'volatile U0' where it causes an lvalue-to-rvalue conversion since it is a union that is non-trivial to destruct}} // expected-error {{cannot use volatile type 'volatile U0' where it causes an lvalue-to-rvalue conversion since it is a union that is non-trivial to copy}}
-}
More information about the cfe-commits
mailing list