forked from OSchip/llvm-project
Implement __is_empty. Patch by Sean Hunt.
llvm-svn: 79143
This commit is contained in:
parent
b20757bdeb
commit
c96d4963eb
|
@ -290,6 +290,12 @@ class CXXRecordDecl : public RecordDecl {
|
|||
/// PlainOldData - True when this class is a POD-type.
|
||||
bool PlainOldData : 1;
|
||||
|
||||
/// Empty - true when this class is empty for traits purposes, i.e. has no
|
||||
/// data members other than 0-width bit-fields, has no virtual function/base,
|
||||
/// and doesn't inherit from a non-empty class. Doesn't take union-ness into
|
||||
/// account.
|
||||
bool Empty : 1;
|
||||
|
||||
/// Polymorphic - True when this class is polymorphic, i.e. has at least one
|
||||
/// virtual member or derives from a polymorphic class.
|
||||
bool Polymorphic : 1;
|
||||
|
@ -297,7 +303,7 @@ class CXXRecordDecl : public RecordDecl {
|
|||
/// Abstract - True when this class is abstract, i.e. has at least one
|
||||
/// pure virtual function, (that can come from a base class).
|
||||
bool Abstract : 1;
|
||||
|
||||
|
||||
/// HasTrivialConstructor - True when this class has a trivial constructor.
|
||||
///
|
||||
/// C++ [class.ctor]p5. A constructor is trivial if it is an
|
||||
|
@ -570,6 +576,15 @@ public:
|
|||
/// setPOD - Set whether this class is a POD-type (C++ [class]p4).
|
||||
void setPOD(bool POD) { PlainOldData = POD; }
|
||||
|
||||
/// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which
|
||||
/// means it has a virtual function, virtual base, data member (other than
|
||||
/// 0-width bit-field) or inherits from a non-empty class. Does NOT include
|
||||
/// a check for union-ness.
|
||||
bool isEmpty() const { return Empty; }
|
||||
|
||||
/// Set whether this class is empty (C++0x [meta.unary.prop])
|
||||
void setEmpty(bool Emp) { Empty = Emp; }
|
||||
|
||||
/// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
|
||||
/// which means that the class contains or inherits a virtual function.
|
||||
bool isPolymorphic() const { return Polymorphic; }
|
||||
|
|
|
@ -223,6 +223,12 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
|||
if (const RecordType *RT = QueriedType->getAs<RecordType>())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->isAbstract();
|
||||
return false;
|
||||
case UTT_IsEmpty:
|
||||
if (const RecordType *Record = QueriedType->getAs<RecordType>()) {
|
||||
return !Record->getDecl()->isUnion()
|
||||
&& cast<CXXRecordDecl>(Record->getDecl())->isEmpty();
|
||||
}
|
||||
return false;
|
||||
case UTT_HasTrivialConstructor:
|
||||
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
|
||||
// If __is_pod (type) is true then the trait is true, else if type is
|
||||
|
|
|
@ -815,6 +815,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
case tok::kw___is_class:
|
||||
case tok::kw___is_enum:
|
||||
case tok::kw___is_union:
|
||||
case tok::kw___is_empty:
|
||||
case tok::kw___is_polymorphic:
|
||||
case tok::kw___is_abstract:
|
||||
case tok::kw___has_trivial_constructor:
|
||||
|
|
|
@ -3324,8 +3324,10 @@ public:
|
|||
/// VerifyBitField - verifies that a bit field expression is an ICE and has
|
||||
/// the correct width, and that the field type is valid.
|
||||
/// Returns false on success.
|
||||
/// Can optionally return whether the bit-field is of width 0
|
||||
bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
|
||||
QualType FieldTy, const Expr *BitWidth);
|
||||
QualType FieldTy, const Expr *BitWidth,
|
||||
bool *ZeroWidth = 0);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Extra semantic analysis beyond the C type system
|
||||
|
|
|
@ -2536,6 +2536,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
CXXRecordDecl *CurClass = cast<CXXRecordDecl>(DC);
|
||||
CurClass->setAggregate(false);
|
||||
CurClass->setPOD(false);
|
||||
CurClass->setEmpty(false);
|
||||
CurClass->setPolymorphic(true);
|
||||
CurClass->setHasTrivialConstructor(false);
|
||||
CurClass->setHasTrivialCopyConstructor(false);
|
||||
|
@ -4331,8 +4332,12 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD,
|
|||
|
||||
// Note that FieldName may be null for anonymous bitfields.
|
||||
bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
|
||||
QualType FieldTy, const Expr *BitWidth) {
|
||||
|
||||
QualType FieldTy, const Expr *BitWidth,
|
||||
bool *ZeroWidth) {
|
||||
// Default to true; that shouldn't confuse checks for emptiness
|
||||
if (ZeroWidth)
|
||||
*ZeroWidth = true;
|
||||
|
||||
// C99 6.7.2.1p4 - verify the field type.
|
||||
// C++ 9.6p3: A bit-field shall have integral or enumeration type.
|
||||
if (!FieldTy->isDependentType() && !FieldTy->isIntegralType()) {
|
||||
|
@ -4355,6 +4360,9 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
|
|||
if (VerifyIntegerConstantExpression(BitWidth, &Value))
|
||||
return true;
|
||||
|
||||
if (Value != 0 && ZeroWidth)
|
||||
*ZeroWidth = false;
|
||||
|
||||
// Zero-width bitfield is ok for anonymous field.
|
||||
if (Value == 0 && FieldName)
|
||||
return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName;
|
||||
|
@ -4490,11 +4498,13 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
|
|||
AbstractFieldType))
|
||||
InvalidDecl = true;
|
||||
|
||||
bool ZeroWidth = false;
|
||||
// If this is declared as a bit-field, check the bit-field.
|
||||
if (BitWidth && VerifyBitField(Loc, II, T, BitWidth)) {
|
||||
if (BitWidth && VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) {
|
||||
InvalidDecl = true;
|
||||
DeleteExpr(BitWidth);
|
||||
BitWidth = 0;
|
||||
ZeroWidth = false;
|
||||
}
|
||||
|
||||
FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, BitWidth,
|
||||
|
@ -4511,17 +4521,24 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
|
|||
if (getLangOptions().CPlusPlus) {
|
||||
QualType EltTy = Context.getBaseElementType(T);
|
||||
|
||||
CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record);
|
||||
|
||||
if (!T->isPODType())
|
||||
CXXRecord->setPOD(false);
|
||||
if (!ZeroWidth)
|
||||
CXXRecord->setEmpty(false);
|
||||
|
||||
if (const RecordType *RT = EltTy->getAs<RecordType>()) {
|
||||
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
|
||||
|
||||
if (!RDecl->hasTrivialConstructor())
|
||||
cast<CXXRecordDecl>(Record)->setHasTrivialConstructor(false);
|
||||
CXXRecord->setHasTrivialConstructor(false);
|
||||
if (!RDecl->hasTrivialCopyConstructor())
|
||||
cast<CXXRecordDecl>(Record)->setHasTrivialCopyConstructor(false);
|
||||
CXXRecord->setHasTrivialCopyConstructor(false);
|
||||
if (!RDecl->hasTrivialCopyAssignment())
|
||||
cast<CXXRecordDecl>(Record)->setHasTrivialCopyAssignment(false);
|
||||
CXXRecord->setHasTrivialCopyAssignment(false);
|
||||
if (!RDecl->hasTrivialDestructor())
|
||||
cast<CXXRecordDecl>(Record)->setHasTrivialDestructor(false);
|
||||
CXXRecord->setHasTrivialDestructor(false);
|
||||
|
||||
// C++ 9.5p1: An object of a class with a non-trivial
|
||||
// constructor, a non-trivial copy constructor, a non-trivial
|
||||
|
@ -4557,9 +4574,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
|
|||
}
|
||||
}
|
||||
|
||||
if (getLangOptions().CPlusPlus && !T->isPODType())
|
||||
cast<CXXRecordDecl>(Record)->setPOD(false);
|
||||
|
||||
// FIXME: We need to pass in the attributes given an AST
|
||||
// representation, not a parser representation.
|
||||
if (D)
|
||||
|
|
|
@ -383,12 +383,16 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
|
|||
SpecifierRange))
|
||||
return 0;
|
||||
|
||||
// If the base class is polymorphic, the new one is, too.
|
||||
// If the base class is polymorphic or isn't empty, the new one is/isn't, too.
|
||||
RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
|
||||
assert(BaseDecl && "Record type has no declaration");
|
||||
BaseDecl = BaseDecl->getDefinition(Context);
|
||||
assert(BaseDecl && "Base type is not incomplete, but has no definition");
|
||||
if (cast<CXXRecordDecl>(BaseDecl)->isPolymorphic())
|
||||
CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
|
||||
assert(CXXBaseDecl && "Base type is not a C++ type");
|
||||
if (!CXXBaseDecl->isEmpty())
|
||||
Class->setEmpty(false);
|
||||
if (CXXBaseDecl->isPolymorphic())
|
||||
Class->setPolymorphic(true);
|
||||
|
||||
// C++ [dcl.init.aggr]p1:
|
||||
|
@ -409,6 +413,11 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
|
|||
// A copy assignment operator is trivial if its class has no virtual
|
||||
// base classes.
|
||||
Class->setHasTrivialCopyAssignment(false);
|
||||
|
||||
// C++0x [meta.unary.prop] is_empty:
|
||||
// T is a class type, but not a union type, with ... no virtual base
|
||||
// classes
|
||||
Class->setEmpty(false);
|
||||
} else {
|
||||
// C++ [class.ctor]p5:
|
||||
// A constructor is trivial if all the direct base classes of its
|
||||
|
|
|
@ -749,6 +749,7 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
|
|||
New->setVirtualAsWritten(true);
|
||||
Record->setAggregate(false);
|
||||
Record->setPOD(false);
|
||||
Record->setEmpty(false);
|
||||
Record->setPolymorphic(true);
|
||||
}
|
||||
if (Tmpl->isPure()) {
|
||||
|
|
|
@ -7,14 +7,23 @@ struct NonPOD { NonPOD(int); };
|
|||
// PODs
|
||||
enum Enum { EV };
|
||||
struct POD { Enum e; int i; float f; NonPOD* p; };
|
||||
struct Empty {};
|
||||
typedef Empty EmptyAr[10];
|
||||
typedef int Int;
|
||||
typedef Int IntAr[10];
|
||||
class Statics { static int priv; static NonPOD np; };
|
||||
union EmptyUnion {};
|
||||
union Union { int i; float f; };
|
||||
struct HasFunc { void f (); };
|
||||
struct HasOp { void operator *(); };
|
||||
struct HasConv { operator int(); };
|
||||
struct HasAssign { void operator =(int); };
|
||||
|
||||
// Not PODs
|
||||
struct Derives : POD {};
|
||||
struct DerivesEmpty : Empty {};
|
||||
struct HasCons { HasCons(int); };
|
||||
struct HasAssign { HasAssign operator =(const HasAssign&); };
|
||||
struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); };
|
||||
struct HasDest { ~HasDest(); };
|
||||
class HasPriv { int priv; };
|
||||
class HasProt { protected: int prot; };
|
||||
|
@ -23,6 +32,7 @@ struct HasNonPOD { NonPOD np; };
|
|||
struct HasVirt { virtual void Virt() {}; };
|
||||
typedef Derives NonPODAr[10];
|
||||
typedef HasVirt VirtAr[10];
|
||||
union NonPODUnion { int i; Derives n; };
|
||||
|
||||
void is_pod()
|
||||
{
|
||||
|
@ -32,10 +42,17 @@ void is_pod()
|
|||
int t04[T(__is_pod(Int))];
|
||||
int t05[T(__is_pod(IntAr))];
|
||||
int t06[T(__is_pod(Statics))];
|
||||
int t07[T(__is_pod(Empty))];
|
||||
int t08[T(__is_pod(EmptyUnion))];
|
||||
int t09[T(__is_pod(Union))];
|
||||
int t10[T(__is_pod(HasFunc))];
|
||||
int t11[T(__is_pod(HasOp))];
|
||||
int t12[T(__is_pod(HasConv))];
|
||||
int t13[T(__is_pod(HasAssign))];
|
||||
|
||||
int t21[F(__is_pod(Derives))];
|
||||
int t22[F(__is_pod(HasCons))];
|
||||
int t23[F(__is_pod(HasAssign))];
|
||||
int t23[F(__is_pod(HasCopyAssign))];
|
||||
int t24[F(__is_pod(HasDest))];
|
||||
int t25[F(__is_pod(HasPriv))];
|
||||
int t26[F(__is_pod(HasProt))];
|
||||
|
@ -43,9 +60,40 @@ void is_pod()
|
|||
int t28[F(__is_pod(HasNonPOD))];
|
||||
int t29[F(__is_pod(HasVirt))];
|
||||
int t30[F(__is_pod(NonPODAr))];
|
||||
int t31[F(__is_pod(DerivesEmpty))];
|
||||
// int t32[F(__is_pod(NonPODUnion))];
|
||||
}
|
||||
|
||||
typedef Empty EmptyAr[10];
|
||||
struct Bit0 { int : 0; };
|
||||
struct Bit0Cons { int : 0; Bit0Cons(); };
|
||||
struct BitOnly { int x : 3; };
|
||||
//struct DerivesVirt : virtual POD {};
|
||||
|
||||
void is_empty()
|
||||
{
|
||||
int t01[T(__is_empty(Empty))];
|
||||
int t02[T(__is_empty(DerivesEmpty))];
|
||||
int t03[T(__is_empty(HasCons))];
|
||||
int t04[T(__is_empty(HasCopyAssign))];
|
||||
int t05[T(__is_empty(HasDest))];
|
||||
int t06[T(__is_empty(HasFunc))];
|
||||
int t07[T(__is_empty(HasOp))];
|
||||
int t08[T(__is_empty(HasConv))];
|
||||
int t09[T(__is_empty(HasAssign))];
|
||||
int t10[T(__is_empty(Bit0))];
|
||||
int t11[T(__is_empty(Bit0Cons))];
|
||||
|
||||
int t21[F(__is_empty(Int))];
|
||||
int t22[F(__is_empty(POD))];
|
||||
int t23[F(__is_empty(EmptyUnion))];
|
||||
int t24[F(__is_empty(EmptyAr))];
|
||||
int t25[F(__is_empty(HasRef))];
|
||||
int t26[F(__is_empty(HasVirt))];
|
||||
int t27[F(__is_empty(BitOnly))];
|
||||
// int t27[F(__is_empty(DerivesVirt))];
|
||||
}
|
||||
|
||||
union Union { int i; float f; };
|
||||
typedef Derives ClassType;
|
||||
|
||||
void is_class()
|
||||
|
@ -93,7 +141,7 @@ void is_enum()
|
|||
int t17[F(__is_enum(ClassType))];
|
||||
}
|
||||
|
||||
struct Polymorph { virtual void f(); };
|
||||
typedef HasVirt Polymorph;
|
||||
struct InheritPolymorph : Polymorph {};
|
||||
|
||||
void is_polymorphic()
|
||||
|
@ -134,7 +182,7 @@ void has_trivial_default_constructor() {
|
|||
int t12[F(__has_trivial_constructor(HasRef))];
|
||||
int t13[F(__has_trivial_constructor(HasCopy))];
|
||||
int t14[F(__has_trivial_constructor(IntRef))];
|
||||
int t15[T(__has_trivial_constructor(HasAssign))];
|
||||
int t15[T(__has_trivial_constructor(HasCopyAssign))];
|
||||
int t16[T(__has_trivial_constructor(const Int))];
|
||||
int t17[T(__has_trivial_constructor(NonPODAr))];
|
||||
int t18[F(__has_trivial_constructor(VirtAr))];
|
||||
|
@ -155,7 +203,7 @@ void has_trivial_copy_constructor() {
|
|||
int t12[T(__has_trivial_copy(HasRef))];
|
||||
int t13[F(__has_trivial_copy(HasCopy))];
|
||||
int t14[T(__has_trivial_copy(IntRef))];
|
||||
int t15[T(__has_trivial_copy(HasAssign))];
|
||||
int t15[T(__has_trivial_copy(HasCopyAssign))];
|
||||
int t16[T(__has_trivial_copy(const Int))];
|
||||
int t17[F(__has_trivial_copy(NonPODAr))];
|
||||
int t18[F(__has_trivial_copy(VirtAr))];
|
||||
|
@ -176,7 +224,7 @@ void has_trivial_copy_assignment() {
|
|||
int t12[T(__has_trivial_assign(HasRef))];
|
||||
int t13[T(__has_trivial_assign(HasCopy))];
|
||||
int t14[F(__has_trivial_assign(IntRef))];
|
||||
int t15[F(__has_trivial_assign(HasAssign))];
|
||||
int t15[F(__has_trivial_assign(HasCopyAssign))];
|
||||
int t16[F(__has_trivial_assign(const Int))];
|
||||
int t17[F(__has_trivial_assign(NonPODAr))];
|
||||
int t18[F(__has_trivial_assign(VirtAr))];
|
||||
|
@ -197,7 +245,7 @@ void has_trivial_destructor() {
|
|||
int t12[T(__has_trivial_destructor(HasRef))];
|
||||
int t13[T(__has_trivial_destructor(HasCopy))];
|
||||
int t14[T(__has_trivial_destructor(IntRef))];
|
||||
int t15[T(__has_trivial_destructor(HasAssign))];
|
||||
int t15[T(__has_trivial_destructor(HasCopyAssign))];
|
||||
int t16[T(__has_trivial_destructor(const Int))];
|
||||
int t17[T(__has_trivial_destructor(NonPODAr))];
|
||||
int t18[T(__has_trivial_destructor(VirtAr))];
|
||||
|
|
Loading…
Reference in New Issue