EricWF created this revision.

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`.

Additionally this patch implements LWG 2015 
<http://cplusplus.github.io/LWG/lwg-defects.html#2015>, which requires than 
arrays used with [meta.unary.prop] traits have a complete element type.


https://reviews.llvm.org/D31513

Files:
  include/clang/Basic/TokenKinds.def
  include/clang/Basic/TypeTraits.h
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  test/PCH/cxx-traits.cpp
  test/PCH/cxx-traits.h
  test/SemaCXX/type-traits.cpp
  test/SemaTemplate/instantiate-method.cpp

Index: test/SemaTemplate/instantiate-method.cpp
===================================================================
--- test/SemaTemplate/instantiate-method.cpp
+++ test/SemaTemplate/instantiate-method.cpp
@@ -49,6 +49,18 @@
                 // the code below should probably instantiate by itself.
 int abstract_destructor[__is_abstract(HasDestructor<int>)? 1 : -1];
 
+template <class>
+class IsAggregate {
+};
+
+template <class T>
+class IsNotAggregate {
+  T value;
+public:
+  IsNotAggregate() {}
+};
+int test_is_aggregate[__is_aggregate(IsAggregate<int>) ? 1 : -1];
+int test_is_not_aggregate[__is_aggregate(IsNotAggregate<int>) ? -1 : 1];
 
 template<typename T>
 class Constructors {
Index: test/SemaCXX/type-traits.cpp
===================================================================
--- test/SemaCXX/type-traits.cpp
+++ test/SemaCXX/type-traits.cpp
@@ -1,4 +1,7 @@
 // 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
 
@@ -9,12 +12,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 +43,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 +57,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 +97,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 +169,12 @@
 };
 
 struct ThrowingDtor {
-  ~ThrowingDtor() throw(int);
+  ~ThrowingDtor()
+#if __cplusplus <= 201402L
+  throw(int);
+#else
+  noexcept(false);
+#endif
 };
 
 struct NoExceptDtor {
@@ -163,6 +185,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 +488,66 @@
   int t31[F(__is_floating_point(IntArNB))];
 }
 
+#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
+
+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))];
+}
+
 void is_arithmetic()
 {
   int t01[T(__is_arithmetic(float))];
@@ -481,9 +577,6 @@
   int t31[F(__is_arithmetic(IntArNB))];
 }
 
-struct ACompleteType {};
-struct AnIncompleteType;
-
 void is_complete_type()
 {
   int t01[T(__is_complete_type(float))];
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: 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<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: 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/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: 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: 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)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to