[cfe-commits] r130642 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/AST/ExprCXX.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Initialization.h include/clang/Sema/Sema.h lib/CodeGen/CGClass.cpp lib/CodeGen/CGExprCXX.cpp lib/CodeGen/CodeGenFunction.h lib/Lex/PPMacroExpansion.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaInit.cpp test/CodeGenCXX/cxx0x-delegating-ctors.cpp test/SemaCXX/cxx0x-delegating-ctors.cpp www/cxx_status.html

Sean Hunt scshunt at csclub.uwaterloo.ca
Sun May 1 00:04:32 PDT 2011


Author: coppro
Date: Sun May  1 02:04:31 2011
New Revision: 130642

URL: http://llvm.org/viewvc/llvm-project?rev=130642&view=rev
Log:
Fully implement delegating constructors!

As far as I know, this implementation is complete but might be missing a
few optimizations. Exceptions and virtual bases are handled correctly.

Because I'm an optimist, the web page has appropriately been updated. If
I'm wrong, feel free to downgrade its support categories.

Added:
    cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
    cfe/trunk/test/SemaCXX/cxx0x-delegating-ctors.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Initialization.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/CodeGen/CGClass.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sun May  1 02:04:31 2011
@@ -1608,6 +1608,23 @@
   void setCtorInitializers(CXXCtorInitializer ** initializers) {
     CtorInitializers = initializers;
   }
+
+  /// isDelegatingConstructor - Whether this constructor is a
+  /// delegating constructor
+  bool isDelegatingConstructor() const {
+    return (getNumCtorInitializers() == 1) &&
+      CtorInitializers[0]->isDelegatingInitializer();
+  }
+
+  /// getTargetConstructor - When this constructor delegates to
+  /// another, retrieve the target
+  CXXConstructorDecl *getTargetConstructor() const {
+    if (isDelegatingConstructor())
+      return CtorInitializers[0]->getTargetConstructor();
+    else
+      return 0;
+  }
+
   /// isDefaultConstructor - Whether this constructor is a default
   /// constructor (C++ [class.ctor]p5), which can be used to
   /// default-initialize a class of this type.

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Sun May  1 02:04:31 2011
@@ -780,7 +780,8 @@
   enum ConstructionKind {
     CK_Complete,
     CK_NonVirtualBase,
-    CK_VirtualBase
+    CK_VirtualBase,
+    CK_Delegating
   };
     
 private:

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun May  1 02:04:31 2011
@@ -1008,6 +1008,10 @@
   "delegating constructors are not fully implemented">;
 def err_delegating_initializer_alone : Error<
   "an initializer for a delegating constructor must appear alone">;
+def err_delegating_ctor_loop : Error<
+  "constructor %0 delegates to itself (possibly indirectly)">;
+def err_delegating_codegen_not_implemented : Error<
+  "code generation for delegating constructors not implemented">;
 
 // C++0x range-based for loop
 def err_for_range_decl_must_be_var : Error<

Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Sun May  1 02:04:31 2011
@@ -65,7 +65,7 @@
     /// \brief The entity being initialized is a base member subobject.
     EK_Base,
     /// \brief The initialization is being done by a delegating constructor.
-    EK_Delegation,
+    EK_Delegating,
     /// \brief The entity being initialized is an element of a vector.
     /// or vector.
     EK_VectorElement,
@@ -215,7 +215,7 @@
 
   /// \brief Create the initialization entity for a delegated constructor.
   static InitializedEntity InitializeDelegation(QualType Type) {
-    return InitializedEntity(EK_Delegation, SourceLocation(), Type);
+    return InitializedEntity(EK_Delegating, SourceLocation(), Type);
   }
   
   /// \brief Create the initialization entity for a member subobject.

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sun May  1 02:04:31 2011
@@ -3072,6 +3072,9 @@
                                            SourceLocation LParenLoc,
                                            CXXRecordDecl *ClassDecl);
 
+  bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+                                CXXCtorInitializer *Initializer);
+
   bool SetCtorInitializers(CXXConstructorDecl *Constructor,
                            CXXCtorInitializer **Initializers,
                            unsigned NumInitializers, bool AnyErrors);

Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Sun May  1 02:04:31 2011
@@ -658,6 +658,10 @@
   if (Ctor->getType()->getAs<FunctionProtoType>()->isVariadic())
     return false;
 
+  // FIXME: Decide if we can do a delegation of a delegating constructor.
+  if (Ctor->isDelegatingConstructor())
+    return false;
+
   return true;
 }
 
@@ -710,6 +714,9 @@
 void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
                                        CXXCtorType CtorType,
                                        FunctionArgList &Args) {
+  if (CD->isDelegatingConstructor())
+    return EmitDelegatingCXXConstructorCall(CD, Args);
+
   const CXXRecordDecl *ClassDecl = CD->getParent();
 
   llvm::SmallVector<CXXCtorInitializer *, 8> MemberInitializers;
@@ -721,8 +728,10 @@
     
     if (Member->isBaseInitializer())
       EmitBaseInitializer(*this, ClassDecl, Member, CtorType);
-    else
+    else if (Member->isAnyMemberInitializer())
       MemberInitializers.push_back(Member);
+    else
+      llvm_unreachable("Delegating initializer on non-delegating constructor");
   }
 
   InitializeVTablePointers(ClassDecl);
@@ -1262,6 +1271,19 @@
            ReturnValueSlot(), DelegateArgs, Ctor);
 }
 
+void
+CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
+                                                  const FunctionArgList &Args) {
+  assert(Ctor->isDelegatingConstructor());
+
+  llvm::Value *ThisPtr = LoadCXXThis();
+
+  AggValueSlot AggSlot = AggValueSlot::forAddr(ThisPtr, false, /*Lifetime*/ true);
+
+  EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
+}
+
+
 void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
                                             CXXDtorType Type,
                                             bool ForVirtualBase,

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sun May  1 02:04:31 2011
@@ -404,9 +404,16 @@
                                E->arg_begin(), E->arg_end());
   }
   else {
-    CXXCtorType Type = 
-      (E->getConstructionKind() == CXXConstructExpr::CK_Complete) 
-      ? Ctor_Complete : Ctor_Base;
+    CXXCtorType Type;
+    CXXConstructExpr::ConstructionKind K = E->getConstructionKind();
+    if (K == CXXConstructExpr::CK_Delegating) {
+      // We should be emitting a constructor; GlobalDecl will assert this
+      Type = CurGD.getCtorType();
+    } else {
+      Type = (E->getConstructionKind() == CXXConstructExpr::CK_Complete)
+             ? Ctor_Complete : Ctor_Base;
+    }
+
     bool ForVirtualBase = 
       E->getConstructionKind() == CXXConstructExpr::CK_VirtualBase;
     

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Sun May  1 02:04:31 2011
@@ -1496,6 +1496,12 @@
   void EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
                                       CXXCtorType CtorType,
                                       const FunctionArgList &Args);
+  // It's important not to confuse this and the previous function. Delegating
+  // constructors are the C++0x feature. The constructor delegate optimization
+  // is used to reduce duplication in the base and complete consturctors where
+  // they are substantially the same.
+  void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
+                                        const FunctionArgList &Args);
   void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
                               bool ForVirtualBase, llvm::Value *This,
                               CallExpr::const_arg_iterator ArgBeg,

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Sun May  1 02:04:31 2011
@@ -561,6 +561,7 @@
            .Case("cxx_auto_type", LangOpts.CPlusPlus0x)
            .Case("cxx_decltype", LangOpts.CPlusPlus0x)
            .Case("cxx_default_function_template_args", LangOpts.CPlusPlus0x)
+           .Case("cxx_delegating_constructors", LangOpts.CPlusPlus0x)
            .Case("cxx_deleted_functions", LangOpts.CPlusPlus0x)
            .Case("cxx_inline_namespaces", LangOpts.CPlusPlus0x)
          //.Case("cxx_lambdas", false)

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun May  1 02:04:31 2011
@@ -2068,6 +2068,30 @@
 
   return false;
 }
+
+bool
+Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+                               CXXCtorInitializer *Initializer) {
+  Constructor->setNumCtorInitializers(1);
+  CXXCtorInitializer **initializer =
+    new (Context) CXXCtorInitializer*[1];
+  memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*));
+  Constructor->setCtorInitializers(initializer);
+
+  // FIXME: This doesn't catch indirect loops yet
+  CXXConstructorDecl *Target = Initializer->getTargetConstructor();
+  while (Target) {
+    if (Target == Constructor) {
+      Diag(Initializer->getSourceLocation(), diag::err_delegating_ctor_loop)
+        << Constructor;
+      return true;
+    }
+    Target = Target->getTargetConstructor();
+  }
+
+  return false;
+}
+
                                
 bool
 Sema::SetCtorInitializers(CXXConstructorDecl *Constructor,
@@ -2442,7 +2466,11 @@
              diag::err_delegating_initializer_alone)
           << MemInits[0]->getSourceRange();
         HadError = true;
+        // We will treat this as being the only initializer.
       }
+      SetDelegatingInitializer(Constructor, *MemInits);
+      // Return immediately as the initializer is set.
+      return;
     }
   }
 

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sun May  1 02:04:31 2011
@@ -2045,7 +2045,7 @@
   case EK_New:
   case EK_Temporary:
   case EK_Base:
-  case EK_Delegation:
+  case EK_Delegating:
   case EK_ArrayElement:
   case EK_VectorElement:
   case EK_BlockElement:
@@ -2068,7 +2068,7 @@
   case EK_New:
   case EK_Temporary:
   case EK_Base:
-  case EK_Delegation:
+  case EK_Delegating:
   case EK_ArrayElement:
   case EK_VectorElement:
   case EK_BlockElement:
@@ -2091,7 +2091,7 @@
   case EK_New:
   case EK_Temporary:
   case EK_Base:
-  case EK_Delegation:
+  case EK_Delegating:
   case EK_ArrayElement:
   case EK_VectorElement:
   case EK_BlockElement:
