forked from OSchip/llvm-project
When checking the copy constructor for the optional copy during a
reference binding to an rvalue of reference-compatible type, check parameters after the first for complete parameter types and build any required default function arguments. We're effectively simulating the type-checking for a call without building the call itself. llvm-svn: 101705
This commit is contained in:
parent
c9cd64eee3
commit
30b5277a0a
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue