Skip to content

Commit 6f6156b

Browse files
committed
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. llvm-svn: 367076
1 parent c07fe30 commit 6f6156b

18 files changed

+122
-615
lines changed

clang/include/clang/AST/Decl.h

-24
Original file line numberDiff line numberDiff line change
@@ -3746,30 +3746,6 @@ class RecordDecl : public TagDecl {
37463746
RecordDeclBits.NonTrivialToPrimitiveDestroy = V;
37473747
}
37483748

3749-
bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const {
3750-
return RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion;
3751-
}
3752-
3753-
void setHasNonTrivialToPrimitiveDefaultInitializeCUnion(bool V) {
3754-
RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion = V;
3755-
}
3756-
3757-
bool hasNonTrivialToPrimitiveDestructCUnion() const {
3758-
return RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion;
3759-
}
3760-
3761-
void setHasNonTrivialToPrimitiveDestructCUnion(bool V) {
3762-
RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion = V;
3763-
}
3764-
3765-
bool hasNonTrivialToPrimitiveCopyCUnion() const {
3766-
return RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion;
3767-
}
3768-
3769-
void setHasNonTrivialToPrimitiveCopyCUnion(bool V) {
3770-
RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion = V;
3771-
}
3772-
37733749
/// Determine whether this class can be passed in registers. In C++ mode,
37743750
/// it must have at least one trivial, non-deleted copy or move constructor.
37753751
/// FIXME: This should be set as part of completeDefinition.

clang/include/clang/AST/DeclBase.h

+1-8
Original file line numberDiff line numberDiff line change
@@ -1440,13 +1440,6 @@ class DeclContext {
14401440
uint64_t NonTrivialToPrimitiveCopy : 1;
14411441
uint64_t NonTrivialToPrimitiveDestroy : 1;
14421442

1443-
/// The following bits indicate whether this is or contains a C union that
1444-
/// is non-trivial to default-initialize, destruct, or copy. These bits
1445-
/// imply the associated basic non-triviality predicates declared above.
1446-
uint64_t HasNonTrivialToPrimitiveDefaultInitializeCUnion : 1;
1447-
uint64_t HasNonTrivialToPrimitiveDestructCUnion : 1;
1448-
uint64_t HasNonTrivialToPrimitiveCopyCUnion : 1;
1449-
14501443
/// Indicates whether this struct is destroyed in the callee.
14511444
uint64_t ParamDestroyedInCallee : 1;
14521445

@@ -1455,7 +1448,7 @@ class DeclContext {
14551448
};
14561449

14571450
/// Number of non-inherited bits in RecordDeclBitfields.
1458-
enum { NumRecordDeclBits = 14 };
1451+
enum { NumRecordDeclBits = 11 };
14591452

14601453
/// Stores the bits used by OMPDeclareReductionDecl.
14611454
/// If modified NumOMPDeclareReductionDeclBits and the accessor

clang/include/clang/AST/Type.h

+6-39
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,12 @@ class QualType {
11291129
PCK_Struct
11301130
};
11311131

1132+
/// Check if this is a non-trivial type that would cause a C struct
1133+
/// transitively containing this type to be non-trivial. This function can be
1134+
/// used to determine whether a field of this type can be declared inside a C
1135+
/// union.
1136+
bool isNonTrivialPrimitiveCType(const ASTContext &Ctx) const;
1137+
11321138
/// Check if this is a non-trivial type that would cause a C struct
11331139
/// transitively containing this type to be non-trivial to copy and return the
11341140
/// kind.
@@ -1158,22 +1164,6 @@ class QualType {
11581164
return isDestructedTypeImpl(*this);
11591165
}
11601166

1161-
/// Check if this is or contains a C union that is non-trivial to
1162-
/// default-initialize, which is a union that has a member that is non-trivial
1163-
/// to default-initialize. If this returns true,
1164-
/// isNonTrivialToPrimitiveDefaultInitialize returns PDIK_Struct.
1165-
bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const;
1166-
1167-
/// Check if this is or contains a C union that is non-trivial to destruct,
1168-
/// which is a union that has a member that is non-trivial to destruct. If
1169-
/// this returns true, isDestructedType returns DK_nontrivial_c_struct.
1170-
bool hasNonTrivialToPrimitiveDestructCUnion() const;
1171-
1172-
/// Check if this is or contains a C union that is non-trivial to copy, which
1173-
/// is a union that has a member that is non-trivial to copy. If this returns
1174-
/// true, isNonTrivialToPrimitiveCopy returns PCK_Struct.
1175-
bool hasNonTrivialToPrimitiveCopyCUnion() const;
1176-
11771167
/// Determine whether expressions of the given type are forbidden
11781168
/// from being lvalues in C.
11791169
///
@@ -1246,11 +1236,6 @@ class QualType {
12461236
const ASTContext &C);
12471237
static QualType IgnoreParens(QualType T);
12481238
static DestructionKind isDestructedTypeImpl(QualType type);
1249-
1250-
/// Check if \param RD is or contains a non-trivial C union.
1251-
static bool hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD);
1252-
static bool hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD);
1253-
static bool hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD);
12541239
};
12551240

12561241
} // namespace clang
@@ -6264,24 +6249,6 @@ inline Qualifiers::GC QualType::getObjCGCAttr() const {
62646249
return getQualifiers().getObjCGCAttr();
62656250
}
62666251

6267-
inline bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion() const {
6268-
if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
6269-
return hasNonTrivialToPrimitiveDefaultInitializeCUnion(RD);
6270-
return false;
6271-
}
6272-
6273-
inline bool QualType::hasNonTrivialToPrimitiveDestructCUnion() const {
6274-
if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
6275-
return hasNonTrivialToPrimitiveDestructCUnion(RD);
6276-
return false;
6277-
}
6278-
6279-
inline bool QualType::hasNonTrivialToPrimitiveCopyCUnion() const {
6280-
if (auto *RD = getTypePtr()->getBaseElementTypeUnsafe()->getAsRecordDecl())
6281-
return hasNonTrivialToPrimitiveCopyCUnion(RD);
6282-
return false;
6283-
}
6284-
62856252
inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) {
62866253
if (const auto *PT = t.getAs<PointerType>()) {
62876254
if (const auto *FT = PT->getPointeeType()->getAs<FunctionType>())

clang/include/clang/Basic/DiagnosticSemaKinds.td

+2-17
Original file line numberDiff line numberDiff line change
@@ -620,23 +620,8 @@ def warn_cstruct_memaccess : Warning<
620620
InGroup<NonTrivialMemaccess>;
621621
def note_nontrivial_field : Note<
622622
"field is non-trivial to %select{copy|default-initialize}0">;
623-
def err_non_trivial_c_union_in_invalid_context : Error<
624-
"cannot %select{"
625-
"use type %1 for a function/method parameter|"
626-
"use type %1 for function/method return|"
627-
"default-initialize an object of type %1|"
628-
"declare an automatic variable of type %1|"
629-
"copy-initialize an object of type %1|"
630-
"assign to a variable of type %1|"
631-
"construct an automatic compound literal of type %1|"
632-
"capture a variable of type %1|"
633-
"cannot use volatile type %1 where it causes an lvalue-to-rvalue conversion"
634-
"}3 "
635-
"since it %select{contains|is}2 a union that is non-trivial to "
636-
"%select{default-initialize|destruct|copy}0">;
637-
def note_non_trivial_c_union : Note<
638-
"%select{%2 has subobjects that are|%3 has type %2 that is}0 "
639-
"non-trivial to %select{default-initialize|destruct|copy}1">;
623+
def err_nontrivial_primitive_type_in_union : Error<
624+
"non-trivial C types are disallowed in union">;
640625
def warn_dyn_class_memaccess : Warning<
641626
"%select{destination for|source of|first operand of|second operand of}0 this "
642627
"%1 call is a pointer to %select{|class containing a }2dynamic class %3; "

clang/include/clang/Sema/Sema.h

-42
Original file line numberDiff line numberDiff line change
@@ -2114,48 +2114,6 @@ class Sema {
21142114
bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
21152115
SourceLocation EqualLoc);
21162116

2117-
// Contexts where using non-trivial C union types can be disallowed. This is
2118-
// passed to err_non_trivial_c_union_in_invalid_context.
2119-
enum NonTrivialCUnionContext {
2120-
// Function parameter.
2121-
NTCUC_FunctionParam,
2122-
// Function return.
2123-
NTCUC_FunctionReturn,
2124-
// Default-initialized object.
2125-
NTCUC_DefaultInitializedObject,
2126-
// Variable with automatic storage duration.
2127-
NTCUC_AutoVar,
2128-
// Initializer expression that might copy from another object.
2129-
NTCUC_CopyInit,
2130-
// Assignment.
2131-
NTCUC_Assignment,
2132-
// Compound literal.
2133-
NTCUC_CompoundLiteral,
2134-
// Block capture.
2135-
NTCUC_BlockCapture,
2136-
// lvalue-to-rvalue conversion of volatile type.
2137-
NTCUC_LValueToRValueVolatile,
2138-
};
2139-
2140-
/// Emit diagnostics if the initializer or any of its explicit or
2141-
/// implicitly-generated subexpressions require copying or
2142-
/// default-initializing a type that is or contains a C union type that is
2143-
/// non-trivial to copy or default-initialize.
2144-
void checkNonTrivialCUnionInInitializer(const Expr *Init, SourceLocation Loc);
2145-
2146-
// These flags are passed to checkNonTrivialCUnion.
2147-
enum NonTrivialCUnionKind {
2148-
NTCUK_Init = 0x1,
2149-
NTCUK_Destruct = 0x2,
2150-
NTCUK_Copy = 0x4,
2151-
};
2152-
2153-
/// Emit diagnostics if a non-trivial C union type or a struct that contains
2154-
/// a non-trivial C union is used in an invalid context.
2155-
void checkNonTrivialCUnion(QualType QT, SourceLocation Loc,
2156-
NonTrivialCUnionContext UseContext,
2157-
unsigned NonTrivialKind);
2158-
21592117
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit);
21602118
void ActOnUninitializedDecl(Decl *dcl);
21612119
void ActOnInitializerError(Decl *Dcl);

clang/lib/AST/Decl.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -4252,9 +4252,6 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
42524252
setNonTrivialToPrimitiveDefaultInitialize(false);
42534253
setNonTrivialToPrimitiveCopy(false);
42544254
setNonTrivialToPrimitiveDestroy(false);
4255-
setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false);
4256-
setHasNonTrivialToPrimitiveDestructCUnion(false);
4257-
setHasNonTrivialToPrimitiveCopyCUnion(false);
42584255
setParamDestroyedInCallee(false);
42594256
setArgPassingRestrictions(APK_CanPassInRegs);
42604257
}

