[cfe-commits] r58757 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticKinds.def lib/AST/DeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/aggregate-initialization.cpp

Douglas Gregor doug.gregor at gmail.com
Wed Nov 5 08:20:42 PST 2008


Author: dgregor
Date: Wed Nov  5 10:20:31 2008
New Revision: 58757

URL: http://llvm.org/viewvc/llvm-project?rev=58757&view=rev
Log:
Keep track of whether a C++ class is an aggregate. Don't allow initialization of non-aggregates with initializer lists.

Added:
    cfe/trunk/test/SemaCXX/aggregate-initialization.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=58757&r1=58756&r2=58757&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Nov  5 10:20:31 2008
@@ -215,6 +215,9 @@
   /// user-defined copy constructor.
   bool UserDeclaredCopyConstructor : 1;
 
+  /// Aggregate - True when this class is an aggregate.
+  bool Aggregate : 1;
+
   /// Bases - Base classes of this class.
   /// FIXME: This is wasted space for a union.
   CXXBaseSpecifier *Bases;
@@ -230,8 +233,8 @@
   CXXRecordDecl(TagKind TK, DeclContext *DC,
                 SourceLocation L, IdentifierInfo *Id) 
     : RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
-      UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), 
-      Bases(0), NumBases(0), Constructors(DC, Id) { }
+      UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
+      Aggregate(true), Bases(0), NumBases(0), Constructors(DC, Id) { }
 
   ~CXXRecordDecl();
 
@@ -300,6 +303,16 @@
     return UserDeclaredCopyConstructor;
   }
 
+  /// isAggregate - Whether this class is an aggregate (C++
+  /// [dcl.init.aggr]), which is a class with no user-declared
+  /// constructors, no private or protected non-static data members,
+  /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
+  bool isAggregate() const { return Aggregate; }
+
+  /// setAggregate - Set whether this class is an aggregate (C++
+  /// [dcl.init.aggr]).
+  void setAggregate(bool Agg) { Aggregate = Agg; }
+
   /// viewInheritance - Renders and displays an inheritance diagram
   /// for this C++ class and all of its base classes (transitively) using
   /// GraphViz.

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=58757&r1=58756&r2=58757&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Nov  5 10:20:31 2008
@@ -697,6 +697,8 @@
      "declaration of reference variable '%0' requires an initializer")
 DIAG(err_const_var_requires_init, ERROR,
      "declaration of const variable '%0' requires an initializer")
+DIAG(err_init_non_aggr_init_list, ERROR,
+     "initialization of non-aggregate type '%0' with an initializer list")
 
 // Objective-C++
 DIAG(err_objc_decls_may_only_appear_in_global_scope, ERROR,

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=58757&r1=58756&r2=58757&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Nov  5 10:20:31 2008
@@ -50,6 +50,11 @@
 void 
 CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, 
                         unsigned NumBases) {
+  // C++ [dcl.init.aggr]p1: 
+  //   An aggregate is an array or a class (clause 9) with [...]
+  //   no base classes [...].
+  Aggregate = false;
+
   if (this->Bases)
     delete [] this->Bases;
 
@@ -78,6 +83,11 @@
     // Note that we have a user-declared constructor.
     UserDeclaredConstructor = true;
 
+    // C++ [dcl.init.aggr]p1: 
+    //   An aggregate is an array or a class (clause 9) with no
+    //   user-declared constructors (12.1) [...].
+    Aggregate = false;
+
     // Note when we have a user-declared copy constructor, which will
     // suppress the implicit declaration of a copy constructor.
     if (ConDecl->isCopyConstructor(Context))
@@ -154,9 +164,8 @@
 
 bool CXXConstructorDecl::isDefaultConstructor() const {
   // C++ [class.ctor]p5:
-  //
-  //     A default constructor for a class X is a constructor of class
-  //     X that can be called without an argument.
+  //   A default constructor for a class X is a constructor of class
+  //   X that can be called without an argument.
   return (getNumParams() == 0) ||
          (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
 }
@@ -165,10 +174,10 @@
 CXXConstructorDecl::isCopyConstructor(ASTContext &Context, 
                                       unsigned &TypeQuals) const {
   // C++ [class.copy]p2:
-  //     A non-template constructor for class X is a copy constructor
-  //     if its first parameter is of type X&, const X&, volatile X& or
-  //     const volatile X&, and either there are no other parameters
-  //     or else all other parameters have default arguments (8.3.6).
+  //   A non-template constructor for class X is a copy constructor
+  //   if its first parameter is of type X&, const X&, volatile X& or
+  //   const volatile X&, and either there are no other parameters
+  //   or else all other parameters have default arguments (8.3.6).
   if ((getNumParams() < 1) ||
       (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
     return false;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=58757&r1=58756&r2=58757&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Nov  5 10:20:31 2008
@@ -701,6 +701,23 @@
                   Init->getSourceRange());
 
     return CheckSingleInitializer(Init, DeclType);
+  } else if (getLangOptions().CPlusPlus) {
+    // C++ [dcl.init]p14:
+    //   [...] If the class is an aggregate (8.5.1), and the initializer
+    //   is a brace-enclosed list, see 8.5.1.
+    //
+    // Note: 8.5.1 is handled below; here, we diagnose the case where
+    // 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.
+    if (const RecordType *ClassRec = DeclType->getAsRecordType()) {
+      const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassRec->getDecl());
+      if (!ClassDecl->isAggregate())
+        return Diag(InitLoc,
+                    diag::err_init_non_aggr_init_list,
+                    DeclType.getAsString(),
+                    Init->getSourceRange());
+    }
   }
 
   InitListChecker CheckInitList(this, InitList, DeclType);

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=58757&r1=58756&r2=58757&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Nov  5 10:20:31 2008
@@ -461,6 +461,15 @@
   // member decls.
   CXXClassMemberWrapper(Member).setAccess(AS);
 
+  // C++ [dcl.init.aggr]p1:
+  //   An aggregate is an array or a class (clause 9) with [...] no
+  //   private or protected non-static data members (clause 11).
+  if (isInstField && (AS == AS_private || AS == AS_protected))
+    cast<CXXRecordDecl>(CurContext)->setAggregate(false);
+
+  // FIXME: If the member is a virtual function, mark it its class as
+  // a non-aggregate.
+
   if (BitWidth) {
     // C++ 9.6p2: Only when declaring an unnamed bit-field may the
     // constant-expression be a value equal to zero.

Added: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=58757&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (added)
+++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp Wed Nov  5 10:20:31 2008
@@ -0,0 +1,26 @@
+// RUN: clang -fsyntax-only -verify -std=c++98 %s 
+
+// Verify that we can't initialize non-aggregates with an initializer
+// list.
+struct NonAggr1 {
+  NonAggr1(int) { }
+
+  int m;
+};
+
+struct Base { };
+struct NonAggr2 : public Base {
+  int m;
+};
+
+class NonAggr3 {
+  int m;
+};
+
+// FIXME: virtual functions
+struct NonAggr4 {
+};
+
+NonAggr1 na1 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr1' with an initializer list}}
+NonAggr2 na2 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr2' with an initializer list}}
+NonAggr3 na3 = { 17 }; // expected-error{{initialization of non-aggregate type 'class NonAggr3' with an initializer list}}

Propchange: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list