[cfe-commits] r131101 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLookup.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriter.cpp test/SemaCXX/aggregate-initialization.cpp

Sean Hunt scshunt at csclub.uwaterloo.ca
Mon May 9 14:45:35 PDT 2011


Author: coppro
Date: Mon May  9 16:45:35 2011
New Revision: 131101

URL: http://llvm.org/viewvc/llvm-project?rev=131101&view=rev
Log:
Clean up trivial default constructors now.

hasTrivialDefaultConstructor() really really means it now.

Also implement a fun standards bug regarding aggregates. Doug, if you'd
like, I can un-implement that bug if you think it is truly a defect.

The bug is that non-special-member constructors are never considered
user-provided, so the following is an aggregate:

struct foo {
  foo(int);
};

It's kind of bad, but the solution isn't obvious - should

struct foo {
  foo (int) = delete;
};

be an aggregate or not?

Lastly, add a missing initialization to FunctionDecl.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/SemaCXX/aggregate-initialization.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=131101&r1=131100&r2=131101&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon May  9 16:45:35 2011
@@ -1450,6 +1450,7 @@
       IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
       IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
       HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
+      IsDefaulted(false), IsExplicitlyDefaulted(false),
       HasImplicitReturnZero(false), IsLateTemplateParsed(false),
       EndRangeLoc(NameInfo.getEndLoc()),
       TemplateOrSpecialization(),

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=131101&r1=131100&r2=131101&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon May  9 16:45:35 2011
@@ -337,8 +337,8 @@
     /// HasPublicFields - True when there are private non-static data members.
     bool HasPublicFields : 1;
 
-    /// HasTrivialDefaultConstructor - True when this class has a trivial
-    /// default constructor.
+    /// HasTrivialDefaultConstructor - True when, if this class has a default
+    /// constructor, this default constructor is trivial.
     ///
     /// C++0x [class.ctor]p5
     ///    A default constructor is trivial if it is not user-provided and if
@@ -438,6 +438,9 @@
 
     /// \brief Whether we have already declared the default constructor or 
     /// do not need to have one declared.
+    bool NeedsImplicitDefaultConstructor : 1;
+
+    /// \brief Whether we have already declared the default constructor.
     bool DeclaredDefaultConstructor : 1;
 
     /// \brief Whether we have already declared the copy constructor.
@@ -676,8 +679,8 @@
   /// declared implicitly or does not need one declared implicitly.
   ///
   /// This value is used for lazy creation of default constructors.
-  bool hasDeclaredDefaultConstructor() const {
-    return data().DeclaredDefaultConstructor;
+  bool needsImplicitDefaultConstructor() const {
+    return data().NeedsImplicitDefaultConstructor;
   }
   
   /// hasConstCopyConstructor - Determines whether this class has a
@@ -810,7 +813,9 @@
   // constructor
   // (C++0x [class.ctor]p5)
   bool hasTrivialDefaultConstructor() const {
-    return data().HasTrivialDefaultConstructor;
+    return data().HasTrivialDefaultConstructor &&
+           (!data().UserDeclaredConstructor ||
+             data().DeclaredDefaultConstructor);
   }
 
   // hasConstExprNonCopyMoveConstructor - Whether this class has at least one

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=131101&r1=131100&r2=131101&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon May  9 16:45:35 2011
@@ -38,10 +38,10 @@
     HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
     HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
     HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
-    DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), 
-    DeclaredCopyAssignment(false), DeclaredDestructor(false),
-    NumBases(0), NumVBases(0), Bases(), VBases(),
-  Definition(D), FirstFriend(0) {
+    NeedsImplicitDefaultConstructor(false), DeclaredDefaultConstructor(false),
+    DeclaredCopyConstructor(false), DeclaredCopyAssignment(false),
+    DeclaredDestructor(false), NumBases(0), NumVBases(0), Bases(), VBases(),
+    Definition(D), FirstFriend(0) {
 }
 
 CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
@@ -458,8 +458,10 @@
     if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
       // If this is the implicit default constructor, note that we have now
       // declared it.
-      if (Constructor->isDefaultConstructor())
+      if (Constructor->isDefaultConstructor()) {
         data().DeclaredDefaultConstructor = true;
+        data().NeedsImplicitDefaultConstructor = true;
+      }
       // If this is the implicit copy constructor, note that we have now
       // declared it.
       else if (Constructor->isCopyConstructor())
@@ -490,21 +492,21 @@
     data().UserDeclaredConstructor = true;
 
     // Note that we have no need of an implicitly-declared default constructor.
-    data().DeclaredDefaultConstructor = true;
+    data().NeedsImplicitDefaultConstructor = true;
     
-    // C++ [dcl.init.aggr]p1:
-    //   An aggregate is an array or a class (clause 9) with no
-    //   user-declared constructors (12.1) [...].
-    data().Aggregate = false;
-
-    // C++ [class]p4:
-    //   A POD-struct is an aggregate class [...]
-    data().PlainOldData = false;
+    // FIXME: Under C++0x, /only/ special member functions may be user-provided.
+    //        This is probably a defect.
+    bool UserProvided = false;
 
     // C++0x [class.ctor]p5:
     //   A default constructor is trivial if it is not user-provided [...]
-    if (Constructor->isUserProvided())
-      data().HasTrivialDefaultConstructor = false;
+    if (Constructor->isDefaultConstructor()) {
+      data().DeclaredDefaultConstructor = true;
+      if (Constructor->isUserProvided()) {
+        data().HasTrivialDefaultConstructor = false;
+        UserProvided = true;
+      }
+    }
 
     // Note when we have a user-declared copy or move constructor, which will
     // suppress the implicit declaration of those constructors.
@@ -516,14 +518,18 @@
         // C++0x [class.copy]p13:
         //   A copy/move constructor for class X is trivial if it is not
         //   user-provided [...]
-        if (Constructor->isUserProvided())
+        if (Constructor->isUserProvided()) {
           data().HasTrivialCopyConstructor = false;
+          UserProvided = true;
+        }
       } else if (Constructor->isMoveConstructor()) {
         // C++0x [class.copy]p13:
         //   A copy/move constructor for class X is trivial if it is not
         //   user-provided [...]
-        if (Constructor->isUserProvided())
+        if (Constructor->isUserProvided()) {
           data().HasTrivialMoveConstructor = false;
+          UserProvided = true;
+        }
       }
     }
     if (Constructor->isConstExpr() &&
@@ -533,6 +539,21 @@
       data().HasConstExprNonCopyMoveConstructor = true;
     }
 
