diff options
-rw-r--r-- | lib/Sema/SemaInit.cpp | 22 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.init/dcl.init.ref/p16-cxx0x-no-extra-copy.cpp | 3 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp | 16 |
3 files changed, 33 insertions, 8 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 59f4393e55..7929b588b6 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3264,10 +3264,26 @@ static Sema::OwningExprResult CopyObject(Sema &S, if (IsExtraneousCopy) { // If this is a totally extraneous copy for C++03 reference // binding purposes, just return the original initialization - // expression. + // expression. We don't generate an (elided) copy operation here + // because doing so would require us to pass down a flag to avoid + // infinite recursion, where each step adds another extraneous, + // elidable copy. + + // Instantiate the default arguments of any extra parameters in + // the selected copy constructor, as if we were going to create a + // proper call to the copy constructor. + for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) { + ParmVarDecl *Parm = Constructor->getParamDecl(I); + if (S.RequireCompleteType(Loc, Parm->getType(), + S.PDiag(diag::err_call_incomplete_argument))) + break; + + // Build the default argument expression; we don't actually care + // if this succeeds or not, because this routine will complain + // if there was a problem. + S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm); + } - // FIXME: We'd like to call CompleteConstructorCall below, so that - // we instantiate default arguments and such. return S.Owned(CurInitExpr); } diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p16-cxx0x-no-extra-copy.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p16-cxx0x-no-extra-copy.cpp index 38bf9f7143..5a342d423a 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p16-cxx0x-no-extra-copy.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p16-cxx0x-no-extra-copy.cpp @@ -27,8 +27,7 @@ private: template<typename T> T get_value_badly() { double *dp = 0; - T *tp = dp; // FIXME: Should get an error here, from instantiating the - // default argument of X4<int> + T *tp = dp; return T(); } diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp index 5dd6861357..16394110d0 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp @@ -24,28 +24,38 @@ private: X3(X3&); // expected-note{{candidate constructor not viable: no known conversion from 'X3' to 'X3 &' for 1st argument}} }; +// Check for instantiation of default arguments template<typename T> T get_value_badly() { double *dp = 0; - T *tp = dp; // FIXME: Should get an error here, from instantiating the - // default argument of X4<int> + T *tp = dp; // expected-error{{ cannot initialize a variable of type 'int *' with an lvalue of type 'double *'}} return T(); } template<typename T> struct X4 { X4(); - X4(const X4&, T = get_value_badly<T>()); + X4(const X4&, T = get_value_badly<T>()); // expected-note{{in instantiation of}} +}; + +// Check for "dangerous" default arguments that could cause recursion. +struct X5 { + X5(); + X5(const X5&, const X5& = X5()); // expected-error{{no viable constructor copying parameter of type 'X5'}} }; void g1(const X1&); void g2(const X2&); void g3(const X3&); void g4(const X4<int>&); +void g5(const X5&); void test() { g1(X1()); // expected-error{{no viable constructor copying parameter of type 'X1'}} g2(X2()); // expected-error{{calling a private constructor of class 'X2'}} g3(X3()); // expected-error{{no viable constructor copying parameter of type 'X3'}} g4(X4<int>()); + g5(X5()); // expected-error{{no viable constructor copying parameter of type 'X5'}} } + +// Check for dangerous recursion in default arguments. |