C.getBaseElementType(QueriedType)->getAs<RecordType>())
return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor();
return false;
+ // TODO: Propagate nothrowness for implicitly declared special members.
+ case UTT_HasNothrowAssign:
+ // 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 __has_trivial_assign (type)
+ // is true then the trait is true, else if type is a cv class
+ // or union type with copy assignment operators that are known
+ // not to throw an exception then the trait is true, else it is
+ // false.
+ if (C.getBaseElementType(QueriedType).isConstQualified())
+ return false;
+ if (QueriedType->isReferenceType())
+ return false;
+ if (QueriedType->isPODType())
+ return true;
+ if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
+ CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialCopyAssignment())
+ return true;
+
+ bool FoundAssign = false;
+ bool AllNoThrow = true;
+ DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
+ DeclContext::lookup_const_iterator Op, OpEnd;
+ for (llvm::tie(Op, OpEnd) = RD->lookup(Name);
+ Op != OpEnd; ++Op) {
+ CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
+ if (Operator->isCopyAssignmentOperator()) {
+ FoundAssign = true;
+ const FunctionProtoType *CPT
+ = Operator->getType()->getAs<FunctionProtoType>();
+ if (!CPT->hasEmptyExceptionSpec()) {
+ AllNoThrow = false;
+ break;
+ }
+ }
+ }
+
+ return FoundAssign && AllNoThrow;
+ }
+ return false;
+ case UTT_HasNothrowCopy:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If __has_trivial_copy (type) is true then the trait is true, else
+ // if type is a cv class or union type with copy constructors that are
+ // known not to throw an exception then the trait is true, else it is
+ // false.
+ if (QueriedType->isPODType() || QueriedType->isReferenceType())
+ return true;
+ if (const RecordType *RT = QueriedType->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialCopyConstructor())
+ return true;
+
+ bool FoundConstructor = false;
+ bool AllNoThrow = true;
+ unsigned FoundTQs;
+ DeclarationName ConstructorName
+ = C.DeclarationNames.getCXXConstructorName(
+ C.getCanonicalType(QueriedType));
+ DeclContext::lookup_const_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = RD->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+ if (Constructor->isCopyConstructor(FoundTQs)) {
+ FoundConstructor = true;
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ if (!CPT->hasEmptyExceptionSpec()) {
+ AllNoThrow = false;
+ break;
+ }
+ }
+ }
+
+ return FoundConstructor && AllNoThrow;
+ }
+ return false;
+ case UTT_HasNothrowConstructor:
+ // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
+ // If __has_trivial_constructor (type) is true then the trait is
+ // true, else if type is a cv class or union type (or array
+ // thereof) with a default constructor that is known not to
+ // throw an exception then the trait is true, else it is false.
+ if (QueriedType->isPODType())
+ return true;
+ if (const RecordType *RT =
+ C.getBaseElementType(QueriedType)->getAs<RecordType>()) {
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->hasTrivialConstructor())
+ return true;
+
+ if (CXXConstructorDecl *Constructor = RD->getDefaultConstructor()) {
+ const FunctionProtoType *CPT
+ = Constructor->getType()->getAs<FunctionProtoType>();
+ // TODO: check whether evaluating default arguments can throw.
+ // For now, we'll be conservative and assume that they can throw.
+ if (CPT->hasEmptyExceptionSpec() && CPT->getNumArgs() == 0)
+ return true;
+ }
+ }
+ return false;
}
}
/// '::'[opt] 'delete' '[' ']' cast-expression
///
/// [GNU] unary-type-trait:
-/// '__has_nothrow_assign' [TODO]
-/// '__has_nothrow_copy' [TODO]
-/// '__has_nothrow_constructor' [TODO]
+/// '__has_nothrow_assign'
+/// '__has_nothrow_copy'
+/// '__has_nothrow_constructor'
/// '__has_trivial_assign' [TODO]
/// '__has_trivial_copy' [TODO]
/// '__has_trivial_constructor'
case tok::kw___has_trivial_copy:
case tok::kw___has_trivial_assign:
case tok::kw___has_trivial_destructor:
+ case tok::kw___has_nothrow_assign:
+ case tok::kw___has_nothrow_copy:
+ case tok::kw___has_nothrow_constructor:
return ParseUnaryTypeTrait();
case tok::at: {
typedef HasVirt VirtAr[10];
union NonPODUnion { int i; Derives n; };
+struct HasNoThrowCopyAssign {
+ void operator =(const HasNoThrowCopyAssign&) throw();
+};
+struct HasMultipleCopyAssign {
+ void operator =(const HasMultipleCopyAssign&) throw();
+ void operator =(volatile HasMultipleCopyAssign&);
+};
+struct HasMultipleNoThrowCopyAssign {
+ void operator =(const HasMultipleNoThrowCopyAssign&) throw();
+ void operator =(volatile HasMultipleNoThrowCopyAssign&) throw();
+};
+
+struct HasNoThrowConstructor { HasNoThrowConstructor() throw(); };
+struct HasNoThrowConstructorWithArgs {
+ HasNoThrowConstructorWithArgs(HasCons i = HasCons(0)) throw();
+};
+
+struct HasNoThrowCopy { HasNoThrowCopy(const HasNoThrowCopy&) throw(); };
+struct HasMultipleCopy {
+ HasMultipleCopy(const HasMultipleCopy&) throw();
+ HasMultipleCopy(volatile HasMultipleCopy&);
+};
+struct HasMultipleNoThrowCopy {
+ HasMultipleNoThrowCopy(const HasMultipleNoThrowCopy&) throw();
+ HasMultipleNoThrowCopy(volatile HasMultipleNoThrowCopy&) throw();
+};
+
void is_pod()
{
int t01[T(__is_pod(int))];
int t01[T(!__has_trivial_destructor(A))];
int t02[T(!__has_trivial_destructor(B<int>))];
}
+
+void has_nothrow_assign() {
+ int t01[T(__has_nothrow_assign(Int))];
+ int t02[T(__has_nothrow_assign(IntAr))];
+ int t03[T(__has_nothrow_assign(Union))];
+ int t04[T(__has_nothrow_assign(UnionAr))];
+ int t05[T(__has_nothrow_assign(POD))];
+ int t06[T(__has_nothrow_assign(Derives))];
+ int t07[F(__has_nothrow_assign(ConstIntAr))];
+ int t08[F(__has_nothrow_assign(ConstIntArAr))];
+ int t09[T(__has_nothrow_assign(HasDest))];
+ int t10[T(__has_nothrow_assign(HasPriv))];
+ int t11[T(__has_nothrow_assign(HasCons))];
+ int t12[T(__has_nothrow_assign(HasRef))];
+ int t13[T(__has_nothrow_assign(HasCopy))];
+ int t14[F(__has_nothrow_assign(IntRef))];
+ int t15[F(__has_nothrow_assign(HasCopyAssign))];
+ int t16[F(__has_nothrow_assign(const Int))];
+ int t17[F(__has_nothrow_assign(NonPODAr))];
+ int t18[F(__has_nothrow_assign(VirtAr))];
+
+ int t19[T(__has_nothrow_assign(HasNoThrowCopyAssign))];
+ int t20[F(__has_nothrow_assign(HasMultipleCopyAssign))];
+ int t21[T(__has_nothrow_assign(HasMultipleNoThrowCopyAssign))];
+}
+
+void has_nothrow_copy() {
+ int t01[T(__has_nothrow_copy(Int))];
+ int t02[T(__has_nothrow_copy(IntAr))];
+ int t03[T(__has_nothrow_copy(Union))];
+ int t04[T(__has_nothrow_copy(UnionAr))];
+ int t05[T(__has_nothrow_copy(POD))];
+ int t06[T(__has_nothrow_copy(Derives))];
+ int t07[T(__has_nothrow_copy(ConstIntAr))];
+ int t08[T(__has_nothrow_copy(ConstIntArAr))];
+ int t09[T(__has_nothrow_copy(HasDest))];
+ int t10[T(__has_nothrow_copy(HasPriv))];
+ int t11[T(__has_nothrow_copy(HasCons))];
+ int t12[T(__has_nothrow_copy(HasRef))];
+ int t13[F(__has_nothrow_copy(HasCopy))];
+ int t14[T(__has_nothrow_copy(IntRef))];
+ int t15[T(__has_nothrow_copy(HasCopyAssign))];
+ int t16[T(__has_nothrow_copy(const Int))];
+ int t17[F(__has_nothrow_copy(NonPODAr))];
+ int t18[F(__has_nothrow_copy(VirtAr))];
+
+ int t19[T(__has_nothrow_copy(HasNoThrowCopy))];
+ int t20[F(__has_nothrow_copy(HasMultipleCopy))];
+ int t21[T(__has_nothrow_copy(HasMultipleNoThrowCopy))];
+}
+
+void has_nothrow_constructor() {
+ int t01[T(__has_nothrow_constructor(Int))];
+ int t02[T(__has_nothrow_constructor(IntAr))];
+ int t03[T(__has_nothrow_constructor(Union))];
+ int t04[T(__has_nothrow_constructor(UnionAr))];
+ int t05[T(__has_nothrow_constructor(POD))];
+ int t06[T(__has_nothrow_constructor(Derives))];
+ int t07[T(__has_nothrow_constructor(ConstIntAr))];
+ int t08[T(__has_nothrow_constructor(ConstIntArAr))];
+ int t09[T(__has_nothrow_constructor(HasDest))];
+ int t10[T(__has_nothrow_constructor(HasPriv))];
+ int t11[F(__has_nothrow_constructor(HasCons))];
+ int t12[F(__has_nothrow_constructor(HasRef))];
+ int t13[F(__has_nothrow_constructor(HasCopy))];
+ int t14[F(__has_nothrow_constructor(IntRef))];
+ int t15[T(__has_nothrow_constructor(HasCopyAssign))];
+ int t16[T(__has_nothrow_constructor(const Int))];
+ int t17[T(__has_nothrow_constructor(NonPODAr))];
+ // int t18[T(__has_nothrow_constructor(VirtAr))]; // not implemented
+
+ int t19[T(__has_nothrow_constructor(HasNoThrowConstructor))];
+ int t20[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))];
+}