PODness and Type Traits

Make C++ classes track the POD property (C++ [class]p4)
Track the existence of a copy assignment operator.
Implicitly declare the copy assignment operator if none is provided.
Implement most of the parsing job for the G++ type traits extension.
Fully implement the low-hanging fruit of the type traits:
__is_pod: Whether a type is a POD.
__is_class: Whether a type is a (non-union) class.
__is_union: Whether a type is a union.
__is_enum: Whether a type is an enum.
__is_polymorphic: Whether a type is polymorphic (C++ [class.virtual]p1).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61746 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index f4677f0..0396f52 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1153,7 +1153,7 @@
     FunctionDecl::StorageClass SC = FunctionDecl::None;
     switch (D.getDeclSpec().getStorageClassSpec()) {
       default: assert(0 && "Unknown storage class!");
-      case DeclSpec::SCS_auto:        
+      case DeclSpec::SCS_auto:
       case DeclSpec::SCS_register:
       case DeclSpec::SCS_mutable:
         Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func);
@@ -1319,9 +1319,14 @@
 
     if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
       InvalidDecl = InvalidDecl || CheckConstructor(Constructor);
-    else if (isa<CXXDestructorDecl>(NewFD))
-      cast<CXXRecordDecl>(NewFD->getParent())->setUserDeclaredDestructor(true);
-    else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
+    else if (isa<CXXDestructorDecl>(NewFD)) {
+      CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
+      Record->setUserDeclaredDestructor(true);
+      // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
+      // user-defined destructor.
+      Record->setPOD(false);
+    } else if (CXXConversionDecl *Conversion =
+               dyn_cast<CXXConversionDecl>(NewFD))
       ActOnConversionDeclarator(Conversion);
 
     // Extra checking for C++ overloaded operators (C++ [over.oper]).
@@ -2836,7 +2841,7 @@
   QualType T = GetTypeForDeclarator(D, S);
   assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
   bool InvalidDecl = false;
-  
+
   // C99 6.7.2.1p8: A member of a structure or union may have any type other
   // than a variably modified type.
   if (T->isVariablyModifiedType()) {
@@ -2872,8 +2877,11 @@
                               DeclSpec::SCS_mutable,
                             /*PrevDecl=*/0);
 
-  if (getLangOptions().CPlusPlus)
+  if (getLangOptions().CPlusPlus) {
     CheckExtraCXXDefaultArguments(D);
+    if (!T->isPODType())
+      cast<CXXRecordDecl>(Record)->setPOD(false);
+  }
 
   ProcessDeclAttributes(NewFD, D);
 
@@ -3088,7 +3096,7 @@
       ++NumNamedMembers;
     }
   }
- 
+
   // Okay, we successfully defined 'Record'.
   if (Record) {
     Record->completeDefinition(Context);