+    // C++ [dcl.init.aggr]p1:
+    //   An aggregate is an array or a class with no user-declared
+    //   constructors [...].
+    // C++0x [dcl.init.aggr]p1:
+    //   An aggregate is an array or a class with no user-provided
+    //   constructors [...].
+    if (!getASTContext().getLangOptions().CPlusPlus0x || UserProvided)
+      data().Aggregate = false;
+
+    // C++ [class]p4:
+    //   A POD-struct is an aggregate class [...]
+    // Since the POD bit is meant to be C++03 POD-ness, clear it even if the
+    // type is technically an aggregate in C++0x since it wouldn't be in 03.
+    data().PlainOldData = false;
+
     return;
   }
 

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=131101&r1=131100&r2=131101&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon May  9 16:45:35 2011
@@ -5005,7 +5005,7 @@
     
     if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
       CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
-      if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+      if (!BaseClassDecl->needsImplicitDefaultConstructor())
         ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
       else if (CXXConstructorDecl *Constructor
                             = getDefaultConstructorUnsafe(*this, BaseClassDecl))
@@ -5019,7 +5019,7 @@
        B != BEnd; ++B) {
     if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) {
       CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
-      if (!BaseClassDecl->hasDeclaredDefaultConstructor())
+      if (!BaseClassDecl->needsImplicitDefaultConstructor())
         ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl));
       else if (CXXConstructorDecl *Constructor
                             = getDefaultConstructorUnsafe(*this, BaseClassDecl))
@@ -5034,7 +5034,7 @@
     if (const RecordType *RecordTy
               = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
       CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
-      if (!FieldClassDecl->hasDeclaredDefaultConstructor())
+      if (!FieldClassDecl->needsImplicitDefaultConstructor())
         ExceptSpec.CalledDecl(
                             DeclareImplicitDefaultConstructor(FieldClassDecl));
       else if (CXXConstructorDecl *Constructor

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=131101&r1=131100&r2=131101&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Mon May  9 16:45:35 2011
@@ -534,7 +534,7 @@
     return;
 
   // If the default constructor has not yet been declared, do so now.
-  if (!Class->hasDeclaredDefaultConstructor())
+  if (!Class->needsImplicitDefaultConstructor())
     DeclareImplicitDefaultConstructor(Class);
 
   // If the copy constructor has not yet been declared, do so now.
@@ -581,7 +581,7 @@
     if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC))
       if (Record->getDefinition() &&
           CanDeclareSpecialMemberFunction(S.Context, Record)) {
-        if (!Record->hasDeclaredDefaultConstructor())
+        if (!Record->needsImplicitDefaultConstructor())
           S.DeclareImplicitDefaultConstructor(
                                            const_cast<CXXRecordDecl *>(Record));
         if (!Record->hasDeclaredCopyConstructor())
@@ -2140,7 +2140,7 @@
 DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) {
   // If the copy constructor has not yet been declared, do so now.
   if (CanDeclareSpecialMemberFunction(Context, Class)) {
-    if (!Class->hasDeclaredDefaultConstructor())
+    if (!Class->needsImplicitDefaultConstructor())
       DeclareImplicitDefaultConstructor(Class);
     if (!Class->hasDeclaredCopyConstructor())
       DeclareImplicitCopyConstructor(Class);

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=131101&r1=131100&r2=131101&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon May  9 16:45:35 2011
@@ -867,6 +867,7 @@
   Data.HasTrivialDestructor = Record[Idx++];
   Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
   Data.ComputedVisibleConversions = Record[Idx++];
+  Data.NeedsImplicitDefaultConstructor = Record[Idx++];
   Data.DeclaredDefaultConstructor = Record[Idx++];
   Data.DeclaredCopyConstructor = Record[Idx++];
   Data.DeclaredCopyAssignment = Record[Idx++];

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=131101&r1=131100&r2=131101&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon May  9 16:45:35 2011
@@ -3827,6 +3827,7 @@
   Record.push_back(Data.HasTrivialDestructor);
   Record.push_back(Data.HasNonLiteralTypeFieldsOrBases);
   Record.push_back(Data.ComputedVisibleConversions);
+  Record.push_back(Data.NeedsImplicitDefaultConstructor);
   Record.push_back(Data.DeclaredDefaultConstructor);
   Record.push_back(Data.DeclaredCopyConstructor);
   Record.push_back(Data.DeclaredCopyAssignment);

Modified: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=131101&r1=131100&r2=131101&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp Mon May  9 16:45:35 2011
@@ -2,6 +2,8 @@
 
 // Verify that we can't initialize non-aggregates with an initializer
 // list.
+// FIXME: Note that due to a (likely) standard bug, this is technically an
+//        aggregate.
 struct NonAggr1 {
   NonAggr1(int) { }
 
@@ -22,7 +24,7 @@
   virtual void f();
 };
 
-NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}}
+NonAggr1 na1 = { 17 };
 NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}}
 NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}}
 NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}}





More information about the cfe-commits mailing list