Switch Type::isAggregateType to use the C++ definition of "aggregate
type" rather than the C definition. We do this because both C99 and
Clang always use "aggregate type" as "aggregate or union type", and
the C++ definition includes union types.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63395 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index baa2016..7697f4a 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -328,7 +328,7 @@
   bool isVoidType() const;         // C99 6.2.5p19
   bool isDerivedType() const;      // C99 6.2.5p20
   bool isScalarType() const;       // C99 6.2.5p21 (arithmetic + pointers)
-  bool isAggregateType() const;    // C99 6.2.5p21 (arrays, structures)
+  bool isAggregateType() const;
   
   // Type Predicates: Check to see if this type is structurally the specified
   // type, ignoring typedefs and qualifiers.
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 65fd3b4..5d3478b 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -661,12 +661,20 @@
          isa<ObjCQualifiedIdType>(CanonicalType);
 }
 
+/// \brief Determines whether the type is a C++ aggregate type or C
+/// aggregate or union type.
+///
+/// An aggregate type is an array or a class type (struct, union, or
+/// class) that has no user-declared constructors, no private or
+/// protected non-static data members, no base classes, and no virtual
+/// functions (C++ [dcl.init.aggr]p1). The notion of an aggregate type
+/// subsumes the notion of C aggregates (C99 6.2.5p21) because it also
+/// includes union types.
 bool Type::isAggregateType() const {
-  if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) {
-    if (TT->getDecl()->isStruct())
-      return true;
-    return false;
-  }
+  if (const CXXRecordType *CXXClassType = dyn_cast<CXXRecordType>(CanonicalType))
+    return CXXClassType->getDecl()->isAggregate();
+  if (isa<RecordType>(CanonicalType))
+    return true;
   if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
     return ASQT->getBaseType()->isAggregateType();
   return isa<ArrayType>(CanonicalType);
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 6a7f86b..d9bdd8b 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -493,8 +493,7 @@
       // can be used in a lvalue context.  We need to enhance our support
       // of such temporaries in both the environment and the store, so right
       // now we just do a regular visit.
-      assert ((Ex->getType()->isAggregateType() || 
-              Ex->getType()->isUnionType()) &&
+      assert ((Ex->getType()->isAggregateType()) &&
               "Other kinds of expressions with non-aggregate/union types do"
               " not have lvalues.");
       
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ad6a719..3395313 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1083,6 +1083,7 @@
     // we have an initializer list and a destination type that is not
     // an aggregate.
     // FIXME: In C++0x, this is yet another form of initialization.
+    // FIXME: Move this checking into CheckInitList!
     if (const RecordType *ClassRec = DeclType->getAsRecordType()) {
       const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
       if (!ClassDecl->isAggregate())
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 77679ee..ed44acf 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -287,8 +287,8 @@
     CheckScalarType(IList, DeclType, Index, StructuredList, StructuredIndex);
   } else if (DeclType->isVectorType()) {
     CheckVectorType(IList, DeclType, Index, StructuredList, StructuredIndex);
-  } else if (DeclType->isAggregateType() || DeclType->isUnionType()) {
-    if (DeclType->isStructureType() || DeclType->isUnionType()) {
+  } else if (DeclType->isAggregateType()) {
+    if (DeclType->isRecordType()) {
       RecordDecl *RD = DeclType->getAsRecordType()->getDecl();
       CheckStructUnionTypes(IList, DeclType, RD->field_begin(), 
                             SubobjectIsDesignatorContext, Index,