clang/lib/AST/Type.cpp

+52-8
Original file line numberDiff line numberDiff line change
@@ -2276,16 +2276,60 @@ bool QualType::isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const {
22762276
getObjCLifetime() != Qualifiers::OCL_Weak;
22772277
}
22782278

2279-
bool QualType::hasNonTrivialToPrimitiveDefaultInitializeCUnion(const RecordDecl *RD) {
2280-
return RD->hasNonTrivialToPrimitiveDefaultInitializeCUnion();
2281-
}
2279+
namespace {
2280+
// Helper class that determines whether this is a type that is non-trivial to
2281+
// primitive copy or move, or is a struct type that has a field of such type.
2282+
template <bool IsMove>
2283+
struct IsNonTrivialCopyMoveVisitor
2284+
: CopiedTypeVisitor<IsNonTrivialCopyMoveVisitor<IsMove>, IsMove, bool> {
2285+
using Super =
2286+
CopiedTypeVisitor<IsNonTrivialCopyMoveVisitor<IsMove>, IsMove, bool>;
2287+
IsNonTrivialCopyMoveVisitor(const ASTContext &C) : Ctx(C) {}
2288+
void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT) {}
2289+
2290+
bool visitWithKind(QualType::PrimitiveCopyKind PCK, QualType QT) {
2291+
if (const auto *AT = this->Ctx.getAsArrayType(QT))
2292+
return this->asDerived().visit(Ctx.getBaseElementType(AT));
2293+
return Super::visitWithKind(PCK, QT);
2294+
}
2295+
2296+
bool visitARCStrong(QualType QT) { return true; }
2297+
bool visitARCWeak(QualType QT) { return true; }
2298+
bool visitTrivial(QualType QT) { return false; }
2299+
// Volatile fields are considered trivial.
2300+
bool visitVolatileTrivial(QualType QT) { return false; }
2301+
2302+
bool visitStruct(QualType QT) {
2303+
const RecordDecl *RD = QT->castAs<RecordType>()->getDecl();
2304+
// We don't want to apply the C restriction in C++ because C++
2305+
// (1) can apply the restriction at a finer grain by banning copying or
2306+
// destroying the union, and
2307+
// (2) allows users to override these restrictions by declaring explicit
2308+
// constructors/etc, which we're not proposing to add to C.
2309+
if (isa<CXXRecordDecl>(RD))
2310+
return false;
2311+
for (const FieldDecl *FD : RD->fields())
2312+
if (this->asDerived().visit(FD->getType()))
2313+
return true;
2314+
return false;
2315+
}
22822316

2283-
bool QualType::hasNonTrivialToPrimitiveDestructCUnion(const RecordDecl *RD) {
2284-
return RD->hasNonTrivialToPrimitiveDestructCUnion();
2285-
}
2317+
const ASTContext &Ctx;
2318+
};
22862319

