[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
John McCall
rjmccall at apple.com
Sun May 1 01:14:24 PDT 2011
On May 1, 2011, at 12:04 AM, Sean Hunt wrote:
> 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;
> + }
> +
My preference would be for this method to assert(isDelegatingConstructor()).
Also, I think the name ought to have 'delegate' in there somewhere, maybe
'getDelegateTargetConstructor()'.
> 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;
> +
Complete-to-base delegation is still fine for delegating constructors if
there are no virtual bases, because by definition the complete and base
variants of the target constructor are equivalent.
> @@ -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");
> }
Better to just assert(Member->isAnyMemberInitializer());
> +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);
> +}
This is clever. After the delegate call succeeds, though, you do
need to push a cleanup to call the dtor if an exception is thrown
in the body of the delegating constructor.
> 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;
> + }
Since this is already inside an if/else, go ahead and break up this
ternary operator, or even consider using a switch over the construction kind.
> 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;
> +}
Is this FIXME still correct? It certainly looks like it detects loops of
arbitrary length.
However, it also looks like it can infinite-loop if there's a loop not
involving the current constructor, e.g.
MyClass() : MyClass(0) {}
MyClass(int x) : MyClass() { this->x = x; } // should get an error here, but then...
MyClass(int x, int y) : MyClass(x) { this->y = y; } // this will infinite loop.
John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20110501/89f9f7ed/attachment.html>
More information about the cfe-commits
mailing list