@@ -3346,7 +3346,7 @@
   case InitializedEntity::EK_New:
   case InitializedEntity::EK_Exception:
   case InitializedEntity::EK_Base:
-  case InitializedEntity::EK_Delegation:
+  case InitializedEntity::EK_Delegating:
     return Sema::AA_Initializing;
 
   case InitializedEntity::EK_Parameter:
@@ -3383,7 +3383,7 @@
   case InitializedEntity::EK_New:
   case InitializedEntity::EK_Variable:
   case InitializedEntity::EK_Base:
-  case InitializedEntity::EK_Delegation:
+  case InitializedEntity::EK_Delegating:
   case InitializedEntity::EK_VectorElement:
   case InitializedEntity::EK_Exception:
   case InitializedEntity::EK_BlockElement:
@@ -3405,7 +3405,7 @@
     case InitializedEntity::EK_Result:
     case InitializedEntity::EK_New:
     case InitializedEntity::EK_Base:
-    case InitializedEntity::EK_Delegation:
+    case InitializedEntity::EK_Delegating:
     case InitializedEntity::EK_VectorElement:
     case InitializedEntity::EK_BlockElement:
       return false;
@@ -3490,7 +3490,7 @@
   case InitializedEntity::EK_Temporary:
   case InitializedEntity::EK_New:
   case InitializedEntity::EK_Base:
-  case InitializedEntity::EK_Delegation:
+  case InitializedEntity::EK_Delegating:
   case InitializedEntity::EK_VectorElement:
   case InitializedEntity::EK_BlockElement:
     Loc = CurInitExpr->getLocStart();
@@ -4061,6 +4061,9 @@
             CXXConstructExpr::CK_VirtualBase :
             CXXConstructExpr::CK_NonVirtualBase;
         }
+        if (Entity.getKind() == InitializedEntity::EK_Delegating) {
+          ConstructKind = CXXConstructExpr::CK_Delegating;
+        }
 
         // Only get the parenthesis range if it is a direct construction.
         SourceRange parenRange =

Added: cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp?rev=130642&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/cxx0x-delegating-ctors.cpp Sun May  1 02:04:31 2011
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -emit-llvm -fexceptions -fcxx-exceptions -std=c++0x -o - %s | FileCheck %s
+
+struct non_trivial {
+  non_trivial();
+  ~non_trivial();
+};
+non_trivial::non_trivial() {}
+non_trivial::~non_trivial() {}
+
+// We use a virtual base to ensure that the constructor
+// delegation optimization (complete->base) can't be
+// performed.
+struct delegator {
+  non_trivial n; 
+  delegator();
+  delegator(int);
+  delegator(char);
+  delegator(bool);
+};
+
+delegator::delegator() {
+  throw 0;
+}
+
+// CHECK: define void @_ZN9delegatorC1Ei
+// CHECK: call void @_ZN9delegatorC1Ev
+// CHECK-NOT: lpad
+// CHECK: ret
+// CHECK-NOT: lpad
+// CHECK: define void @_ZN9delegatorC2Ei
+// CHECK: call void @_ZN9delegatorC2Ev
+// CHECK-NOT: lpad
+// CHECK: ret
+// CHECK-NOT: lpad
+delegator::delegator(int)
+  : delegator()
+{}
+
+delegator::delegator(bool)
+{}
+
+// CHECK: define void @_ZN9delegatorC2Ec
+// CHECK: call void @_ZN9delegatorC2Eb
+// CHECK: call void @__cxa_throw
+delegator::delegator(char)
+  : delegator(true) {
+  throw 0;
+}

Added: cfe/trunk/test/SemaCXX/cxx0x-delegating-ctors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-delegating-ctors.cpp?rev=130642&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-delegating-ctors.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx0x-delegating-ctors.cpp Sun May  1 02:04:31 2011
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s
+
+struct foo {
+  int i;
+  foo();
+  foo(int);
+  foo(int, int);
+  foo(bool);
+  foo(char);
+  foo(float*);
+  foo(float&);
+};
+
+// Good
+foo::foo (int i) : i(i) {
+}
+// Good
+foo::foo () : foo(-1) {
+}
+// Good
+foo::foo (int, int) : foo() {
+}
+
+foo::foo (bool) : foo(true) { // expected-error{{delegates to itself}}
+}
+
+// Good
+foo::foo (float* f) : foo(*f) {
+}
+
+// FIXME: This should error
+foo::foo (float &f) : foo(&f) {
+}
+
+foo::foo (char) : i(3), foo(3) { // expected-error{{must appear alone}}
+}

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=130642&r1=130641&r2=130642&view=diff
==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Sun May  1 02:04:31 2011
@@ -348,10 +348,10 @@
 <tr><td colspan="7" class="category">Class Modifications</td></tr>
 <tr>
   <td>delegating constructors</td>
-  <td></td>
-  <td></td>
-  <td></td>
-  <td></td>
+  <td class="complete"></td>
+  <td class="complete"></td>
+  <td class="complete"></td>
+  <td class="complete"></td>
   <td>12.6.2</td>
   <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986">N1986</a></td>
 </tr>





More information about the cfe-commits mailing list