aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-07-23 23:49:00 +0000
committerDouglas Gregor <dgregor@apple.com>2009-07-23 23:49:00 +0000
commit5e03f9ea8174ae588c5e69ec6b5ef4c68f8fd766 (patch)
treec28c5e0be4aa5ba6ea746eda3c255afee997abdd /lib/AST
parent70ee975fad4653fa09f8e77f9a46a7b1f592ef59 (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.cpp12
-rw-r--r--lib/AST/DeclCXX.cpp25
-rw-r--r--lib/AST/ExprCXX.cpp53
-rw-r--r--lib/AST/ExprConstant.cpp2
-rw-r--r--lib/AST/Type.cpp24
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
//===----------------------------------------------------------------------===//