forked from OSchip/llvm-project
This patch fixes the implementations of the __has_trivial_destructor
and __has_trivial_constructor builtin pseudo-functions and additionally implements __has_trivial_copy and __has_trivial_assign, from John McCall! llvm-svn: 76916
This commit is contained in:
parent
91ade14197
commit
79f83eda84
|
@ -708,6 +708,10 @@ public:
|
|||
/// getBaseElementType - Returns the innermost element type of a variable
|
||||
/// length array type. For example, will return "int" for int[m][n]
|
||||
QualType getBaseElementType(const VariableArrayType *VAT);
|
||||
|
||||
/// getBaseElementType - Returns the innermost element type of a type
|
||||
/// (which needn't actually be an array type).
|
||||
QualType getBaseElementType(QualType QT);
|
||||
|
||||
/// getArrayDecayedType - Return the properly qualified result of decaying the
|
||||
/// specified array type to a pointer. This operation is non-trivial when
|
||||
|
|
|
@ -913,7 +913,7 @@ public:
|
|||
|
||||
QualType getQueriedType() const { return QueriedType; }
|
||||
|
||||
bool EvaluateTrait() const;
|
||||
bool EvaluateTrait(ASTContext&) const;
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == UnaryTypeTraitExprClass;
|
||||
|
|
|
@ -564,6 +564,39 @@ public:
|
|||
};
|
||||
|
||||
|
||||
/// QualifierSet - This class is used to collect qualifiers.
|
||||
class QualifierSet {
|
||||
public:
|
||||
QualifierSet() :
|
||||
CVRMask(0), AddressSpace(0), GCAttrType(QualType::GCNone) {
|
||||
}
|
||||
|
||||
/// Collect any qualifiers on the given type and return an
|
||||
/// unqualified type.
|
||||
const Type *strip(QualType QT) {
|
||||
CVRMask |= QT.getCVRQualifiers();
|
||||
return strip(QT.getTypePtr());
|
||||
}
|
||||
|
||||
/// Collect any qualifiers on the given type and return an
|
||||
/// unqualified type.
|
||||
const Type *strip(const Type* T);
|
||||
|
||||
/// Apply the collected qualifiers to the given type.
|
||||
QualType apply(QualType QT, ASTContext& C);
|
||||
|
||||
/// Apply the collected qualifiers to the given type.
|
||||
QualType apply(const Type* T, ASTContext& C) {
|
||||
return apply(QualType(T, 0), C);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned CVRMask;
|
||||
unsigned AddressSpace;
|
||||
QualType::GCAttrTypes GCAttrType;
|
||||
};
|
||||
|
||||
|
||||
/// BuiltinType - This class is used for builtin types like 'int'. Builtin
|
||||
/// types are always canonical and have a literal name field.
|
||||
class BuiltinType : public Type {
|
||||
|
|
|
@ -2107,6 +2107,18 @@ QualType ASTContext::getArrayDecayedType(QualType Ty) {
|
|||
return PtrTy.getQualifiedType(PrettyArrayType->getIndexTypeQualifier());
|
||||
}
|
||||
|
||||
QualType ASTContext::getBaseElementType(QualType QT) {
|
||||
QualifierSet qualifiers;
|
||||
while (true) {
|
||||
const Type *UT = qualifiers.strip(QT);
|
||||
if (const ArrayType *AT = getAsArrayType(QualType(UT,0))) {
|
||||
QT = AT->getElementType();
|
||||
}else {
|
||||
return qualifiers.apply(QT, *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QualType ASTContext::getBaseElementType(const VariableArrayType *VAT) {
|
||||
QualType ElemTy = VAT->getElementType();
|
||||
|
||||
|
|
|
@ -537,14 +537,11 @@ CXXDestructorDecl::computeBaseOrMembersToDestroy(ASTContext &C) {
|
|||
// non-static data members.
|
||||
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
|
||||
E = ClassDecl->field_end(); Field != E; ++Field) {
|
||||
QualType FieldType = C.getCanonicalType((*Field)->getType());
|
||||
while (const ArrayType *AT = C.getAsArrayType(FieldType))
|
||||
FieldType = AT->getElementType();
|
||||
QualType FieldType = C.getBaseElementType((*Field)->getType());
|
||||
|
||||
if (FieldType->getAsRecordType()) {
|
||||
if (const RecordType* RT = FieldType->getAsRecordType()) {
|
||||
// Skip over virtual bases which have trivial destructors.
|
||||
CXXRecordDecl *BaseClassDecl
|
||||
= cast<CXXRecordDecl>(FieldType->getAsRecordType()->getDecl());
|
||||
CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
|
||||
if (BaseClassDecl->hasTrivialDestructor())
|
||||
continue;
|
||||
uintptr_t Member = reinterpret_cast<uintptr_t>(*Field);
|
||||
|
@ -640,16 +637,12 @@ CXXConstructorDecl::setBaseOrMemberInitializers(
|
|||
AllToInit.push_back(AllBaseFields[Key]);
|
||||
continue;
|
||||
}
|
||||
QualType FieldType = C.getCanonicalType((*Field)->getType());
|
||||
while (const ArrayType *AT = C.getAsArrayType(FieldType))
|
||||
FieldType = AT->getElementType();
|
||||
|
||||
if (FieldType->getAsRecordType()) {
|
||||
CXXConstructorDecl *Ctor = 0;
|
||||
if (CXXRecordDecl *FieldClassDecl =
|
||||
dyn_cast<CXXRecordDecl>(FieldType->getAsRecordType()->getDecl()))
|
||||
Ctor = FieldClassDecl->getDefaultConstructor(C);
|
||||
if (!Ctor && !FieldType->isDependentType())
|
||||
|
||||
QualType FT = C.getBaseElementType((*Field)->getType());
|
||||
if (const RecordType* RT = FT->getAsRecordType()) {
|
||||
CXXConstructorDecl *Ctor =
|
||||
cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(C);
|
||||
if (!Ctor && !FT->isDependentType())
|
||||
Fields.push_back(*Field);
|
||||
CXXBaseOrMemberInitializer *Member =
|
||||
new (C) CXXBaseOrMemberInitializer((*Field), 0, 0,
|
||||
|
|
|
@ -213,7 +213,7 @@ Stmt::child_iterator TemplateIdRefExpr::child_end() {
|
|||
return Stmt::child_iterator();
|
||||
}
|
||||
|
||||
bool UnaryTypeTraitExpr::EvaluateTrait() const {
|
||||
bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
|
||||
switch(UTT) {
|
||||
default: assert(false && "Unknown type trait or not implemented");
|
||||
case UTT_IsPOD: return QueriedType->isPODType();
|
||||
|
@ -236,11 +236,58 @@ bool UnaryTypeTraitExpr::EvaluateTrait() const {
|
|||
return cast<CXXRecordDecl>(RT->getDecl())->isAbstract();
|
||||
return false;
|
||||
case UTT_HasTrivialConstructor:
|
||||
if (const RecordType *RT = QueriedType->getAsRecordType())
|
||||
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
|
||||
// If __is_pod (type) is true then the trait is true, else if type is
|
||||
// a cv class or union type (or array thereof) with a trivial default
|
||||
// constructor ([class.ctor]) then the trait is true, else it is false.
|
||||
if (QueriedType->isPODType())
|
||||
return true;
|
||||
if (const RecordType *RT =
|
||||
C.getBaseElementType(QueriedType)->getAsRecordType())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialConstructor();
|
||||
return false;
|
||||
case UTT_HasTrivialDestructor:
|
||||
case UTT_HasTrivialCopy:
|
||||
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
|
||||
// If __is_pod (type) is true or type is a reference type then
|
||||
// the trait is true, else if type is a cv class or union type
|
||||
// with a trivial copy constructor ([class.copy]) then the trait
|
||||
// is true, else it is false.
|
||||
if (QueriedType->isPODType() || QueriedType->isReferenceType())
|
||||
return true;
|
||||
if (const RecordType *RT = QueriedType->getAsRecordType())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor();
|
||||
return false;
|
||||
case UTT_HasTrivialAssign:
|
||||
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
|
||||
// If type is const qualified or is a reference type then the
|
||||
// trait is false. Otherwise if __is_pod (type) is true then the
|
||||
// trait is true, else if type is a cv class or union type with
|
||||
// a trivial copy assignment ([class.copy]) then the trait is
|
||||
// true, else it is false.
|
||||
// Note: the const and reference restrictions are interesting,
|
||||
// given that const and reference members don't prevent a class
|
||||
// from having a trivial copy assignment operator (but do cause
|
||||
// errors if the copy assignment operator is actually used, q.v.
|
||||
// [class.copy]p12).
|
||||
|
||||
if (C.getBaseElementType(QueriedType).isConstQualified())
|
||||
return false;
|
||||
if (QueriedType->isPODType())
|
||||
return true;
|
||||
if (const RecordType *RT = QueriedType->getAsRecordType())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment();
|
||||
return false;
|
||||
case UTT_HasTrivialDestructor:
|
||||
// http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
|
||||
// If __is_pod (type) is true or type is a reference type
|
||||
// then the trait is true, else if type is a cv class or union
|
||||
// type (or array thereof) with a trivial destructor
|
||||
// ([class.dtor]) then the trait is true, else it is
|
||||
// false.
|
||||
if (QueriedType->isPODType() || QueriedType->isReferenceType())
|
||||
return true;
|
||||
if (const RecordType *RT =
|
||||
C.getBaseElementType(QueriedType)->getAsRecordType())
|
||||
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -735,7 +735,7 @@ public:
|
|||
}
|
||||
|
||||
bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
|
||||
return Success(E->EvaluateTrait(), E);
|
||||
return Success(E->EvaluateTrait(Info.Ctx), E);
|
||||
}
|
||||
|
||||
bool VisitChooseExpr(const ChooseExpr *E) {
|
||||
|
|
|
@ -1072,6 +1072,30 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
|
|||
Args[Idx].Profile(ID);
|
||||
}
|
||||
|
||||
const Type *QualifierSet::strip(const Type* T) {
|
||||
QualType DT = T->getDesugaredType();
|
||||
CVRMask |= DT.getCVRQualifiers();
|
||||
|
||||
if (const ExtQualType* EQT = dyn_cast<ExtQualType>(DT)) {
|
||||
if (EQT->getAddressSpace())
|
||||
AddressSpace = EQT->getAddressSpace();
|
||||
if (EQT->getObjCGCAttr())
|
||||
GCAttrType = EQT->getObjCGCAttr();
|
||||
return EQT->getBaseType();
|
||||
}else {
|
||||
// Use the sugared type unless desugaring found extra qualifiers.
|
||||
return (DT.getCVRQualifiers() ? DT.getTypePtr() : T);
|
||||
}
|
||||
}
|
||||
|
||||
QualType QualifierSet::apply(QualType QT, ASTContext& C) {
|
||||
QT = QT.getWithAdditionalQualifiers(CVRMask);
|
||||
if (GCAttrType) QT = C.getObjCGCQualType(QT, GCAttrType);
|
||||
if (AddressSpace) QT = C.getAddrSpaceQualType(QT, AddressSpace);
|
||||
return QT;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type Printing
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -815,6 +815,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
case tok::kw___is_polymorphic:
|
||||
case tok::kw___is_abstract:
|
||||
case tok::kw___has_trivial_constructor:
|
||||
case tok::kw___has_trivial_copy:
|
||||
case tok::kw___has_trivial_assign:
|
||||
case tok::kw___has_trivial_destructor:
|
||||
return ParseUnaryTypeTrait();
|
||||
|
||||
|
|
|
@ -4244,9 +4244,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
|
|||
}
|
||||
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
QualType EltTy = T;
|
||||
while (const ArrayType *AT = Context.getAsArrayType(EltTy))
|
||||
EltTy = AT->getElementType();
|
||||
QualType EltTy = Context.getBaseElementType(T);
|
||||
|
||||
if (const RecordType *RT = EltTy->getAsRecordType()) {
|
||||
CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl());
|
||||
|
@ -4430,10 +4428,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) {
|
|||
typedef RecordDecl::field_iterator field_iter;
|
||||
for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe;
|
||||
++fi) {
|
||||
QualType EltTy = (*fi)->getType();
|
||||
while (const ArrayType *AT = Context.getAsArrayType(EltTy))
|
||||
EltTy = AT->getElementType();
|
||||
|
||||
QualType EltTy = Context.getBaseElementType((*fi)->getType());
|
||||
if (const RecordType *EltRT = EltTy->getAsRecordType()) {
|
||||
CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl());
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ struct HasRef { int i; int& ref; HasRef() : i(0), ref(i) {} };
|
|||
struct HasNonPOD { NonPOD np; };
|
||||
struct HasVirt { virtual void Virt() {}; };
|
||||
typedef Derives NonPODAr[10];
|
||||
typedef HasVirt VirtAr[10];
|
||||
|
||||
void is_pod()
|
||||
{
|
||||
|
@ -109,3 +110,95 @@ void is_polymorphic()
|
|||
int t17[F(__is_polymorphic(ClassType))];
|
||||
int t18[F(__is_polymorphic(Enum))];
|
||||
}
|
||||
|
||||
typedef Int& IntRef;
|
||||
typedef const IntAr ConstIntAr;
|
||||
typedef ConstIntAr ConstIntArAr[4];
|
||||
|
||||
struct HasCopy {
|
||||
HasCopy(HasCopy& cp);
|
||||
};
|
||||
|
||||
void has_trivial_default_constructor() {
|
||||
int t01[T(__has_trivial_constructor(Int))];
|
||||
int t02[T(__has_trivial_constructor(IntAr))];
|
||||
int t03[T(__has_trivial_constructor(Union))];
|
||||
int t04[T(__has_trivial_constructor(UnionAr))];
|
||||
int t05[T(__has_trivial_constructor(POD))];
|
||||
int t06[T(__has_trivial_constructor(Derives))];
|
||||
int t07[T(__has_trivial_constructor(ConstIntAr))];
|
||||
int t08[T(__has_trivial_constructor(ConstIntArAr))];
|
||||
int t09[T(__has_trivial_constructor(HasDest))];
|
||||
int t10[T(__has_trivial_constructor(HasPriv))];
|
||||
int t11[F(__has_trivial_constructor(HasCons))];
|
||||
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 t16[T(__has_trivial_constructor(const Int))];
|
||||
int t17[T(__has_trivial_constructor(NonPODAr))];
|
||||
int t18[F(__has_trivial_constructor(VirtAr))];
|
||||
}
|
||||
|
||||
void has_trivial_copy_constructor() {
|
||||
int t01[T(__has_trivial_copy(Int))];
|
||||
int t02[T(__has_trivial_copy(IntAr))];
|
||||
int t03[T(__has_trivial_copy(Union))];
|
||||
int t04[T(__has_trivial_copy(UnionAr))];
|
||||
int t05[T(__has_trivial_copy(POD))];
|
||||
int t06[T(__has_trivial_copy(Derives))];
|
||||
int t07[T(__has_trivial_copy(ConstIntAr))];
|
||||
int t08[T(__has_trivial_copy(ConstIntArAr))];
|
||||
int t09[T(__has_trivial_copy(HasDest))];
|
||||
int t10[T(__has_trivial_copy(HasPriv))];
|
||||
int t11[T(__has_trivial_copy(HasCons))];
|
||||
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 t16[T(__has_trivial_copy(const Int))];
|
||||
int t17[F(__has_trivial_copy(NonPODAr))];
|
||||
int t18[F(__has_trivial_copy(VirtAr))];
|
||||
}
|
||||
|
||||
void has_trivial_copy_assignment() {
|
||||
int t01[T(__has_trivial_assign(Int))];
|
||||
int t02[T(__has_trivial_assign(IntAr))];
|
||||
int t03[T(__has_trivial_assign(Union))];
|
||||
int t04[T(__has_trivial_assign(UnionAr))];
|
||||
int t05[T(__has_trivial_assign(POD))];
|
||||
int t06[T(__has_trivial_assign(Derives))];
|
||||
int t07[F(__has_trivial_assign(ConstIntAr))];
|
||||
int t08[F(__has_trivial_assign(ConstIntArAr))];
|
||||
int t09[T(__has_trivial_assign(HasDest))];
|
||||
int t10[T(__has_trivial_assign(HasPriv))];
|
||||
int t11[T(__has_trivial_assign(HasCons))];
|
||||
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 t16[F(__has_trivial_assign(const Int))];
|
||||
int t17[F(__has_trivial_assign(NonPODAr))];
|
||||
int t18[F(__has_trivial_assign(VirtAr))];
|
||||
}
|
||||
|
||||
void has_trivial_destructor() {
|
||||
int t01[T(__has_trivial_destructor(Int))];
|
||||
int t02[T(__has_trivial_destructor(IntAr))];
|
||||
int t03[T(__has_trivial_destructor(Union))];
|
||||
int t04[T(__has_trivial_destructor(UnionAr))];
|
||||
int t05[T(__has_trivial_destructor(POD))];
|
||||
int t06[T(__has_trivial_destructor(Derives))];
|
||||
int t07[T(__has_trivial_destructor(ConstIntAr))];
|
||||
int t08[T(__has_trivial_destructor(ConstIntArAr))];
|
||||
int t09[F(__has_trivial_destructor(HasDest))];
|
||||
int t10[T(__has_trivial_destructor(HasPriv))];
|
||||
int t11[T(__has_trivial_destructor(HasCons))];
|
||||
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 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