When performing copy initialization (= "implicit conversion", here) to
a class type from itself or a derived class thereof, enumerate constructors and permit user-defined conversions to the arguments of those constructors. This fixes the wacky implicit conversion sequence used in std::auto_ptr's lame emulation of move semantics. llvm-svn: 88670
This commit is contained in:
parent
07eae02fc7
commit
379d84b7ed
|
@ -1399,6 +1399,13 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
|
|||
// functions are all the converting constructors (12.3.1) of
|
||||
// that class. The argument list is the expression-list within
|
||||
// the parentheses of the initializer.
|
||||
bool SuppressUserConversions = !UserCast;
|
||||
if (Context.hasSameUnqualifiedType(ToType, From->getType()) ||
|
||||
IsDerivedFrom(From->getType(), ToType)) {
|
||||
SuppressUserConversions = false;
|
||||
AllowConversionFunctions = false;
|
||||
}
|
||||
|
||||
DeclarationName ConstructorName
|
||||
= Context.DeclarationNames.getCXXConstructorName(
|
||||
Context.getCanonicalType(ToType).getUnqualifiedType());
|
||||
|
@ -1420,15 +1427,13 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
|
|||
Constructor->isConvertingConstructor(AllowExplicit)) {
|
||||
if (ConstructorTmpl)
|
||||
AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, &From,
|
||||
1, CandidateSet,
|
||||
/*SuppressUserConversions=*/!UserCast,
|
||||
ForceRValue);
|
||||
1, CandidateSet,
|
||||
SuppressUserConversions, ForceRValue);
|
||||
else
|
||||
// Allow one user-defined conversion when user specifies a
|
||||
// From->ToType conversion via an static cast (c-style, etc).
|
||||
AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
|
||||
/*SuppressUserConversions=*/!UserCast,
|
||||
ForceRValue);
|
||||
SuppressUserConversions, ForceRValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
class X {
|
||||
public:
|
||||
operator bool();
|
||||
|
@ -93,3 +93,31 @@ void f(Yb& a) {
|
|||
char ch = a; // OK. calls Yb::operator char();
|
||||
}
|
||||
|
||||
// Test conversion + copy construction.
|
||||
class AutoPtrRef { };
|
||||
|
||||
class AutoPtr {
|
||||
// FIXME: Using 'unavailable' since we do not have access control yet.
|
||||
// FIXME: The error message isn't so good.
|
||||
AutoPtr(AutoPtr &) __attribute__((unavailable));
|
||||
|
||||
public:
|
||||
AutoPtr();
|
||||
AutoPtr(AutoPtrRef);
|
||||
|
||||
operator AutoPtrRef();
|
||||
};
|
||||
|
||||
AutoPtr make_auto_ptr();
|
||||
|
||||
AutoPtr test_auto_ptr(bool Cond) {
|
||||
AutoPtr p1( make_auto_ptr() );
|
||||
|
||||
AutoPtr p;
|
||||
if (Cond)
|
||||
return p; // expected-error{{incompatible type returning}}
|
||||
|
||||
return AutoPtr();
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue