diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-07-23 23:49:00 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-07-23 23:49:00 +0000 |
commit | 5e03f9ea8174ae588c5e69ec6b5ef4c68f8fd766 (patch) | |
tree | c28c5e0be4aa5ba6ea746eda3c255afee997abdd /lib/AST | |
parent | 70ee975fad4653fa09f8e77f9a46a7b1f592ef59 (diff) |
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!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76916 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 12 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 25 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 53 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 2 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 24 |
5 files changed, 96 insertions, 20 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 727dc4ee3d..5572b7a3a0 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -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(); diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 7b5a29028c..4d861be9fd 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -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, diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 399c30255a..fbefcd1ee8 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -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; } diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index c3d0402152..0291f6af15 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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) { diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1df8b63e2e..c3bb29b8d5 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -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 //===----------------------------------------------------------------------===// |