2287-
bool QualType::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) {
2288-
return RD->hasNonTrivialToPrimitiveCopyCUnion();
2320+
} // namespace
2321+
2322+
bool QualType::isNonTrivialPrimitiveCType(const ASTContext &Ctx) const {
2323+
if (isNonTrivialToPrimitiveDefaultInitialize())
2324+
return true;
2325+
DestructionKind DK = isDestructedType();
2326+
if (DK != DK_none && DK != DK_cxx_destructor)
2327+
return true;
2328+
if (IsNonTrivialCopyMoveVisitor<false>(Ctx).visit(*this))
2329+
return true;
2330+
if (IsNonTrivialCopyMoveVisitor<true>(Ctx).visit(*this))
2331+
return true;
2332+
return false;
22892333
}
22902334

22912335
QualType::PrimitiveDefaultInitializeKind

clang/lib/Sema/Sema.cpp

+3-15
Original file line numberDiff line numberDiff line change
@@ -1658,24 +1658,12 @@ static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) {
16581658
// Set the EscapingByref flag of __block variables captured by
16591659
// escaping blocks.
16601660
for (const BlockDecl *BD : FSI.Blocks) {
1661+
if (BD->doesNotEscape())
1662+
continue;
16611663
for (const BlockDecl::Capture &BC : BD->captures()) {
16621664
VarDecl *VD = BC.getVariable();
1663-
if (VD->hasAttr<BlocksAttr>()) {
1664-
// Nothing to do if this is a __block variable captured by a
1665-
// non-escaping block.
1666-
if (BD->doesNotEscape())
1667-
continue;
1665+
if (VD->hasAttr<BlocksAttr>())
16681666
VD->setEscapingByref();
1669-
}
1670-
// Check whether the captured variable is or contains an object of
1671-
// non-trivial C union type.
1672-
QualType CapType = BC.getVariable()->getType();
1673-
if (CapType.hasNonTrivialToPrimitiveDestructCUnion() ||
1674-
CapType.hasNonTrivialToPrimitiveCopyCUnion())
1675-
S.checkNonTrivialCUnion(BC.getVariable()->getType(),
1676-
BD->getCaretLocation(),
1677-
Sema::NTCUC_BlockCapture,
1678-
Sema::NTCUK_Destruct|Sema::NTCUK_Copy);
16791667
}
16801668
}
16811669

0 commit comments

Comments
 (0)