r300116 - [Sema] Add __is_aggregate type-trait

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 12 15:12:15 PDT 2017


Author: ericwf
Date: Wed Apr 12 17:12:15 2017
New Revision: 300116

URL: http://llvm.org/viewvc/llvm-project?rev=300116&view=rev
Log:
[Sema] Add __is_aggregate type-trait

Summary:
[LWG 2911](http://cplusplus.github.io/LWG/lwg-defects.html#2911) adds `std::is_aggregate` to the library, which requires a new builtin trait. This patch implements `__is_aggregate`.


Reviewers: rsmith, majnemer, aaron.ballman

Reviewed By: aaron.ballman

Subscribers: STL_MSFT, cfe-commits

Differential Revision: https://reviews.llvm.org/D31513

Modified:
    cfe/trunk/docs/LanguageExtensions.rst
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/include/clang/Basic/TypeTraits.h
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/PCH/cxx-traits.cpp
    cfe/trunk/test/PCH/cxx-traits.h
    cfe/trunk/test/SemaCXX/type-traits.cpp

Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Wed Apr 12 17:12:15 2017
@@ -993,6 +993,7 @@ The following type trait primitives are
 * ``__has_trivial_destructor`` (GNU, Microsoft)
 * ``__has_virtual_destructor`` (GNU, Microsoft)
 * ``__is_abstract`` (GNU, Microsoft)
+* ``__is_aggregate`` (GNU, Microsoft)
 * ``__is_base_of`` (GNU, Microsoft)
 * ``__is_class`` (GNU, Microsoft)
 * ``__is_convertible_to`` (Microsoft)

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Wed Apr 12 17:12:15 2017
@@ -432,6 +432,7 @@ TYPE_TRAIT_1(__has_trivial_move_construc
 TYPE_TRAIT_1(__has_trivial_destructor, HasTrivialDestructor, KEYCXX)
 TYPE_TRAIT_1(__has_virtual_destructor, HasVirtualDestructor, KEYCXX)
 TYPE_TRAIT_1(__is_abstract, IsAbstract, KEYCXX)
+TYPE_TRAIT_1(__is_aggregate, IsAggregate, KEYCXX)
 TYPE_TRAIT_2(__is_base_of, IsBaseOf, KEYCXX)
 TYPE_TRAIT_1(__is_class, IsClass, KEYCXX)
 TYPE_TRAIT_2(__is_convertible_to, IsConvertibleTo, KEYCXX)

Modified: cfe/trunk/include/clang/Basic/TypeTraits.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TypeTraits.h (original)
+++ cfe/trunk/include/clang/Basic/TypeTraits.h Wed Apr 12 17:12:15 2017
@@ -31,6 +31,7 @@ namespace clang {
     UTT_HasTrivialDestructor,
     UTT_HasVirtualDestructor,
     UTT_IsAbstract,
+    UTT_IsAggregate,
     UTT_IsArithmetic,
     UTT_IsArray,
     UTT_IsClass,

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Wed Apr 12 17:12:15 2017
@@ -1406,6 +1406,7 @@ void Parser::ParseClassSpecifier(tok::To
       !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,

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Wed Apr 12 17:12:15 2017
@@ -676,6 +676,7 @@ class CastExpressionIdValidator : public
 ///                   '__is_union'
 ///
 /// [Clang] unary-type-trait:
+///                   '__is_aggregate'
 ///                   '__trivially_copyable'
 ///
 ///       binary-type-trait:
@@ -804,6 +805,7 @@ ExprResult Parser::ParseCastExpression(b
             = 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);

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Apr 12 17:12:15 2017
@@ -4057,6 +4057,7 @@ static bool CheckUnaryTypeTraitTypeCompl
 
   // 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:
@@ -4231,6 +4232,12 @@ static bool EvaluateUnaryTypeTrait(Sema
     if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
       return !RD->isUnion() && RD->isAbstract();
     return false;
+  case UTT_IsAggregate:
+    // Report vector extensions and complex types as aggregates because they
+    // support aggregate initialization. GCC mirrors this behavior for vectors
+    // but not _Complex.
+    return T->isAggregateType() || T->isVectorType() || T->isExtVectorType() ||
+           T->isAnyComplexType();
   // __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.

Modified: cfe/trunk/test/PCH/cxx-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-traits.cpp?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-traits.cpp (original)
+++ cfe/trunk/test/PCH/cxx-traits.cpp Wed Apr 12 17:12:15 2017
@@ -16,6 +16,7 @@ bool copy_construct_int = n::is_triviall
 
 // 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);

Modified: cfe/trunk/test/PCH/cxx-traits.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-traits.h?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-traits.h (original)
+++ cfe/trunk/test/PCH/cxx-traits.h Wed Apr 12 17:12:15 2017
@@ -18,6 +18,7 @@ struct is_trivially_constructible {
 };
 
 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}}

Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=300116&r1=300115&r2=300116&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Wed Apr 12 17:12:15 2017
@@ -1,20 +1,28 @@
 // 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
 
 struct NonPOD { NonPOD(int); };
+typedef NonPOD NonPODAr[10];
+typedef NonPOD NonPODArNB[];
+typedef NonPOD NonPODArMB[10][2];
 
 // PODs
 enum Enum { EV };
 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 *(); };
@@ -31,6 +39,9 @@ struct HasAnonymousUnion {
 typedef int Vector __attribute__((vector_size(16)));
 typedef int VectorExt __attribute__((ext_vector_type(4)));
 
+using ComplexFloat = _Complex float;
+using ComplexInt = _Complex int;
+
 // Not PODs
 typedef const void cvoid;
 struct Derives : POD {};
@@ -38,6 +49,10 @@ typedef Derives DerivesAr[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 +63,15 @@ struct HasNoExceptNoThrowMoveAssign {
     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 +103,7 @@ struct HasDest { ~HasDest(); };
 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 +175,12 @@ struct VariadicCtor {
 };
 
 struct ThrowingDtor {
-  ~ThrowingDtor() throw(int);
+  ~ThrowingDtor()
+#if __cplusplus <= 201402L
+  throw(int);
+#else
+  noexcept(false);
+#endif
 };
 
 struct NoExceptDtor {
@@ -163,6 +191,20 @@ struct NoThrowDtor {
   ~NoThrowDtor() throw();
 };
 
+struct ACompleteType {};
+struct AnIncompleteType; // expected-note 1+ {{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 +494,83 @@ void is_floating_point()
   int t31[F(__is_floating_point(IntArNB))];
 }
 
+template <class T>
+struct AggregateTemplate {
+  T value;
+};
+
+template <class T>
+struct NonAggregateTemplate {
+  T value;
+  NonAggregateTemplate();
+};
+
+void is_aggregate()
+{
+  constexpr bool TrueAfterCpp11 = __cplusplus > 201103L;
+  constexpr bool TrueAfterCpp14 = __cplusplus > 201402L;
+
+  __is_aggregate(AnIncompleteType); // expected-error {{incomplete type}}
+  __is_aggregate(AnIncompleteTypeAr); // expected-error {{incomplete type}}
+  __is_aggregate(AnIncompleteTypeArNB); // expected-error {{incomplete type}}
+  __is_aggregate(AnIncompleteTypeArMB); // expected-error {{incomplete type}}
+  __is_aggregate(IncompleteUnion); // expected-error {{incomplete type}}
+
+  static_assert(!__is_aggregate(NonPOD), "");
+  static_assert(__is_aggregate(NonPODAr), "");
+  static_assert(__is_aggregate(NonPODArNB), "");
+  static_assert(__is_aggregate(NonPODArMB), "");
+
+  static_assert(!__is_aggregate(Enum), "");
+  static_assert(__is_aggregate(POD), "");
+  static_assert(__is_aggregate(Empty), "");
+  static_assert(__is_aggregate(EmptyAr), "");
+  static_assert(__is_aggregate(EmptyArNB), "");
+  static_assert(__is_aggregate(EmptyArMB), "");
+  static_assert(!__is_aggregate(void), "");
+  static_assert(!__is_aggregate(const volatile void), "");
+  static_assert(!__is_aggregate(int), "");
+  static_assert(__is_aggregate(IntAr), "");
+  static_assert(__is_aggregate(IntArNB), "");
+  static_assert(__is_aggregate(EmptyUnion), "");
+  static_assert(__is_aggregate(Union), "");
+  static_assert(__is_aggregate(Statics), "");
+  static_assert(__is_aggregate(HasFunc), "");
+  static_assert(__is_aggregate(HasOp), "");
+  static_assert(__is_aggregate(HasAssign), "");
+  static_assert(__is_aggregate(HasAnonymousUnion), "");
+
+  static_assert(__is_aggregate(Derives) == TrueAfterCpp14, "");
+  static_assert(__is_aggregate(DerivesAr), "");
+  static_assert(__is_aggregate(DerivesArNB), "");
+  static_assert(!__is_aggregate(HasCons), "");
+  static_assert(__is_aggregate(HasDefaultCons), "");
+  static_assert(!__is_aggregate(HasExplicitDefaultCons), "");
+  static_assert(!__is_aggregate(HasInheritedCons), "");
+  static_assert(__is_aggregate(HasNoInheritedCons) == TrueAfterCpp14, "");
+  static_assert(__is_aggregate(HasCopyAssign), "");
+  static_assert(!__is_aggregate(NonTrivialDefault), "");
+  static_assert(__is_aggregate(HasDest), "");
+  static_assert(!__is_aggregate(HasPriv), "");
+  static_assert(!__is_aggregate(HasProt), "");
+  static_assert(__is_aggregate(HasRefAggregate), "");
+  static_assert(__is_aggregate(HasNonPOD), "");
+  static_assert(!__is_aggregate(HasVirt), "");
+  static_assert(__is_aggregate(VirtAr), "");
+  static_assert(__is_aggregate(HasInClassInit) == TrueAfterCpp11, "");
+  static_assert(!__is_aggregate(HasPrivateBase), "");
+  static_assert(!__is_aggregate(HasProtectedBase), "");
+  static_assert(!__is_aggregate(HasVirtBase), "");
+
+  static_assert(__is_aggregate(AggregateTemplate<int>), "");
+  static_assert(!__is_aggregate(NonAggregateTemplate<int>), "");
+
+  static_assert(__is_aggregate(Vector), ""); // Extension supported by GCC and Clang
+  static_assert(__is_aggregate(VectorExt), "");
+  static_assert(__is_aggregate(ComplexInt), "");
+  static_assert(__is_aggregate(ComplexFloat), "");
+}
+
 void is_arithmetic()
 {
   int t01[T(__is_arithmetic(float))];
@@ -481,9 +600,6 @@ void is_arithmetic()
   int t31[F(__is_arithmetic(IntArNB))];
 }
 
-struct ACompleteType {};
-struct AnIncompleteType;
-
 void is_complete_type()
 {
   int t01[T(__is_complete_type(float))];




More information about the cfe-commits mailing list