Index: test/SemaCXX/type-traits.cpp =================================================================== --- test/SemaCXX/type-traits.cpp (revision 76898) +++ test/SemaCXX/type-traits.cpp (working copy) @@ -22,6 +22,7 @@ struct HasRef { int i; int& ref; HasRef( 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))]; +} Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h (revision 76898) +++ include/clang/AST/ASTContext.h (working copy) @@ -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 Index: include/clang/AST/ExprCXX.h =================================================================== --- include/clang/AST/ExprCXX.h (revision 76898) +++ include/clang/AST/ExprCXX.h (working copy) @@ -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; Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h (revision 76898) +++ include/clang/AST/Type.h (working copy) @@ -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 { Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp (revision 76898) +++ lib/Sema/SemaDecl.cpp (working copy) @@ -4233,9 +4233,7 @@ FieldDecl *Sema::CheckFieldDecl(Declarat } 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(RT->getDecl()); @@ -4419,10 +4417,7 @@ void Sema::DiagnoseNontrivial(const Reco 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(EltRT->getDecl()); Index: lib/AST/ExprCXX.cpp =================================================================== --- lib/AST/ExprCXX.cpp (revision 76898) +++ lib/AST/ExprCXX.cpp (working copy) @@ -213,7 +213,7 @@ Stmt::child_iterator TemplateIdRefExpr:: 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() return cast(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(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(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(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(RT->getDecl())->hasTrivialDestructor(); return false; } Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp (revision 76898) +++ lib/AST/Type.cpp (working copy) @@ -1072,6 +1072,30 @@ TemplateSpecializationType::Profile(llvm Args[Idx].Profile(ID); } +const Type *QualifierSet::strip(const Type* T) { + QualType DT = T->getDesugaredType(); + CVRMask |= DT.getCVRQualifiers(); + + if (const ExtQualType* EQT = dyn_cast(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 //===----------------------------------------------------------------------===// Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp (revision 76898) +++ lib/AST/ExprConstant.cpp (working copy) @@ -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) { Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp (revision 76898) +++ lib/AST/DeclCXX.cpp (working copy) @@ -537,14 +537,11 @@ CXXDestructorDecl::computeBaseOrMembersT // 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(FieldType->getAsRecordType()->getDecl()); + CXXRecordDecl *BaseClassDecl = cast(RT->getDecl()); if (BaseClassDecl->hasTrivialDestructor()) continue; uintptr_t Member = reinterpret_cast(*Field); @@ -634,15 +631,11 @@ CXXConstructorDecl::setBaseOrMemberIniti 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(FieldType->getAsRecordType()->getDecl())) - Ctor = FieldClassDecl->getDefaultConstructor(C); + + QualType FT = C.getBaseElementType((*Field)->getType()); + if (const RecordType* RT = FT->getAsRecordType()) { + CXXConstructorDecl *Ctor = + cast(RT->getDecl())->getDefaultConstructor(C); // FIXME. Issue error if default ctor is missing. CXXBaseOrMemberInitializer *Member = new (C) CXXBaseOrMemberInitializer((*Field), 0, 0, Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp (revision 76898) +++ lib/AST/ASTContext.cpp (working copy) @@ -2107,6 +2107,18 @@ QualType ASTContext::getArrayDecayedType 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(); Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp (revision 76898) +++ lib/Parse/ParseExpr.cpp (working copy) @@ -815,6 +815,8 @@ Parser::OwningExprResult Parser::ParseCa 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();