Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -449,6 +449,7 @@ TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) // Clang-only C++ Type Traits +TYPE_TRAIT_1(__is_aggregate, IsAggregate, KEYCXX) TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX) TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX) TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX) Index: include/clang/Basic/TypeTraits.h =================================================================== --- include/clang/Basic/TypeTraits.h +++ include/clang/Basic/TypeTraits.h @@ -31,6 +31,7 @@ UTT_HasTrivialDestructor, UTT_HasVirtualDestructor, UTT_IsAbstract, + UTT_IsAggregate, UTT_IsArithmetic, UTT_IsArray, UTT_IsClass, Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -1405,6 +1405,7 @@ !Tok.isAnnotation() && Tok.getIdentifierInfo() && Tok.isOneOf(tok::kw___is_abstract, + tok::kw___is_aggregate, tok::kw___is_arithmetic, tok::kw___is_array, tok::kw___is_assignable, Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -676,6 +676,7 @@ /// '__is_union' /// /// [Clang] unary-type-trait: +/// '__is_aggregate' /// '__trivially_copyable' /// /// binary-type-trait: @@ -804,6 +805,7 @@ = RTT_JOIN(tok::kw_,Name) REVERTIBLE_TYPE_TRAIT(__is_abstract); + REVERTIBLE_TYPE_TRAIT(__is_aggregate); REVERTIBLE_TYPE_TRAIT(__is_arithmetic); REVERTIBLE_TYPE_TRAIT(__is_array); REVERTIBLE_TYPE_TRAIT(__is_assignable); Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -4055,6 +4055,7 @@ // C++0x [meta.unary.prop] Table 49 requires the following traits to be // applied to a complete type. + case UTT_IsAggregate: case UTT_IsTrivial: case UTT_IsTriviallyCopyable: case UTT_IsStandardLayout: @@ -4081,15 +4082,13 @@ case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: - // Arrays of unknown bound are expressly allowed. - QualType ElTy = ArgTy; - if (ArgTy->isIncompleteArrayType()) - ElTy = S.Context.getAsArrayType(ArgTy)->getElementType(); - - // The void type is expressly allowed. + // C++14 [meta.unary.prop] + // remove_all_extents_t shall be a complete type or + // (possibly cv-qualified) void. + // See LWG 2015 + QualType ElTy = S.Context.getBaseElementType(ArgTy); if (ElTy->isVoidType()) return true; - return !S.RequireCompleteType( Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr); } @@ -4229,6 +4228,10 @@ if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return !RD->isUnion() && RD->isAbstract(); return false; + case UTT_IsAggregate: + if (const CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->isAggregate(); + return false; // __is_interface_class only returns true when CL is invoked in /CLR mode and // even then only when it is used with the 'interface struct ...' syntax // Clang doesn't support /CLR which makes this type trait moot. Index: test/PCH/cxx-traits.h =================================================================== --- test/PCH/cxx-traits.h +++ test/PCH/cxx-traits.h @@ -18,6 +18,7 @@ }; struct __is_abstract {}; // expected-warning {{made available}} +struct __is_aggregate {}; // expected-warning {{made available}} struct __is_arithmetic {}; // expected-warning {{made available}} struct __is_array {}; // expected-warning {{made available}} struct __is_assignable {}; // expected-warning {{made available}} Index: test/PCH/cxx-traits.cpp =================================================================== --- test/PCH/cxx-traits.cpp +++ test/PCH/cxx-traits.cpp @@ -16,6 +16,7 @@ // The built-ins should still work too: bool _is_abstract_result = __is_abstract(int); +bool _is_aggregate_result = __is_aggregate(int); bool _is_arithmetic_result = __is_arithmetic(int); bool _is_array_result = __is_array(int); bool _is_assignable_result = __is_assignable(int, int); Index: test/SemaCXX/type-traits.cpp =================================================================== --- test/SemaCXX/type-traits.cpp +++ test/SemaCXX/type-traits.cpp @@ -1,7 +1,22 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fms-extensions -Wno-microsoft %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++14 -fms-extensions -Wno-microsoft %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++1z -fms-extensions -Wno-microsoft %s + #define T(b) (b) ? 1 : -1 #define F(b) (b) ? -1 : 1 +#if __cplusplus <= 201103L +#define T_AFTER_CPP11(...) F(__VA_ARGS__) +#else +#define T_AFTER_CPP11(...) T(__VA_ARGS__) +#endif + +#if __cplusplus <= 201402L +#define T_AFTER_CPP14(...) F(__VA_ARGS__) +#else +#define T_AFTER_CPP14(...) T(__VA_ARGS__) +#endif + struct NonPOD { NonPOD(int); }; // PODs @@ -9,12 +24,14 @@ struct POD { Enum e; int i; float f; NonPOD* p; }; struct Empty {}; typedef Empty EmptyAr[10]; +typedef Empty EmptyArNB[]; +typedef Empty EmptyArMB[1][2]; typedef int Int; typedef Int IntAr[10]; typedef Int IntArNB[]; class Statics { static int priv; static NonPOD np; }; union EmptyUnion {}; -union IncompleteUnion; +union IncompleteUnion; // expected-note {{forward declaration of 'IncompleteUnion'}} union Union { int i; float f; }; struct HasFunc { void f (); }; struct HasOp { void operator *(); }; @@ -38,6 +55,10 @@ typedef Derives DerivesArNB[]; struct DerivesEmpty : Empty {}; struct HasCons { HasCons(int); }; +struct HasDefaultCons { HasDefaultCons() = default; }; +struct HasExplicitDefaultCons { explicit HasExplicitDefaultCons() = default; }; +struct HasInheritedCons : HasDefaultCons { using HasDefaultCons::HasDefaultCons; }; +struct HasNoInheritedCons : HasCons {}; struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); }; struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; struct HasNoThrowMoveAssign { @@ -48,8 +69,15 @@ const HasNoExceptNoThrowMoveAssign&&) noexcept; }; struct HasThrowMoveAssign { - HasThrowMoveAssign& operator=( - const HasThrowMoveAssign&&) throw(POD); }; + HasThrowMoveAssign& operator=(const HasThrowMoveAssign&&) +#if __cplusplus <= 201402L + throw(POD); +#else + noexcept(false); +#endif +}; + + struct HasNoExceptFalseMoveAssign { HasNoExceptFalseMoveAssign& operator=( const HasNoExceptFalseMoveAssign&&) noexcept(false); }; @@ -81,6 +109,7 @@ class HasPriv { int priv; }; class HasProt { protected: int prot; }; struct HasRef { int i; int& ref; HasRef() : i(0), ref(i) {} }; +struct HasRefAggregate { int i; int& ref; }; struct HasNonPOD { NonPOD np; }; struct HasVirt { virtual void Virt() {}; }; typedef NonPOD NonPODAr[10]; @@ -152,7 +181,12 @@ }; struct ThrowingDtor { - ~ThrowingDtor() throw(int); + ~ThrowingDtor() +#if __cplusplus <= 201402L + throw(int); +#else + noexcept(false); +#endif }; struct NoExceptDtor { @@ -163,6 +197,20 @@ ~NoThrowDtor() throw(); }; +struct ACompleteType {}; +struct AnIncompleteType; // expected-note 4 {{forward declaration of 'AnIncompleteType'}} +typedef AnIncompleteType AnIncompleteTypeAr[42]; +typedef AnIncompleteType AnIncompleteTypeArNB[]; +typedef AnIncompleteType AnIncompleteTypeArMB[1][10]; + +struct HasInClassInit { + int x = 42; +}; + +struct HasPrivateBase : private ACompleteType {}; +struct HasProtectedBase : protected ACompleteType {}; +struct HasVirtBase : virtual ACompleteType {}; + void is_pod() { { int arr[T(__is_pod(int))]; } @@ -452,6 +500,68 @@ int t31[F(__is_floating_point(IntArNB))]; } +template +struct AggregateTemplate { + T value; +}; + +template +struct NonAggregateTemplate { + T value; + NonAggregateTemplate(); +}; + +void is_aggregate() +{ + int t01[F(__is_aggregate(NonPOD))]; + int t02[F(__is_aggregate(Enum))]; + int t03[T(__is_aggregate(POD))]; + int t04[T(__is_aggregate(Empty))]; + int t05[T(__is_aggregate(EmptyAr))]; + int t06[T(__is_aggregate(EmptyArNB))]; + int t07[T(__is_aggregate(EmptyArMB))]; + int t08[F(__is_aggregate(AnIncompleteType))]; // expected-error {{incomplete type 'AnIncompleteType' used in type trait expression}} + int t09[F(__is_aggregate(AnIncompleteTypeAr))]; // expected-error {{incomplete type 'AnIncompleteType' used in type trait expression}} + int t10[F(__is_aggregate(AnIncompleteTypeArNB))]; // expected-error {{incomplete type 'AnIncompleteType' used in type trait expression}} + int t11[F(__is_aggregate(AnIncompleteTypeArMB))]; // expected-error {{incomplete type 'AnIncompleteType' used in type trait expression}} + int t12[F(__is_aggregate(void))]; + int t13[F(__is_aggregate(const volatile void))]; + int t14[F(__is_aggregate(int))]; + int t15[T(__is_aggregate(EmptyUnion))]; + int t16[T(__is_aggregate(Union))]; + int t17[F(__is_aggregate(IncompleteUnion))]; // expected-error {{incomplete type 'IncompleteUnion' used in type trait expression}} + int t18[T(__is_aggregate(Statics))]; + int t19[T(__is_aggregate(HasFunc))]; + int t20[T(__is_aggregate(HasOp))]; + int t21[T(__is_aggregate(HasAssign))]; + int t22[T(__is_aggregate(HasAnonymousUnion))]; + + int t23[T_AFTER_CPP14(__is_aggregate(Derives))]; + int t24[T_AFTER_CPP14(__is_aggregate(DerivesAr))]; + int t25[T_AFTER_CPP14(__is_aggregate(DerivesArNB))]; + int t26[F(__is_aggregate(HasCons))]; + int t27[T(__is_aggregate(HasDefaultCons))]; + int t28[F(__is_aggregate(HasExplicitDefaultCons))]; + int t29[F(__is_aggregate(HasInheritedCons))]; + int t30[T_AFTER_CPP14(__is_aggregate(HasNoInheritedCons))]; + int t31[T(__is_aggregate(HasCopyAssign))]; + int t32[F(__is_aggregate(NonTrivialDefault))]; + int t33[T(__is_aggregate(HasDest))]; + int t34[F(__is_aggregate(HasPriv))]; + int t35[F(__is_aggregate(HasProt))]; + int t36[T(__is_aggregate(HasRefAggregate))]; + int t37[T(__is_aggregate(HasNonPOD))]; + int t38[F(__is_aggregate(HasVirt))]; + int t39[F(__is_aggregate(VirtAr))]; + int t40[T_AFTER_CPP11(__is_aggregate(HasInClassInit))]; + int t41[F(__is_aggregate(HasPrivateBase))]; + int t42[F(__is_aggregate(HasProtectedBase))]; + int t43[F(__is_aggregate(HasVirtBase))]; + + int t44[T(__is_aggregate(AggregateTemplate))]; + int t45[F(__is_aggregate(NonAggregateTemplate))]; +} + void is_arithmetic() { int t01[T(__is_arithmetic(float))]; @@ -481,9 +591,6 @@ int t31[F(__is_arithmetic(IntArNB))]; } -struct ACompleteType {}; -struct AnIncompleteType; - void is_complete_type() { int t01[T(__is_complete_type(float))];