[cfe-commits] r101680 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaCXX/aggregate-initialization.cpp test/SemaCXX/conditional-expr.cpp test/SemaCXX/conversion-function.cpp test/SemaCXX/copy-initialization.cpp test/SemaCXX/user-defined-conversions.cpp test/SemaTemplate/constructor-template.cpp
Douglas Gregor
dgregor at apple.com
Sat Apr 17 15:01:05 PDT 2010
Author: dgregor
Date: Sat Apr 17 17:01:05 2010
New Revision: 101680
URL: http://llvm.org/viewvc/llvm-project?rev=101680&view=rev
Log:
Improve our handling of user-defined conversions as part of overload
resolution. There are two sources of problems involving user-defined
conversions that this change eliminates, along with providing simpler
interfaces for checking implicit conversions:
- It eliminates a case of infinite recursion found in Boost.
- It eliminates the search for the constructor needed to copy a temporary
generated by an implicit conversion from overload
resolution. Overload resolution assumes that, if it gets a value
of the parameter's class type (or a derived class thereof), there
is a way to copy if... even if there isn't. We now model this
properly.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaOverload.h
cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
cfe/trunk/test/SemaCXX/conditional-expr.cpp
cfe/trunk/test/SemaCXX/conversion-function.cpp
cfe/trunk/test/SemaCXX/copy-initialization.cpp
cfe/trunk/test/SemaCXX/user-defined-conversions.cpp
cfe/trunk/test/SemaTemplate/constructor-template.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Apr 17 17:01:05 2010
@@ -692,17 +692,20 @@
InGroup<DiagGroup<"uninitialized">>;
def err_temp_copy_no_viable : Error<
- "no viable copy constructor %select{copying variable|copying parameter|"
+ "no viable constructor %select{copying variable|copying parameter|"
"returning object|throwing object|copying member subobject|copying array "
- "element}0 of type %1">;
+ "element|allocating object|copying temporary|initializing base subobject|"
+ "initializing vector element}0 of type %1">;
def err_temp_copy_ambiguous : Error<
- "ambiguous copy constructor call when %select{copying variable|copying "
+ "ambiguous constructor call when %select{copying variable|copying "
"parameter|returning object|throwing object|copying member subobject|copying "
- "array element}0 of type %1">;
+ "array element|allocating object|copying temporary|initializing base subobject|"
+ "initializing vector element}0 of type %1">;
def err_temp_copy_deleted : Error<
"%select{copying variable|copying parameter|returning object|throwing "
- "object|copying member subobject|copying array element}0 of type %1 invokes "
- "deleted copy constructor">;
+ "object|copying member subobject|copying array element|allocating object|"
+ "copying temporary|initializing base subobject|initializing vector element}0 "
+ "of type %1 invokes deleted constructor">;
// C++0x decltype
def err_cannot_determine_declared_type_of_overloaded_function : Error<
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Apr 17 17:01:05 2010
@@ -1064,8 +1064,7 @@
TryImplicitConversion(Expr* From, QualType ToType,
bool SuppressUserConversions,
bool AllowExplicit,
- bool InOverloadResolution,
- bool UserCast = false);
+ bool InOverloadResolution);
bool IsStandardConversion(Expr *From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence& SCS);
@@ -1090,9 +1089,7 @@
OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
OverloadCandidateSet& Conversions,
- bool AllowConversionFunctions,
- bool AllowExplicit,
- bool UserCast);
+ bool AllowExplicit);
bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Apr 17 17:01:05 2010
@@ -2531,8 +2531,7 @@
ImplicitConversionSequence ICS
= S.TryImplicitConversion(Initializer, cv1T1,
/*SuppressUserConversions=*/false, AllowExplicit,
- /*FIXME:InOverloadResolution=*/false,
- /*UserCast=*/Kind.isExplicitCast());
+ /*FIXME:InOverloadResolution=*/false);
if (ICS.isBad()) {
// FIXME: Use the conversion function set stored in ICS to turn
@@ -2867,10 +2866,21 @@
// Add the user-defined conversion step that calls the conversion function.
QualType ConvType = Function->getResultType().getNonReferenceType();
- Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType);
+ if (ConvType->getAs<RecordType>()) {
+ // If we're converting to a class type, there may be an copy if
+ // the resulting temporary object (possible to create an object of
+ // a base class type). That copy is not a separate conversion, so
+ // we just make a note of the actual destination type (possibly a
+ // base class of the type returned by the conversion function) and
+ // let the user-defined conversion step handle the conversion.
+ Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType);
+ return;
+ }
- // If the conversion following the call to the conversion function is
- // interesting, add it as a separate step.
+ Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType);
+
+ // If the conversion following the call to the conversion function
+ // is interesting, add it as a separate step.
if (Best->FinalConversion.First || Best->FinalConversion.Second ||
Best->FinalConversion.Third) {
ImplicitConversionSequence ICS;
@@ -2891,8 +2901,7 @@
= S.TryImplicitConversion(Initializer, Entity.getType(),
/*SuppressUserConversions=*/true,
/*AllowExplicit=*/false,
- /*FIXME:InOverloadResolution=*/false,
- /*UserCast=*/Kind.isExplicitCast());
+ /*InOverloadResolution=*/false);
if (ICS.isBad()) {
Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
@@ -3103,10 +3112,11 @@
const InitializedEntity &Entity,
const InitializationKind &Kind,
Sema::OwningExprResult CurInit) {
- // Determine which class type we're copying.
+ // Determine which class type we're copying to.
Expr *CurInitExpr = (Expr *)CurInit.get();
CXXRecordDecl *Class = 0;
- if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>())
+ if (const RecordType *Record
+ = Entity.getType().getNonReferenceType()->getAs<RecordType>())
Class = cast<CXXRecordDecl>(Record->getDecl());
if (!Class)
return move(CurInit);
@@ -3203,16 +3213,26 @@
return S.ExprError();
}
- S.CheckConstructorAccess(Loc,
- cast<CXXConstructorDecl>(Best->Function),
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
+ ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+ CurInit.release(); // Ownership transferred into MultiExprArg, below.
+
+ // Determine the arguments required to actually perform the
+ // constructor call (we might have derived-to-base conversions).
+ if (S.CompleteConstructorCall(Constructor,
+ Sema::MultiExprArg(S,
+ (void **)&CurInitExpr,
+ 1),
+ Loc, ConstructorArgs))
+ return S.ExprError();
+
+ S.CheckConstructorAccess(Loc, Constructor,
Best->FoundDecl.getAccess());
- CurInit.release();
return S.BuildCXXConstructExpr(Loc, Entity.getType().getNonReferenceType(),
- cast<CXXConstructorDecl>(Best->Function),
+ Constructor,
Elidable,
- Sema::MultiExprArg(S,
- (void**)&CurInitExpr, 1));
+ move_arg(ConstructorArgs));
}
Action::OwningExprResult
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat Apr 17 17:01:05 2010
@@ -436,14 +436,11 @@
/// not permitted.
/// If @p AllowExplicit, then explicit user-defined conversions are
/// permitted.
-/// If @p UserCast, the implicit conversion is being done for a user-specified
-/// cast.
ImplicitConversionSequence
Sema::TryImplicitConversion(Expr* From, QualType ToType,
bool SuppressUserConversions,
bool AllowExplicit,
- bool InOverloadResolution,
- bool UserCast) {
+ bool InOverloadResolution) {
ImplicitConversionSequence ICS;
if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) {
ICS.setStandard();
@@ -455,11 +452,47 @@
return ICS;
}
+ if (SuppressUserConversions) {
+ // C++ [over.ics.user]p4:
+ // A conversion of an expression of class type to the same class
+ // type is given Exact Match rank, and a conversion of an
+ // expression of class type to a base class of that type is
+ // given Conversion rank, in spite of the fact that a copy/move
+ // constructor (i.e., a user-defined conversion function) is
+ // called for those cases.
+ QualType FromType = From->getType();
+ if (!ToType->getAs<RecordType>() || !FromType->getAs<RecordType>() ||
+ !(Context.hasSameUnqualifiedType(FromType, ToType) ||
+ IsDerivedFrom(FromType, ToType))) {
+ // We're not in the case above, so there is no conversion that
+ // we can perform.
+ ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
+ return ICS;
+ }
+
+ ICS.setStandard();
+ ICS.Standard.setAsIdentityConversion();
+ ICS.Standard.setFromType(FromType);
+ ICS.Standard.setAllToTypes(ToType);
+
+ // We don't actually check at this point whether there is a valid
+ // copy/move constructor, since overloading just assumes that it
+ // exists. When we actually perform initialization, we'll find the
+ // appropriate constructor to copy the returned object, if needed.
+ ICS.Standard.CopyConstructor = 0;
+
+ // Determine whether this is considered a derived-to-base conversion.
+ if (!Context.hasSameUnqualifiedType(FromType, ToType))
+ ICS.Standard.Second = ICK_Derived_To_Base;
+
+ return ICS;
+ }
+
+ // Attempt user-defined conversion.
OverloadCandidateSet Conversions(From->getExprLoc());
OverloadingResult UserDefResult
= IsUserDefinedConversion(From, ToType, ICS.UserDefined, Conversions,
- !SuppressUserConversions, AllowExplicit,
- UserCast);
+ AllowExplicit);
if (UserDefResult == OR_Success) {
ICS.setUserDefined();
@@ -1509,45 +1542,39 @@
/// and this routine will return true. Otherwise, this routine returns
/// false and User is unspecified.
///
-/// \param AllowConversionFunctions true if the conversion should
-/// consider conversion functions at all. If false, only constructors
-/// will be considered.
-///
/// \param AllowExplicit true if the conversion should consider C++0x
/// "explicit" conversion functions as well as non-explicit conversion
/// functions (C++0x [class.conv.fct]p2).
-///
-/// \param UserCast true if looking for user defined conversion for a static
-/// cast.
OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
- OverloadCandidateSet& CandidateSet,
- bool AllowConversionFunctions,
- bool AllowExplicit,
- bool UserCast) {
+ OverloadCandidateSet& CandidateSet,
+ bool AllowExplicit) {
+ // Whether we will only visit constructors.
+ bool ConstructorsOnly = false;
+
+ // If the type we are conversion to is a class type, enumerate its
+ // constructors.
if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
+ // C++ [over.match.ctor]p1:
+ // When objects of class type are direct-initialized (8.5), or
+ // copy-initialized from an expression of the same or a
+ // derived class type (8.5), overload resolution selects the
+ // constructor. [...] For copy-initialization, the candidate
+ // 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.
+ if (Context.hasSameUnqualifiedType(ToType, From->getType()) ||
+ (From->getType()->getAs<RecordType>() &&
+ IsDerivedFrom(From->getType(), ToType)))
+ ConstructorsOnly = true;
+
if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) {
// We're not going to find any constructors.
} else if (CXXRecordDecl *ToRecordDecl
= dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
- // C++ [over.match.ctor]p1:
- // When objects of class type are direct-initialized (8.5), or
- // copy-initialized from an expression of the same or a
- // derived class type (8.5), overload resolution selects the
- // constructor. [...] For copy-initialization, the candidate
- // 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());
+ Context.getCanonicalType(ToType).getUnqualifiedType());
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd)
= ToRecordDecl->lookup(ConstructorName);
@@ -1571,26 +1598,25 @@
AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
&From, 1, CandidateSet,
- SuppressUserConversions);
+ /*SuppressUserConversions=*/!ConstructorsOnly);
else
// Allow one user-defined conversion when user specifies a
// From->ToType conversion via an static cast (c-style, etc).
AddOverloadCandidate(Constructor, FoundDecl,
&From, 1, CandidateSet,
- SuppressUserConversions);
+ /*SuppressUserConversions=*/!ConstructorsOnly);
}
}
}
}
- if (!AllowConversionFunctions) {
- // Don't allow any conversion functions to enter the overload set.
+ // Enumerate conversion functions, if we're allowed to.
+ if (ConstructorsOnly) {
} else if (RequireCompleteType(From->getLocStart(), From->getType(),
- PDiag(0)
- << From->getSourceRange())) {
+ PDiag(0) << From->getSourceRange())) {
// No conversion functions from incomplete types.
} else if (const RecordType *FromRecordType
- = From->getType()->getAs<RecordType>()) {
+ = From->getType()->getAs<RecordType>()) {
if (CXXRecordDecl *FromRecordDecl
= dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) {
// Add all of the conversion functions as candidates.
@@ -1696,7 +1722,7 @@
OverloadCandidateSet CandidateSet(From->getExprLoc());
OverloadingResult OvResult =
IsUserDefinedConversion(From, ToType, ICS.UserDefined,
- CandidateSet, true, false, false);
+ CandidateSet, false);
if (OvResult == OR_Ambiguous)
Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_ambiguous_condition)
@@ -1732,16 +1758,10 @@
// described in 13.3.3.2, the ambiguous conversion sequence is
// treated as a user-defined sequence that is indistinguishable
// from any other user-defined conversion sequence.
- if (ICS1.getKind() < ICS2.getKind()) {
- if (!(ICS1.isUserDefined() && ICS2.isAmbiguous()))
- return ImplicitConversionSequence::Better;
- } else if (ICS2.getKind() < ICS1.getKind()) {
- if (!(ICS2.isUserDefined() && ICS1.isAmbiguous()))
- return ImplicitConversionSequence::Worse;
- }
-
- if (ICS1.isAmbiguous() || ICS2.isAmbiguous())
- return ImplicitConversionSequence::Indistinguishable;
+ if (ICS1.getKindRank() < ICS2.getKindRank())
+ return ImplicitConversionSequence::Better;
+ else if (ICS2.getKindRank() < ICS1.getKindRank())
+ return ImplicitConversionSequence::Worse;
// Two implicit conversion sequences of the same form are
// indistinguishable conversion sequences unless one of the
@@ -2167,9 +2187,7 @@
}
}
- if ((SCS1.ReferenceBinding || SCS1.CopyConstructor) &&
- (SCS2.ReferenceBinding || SCS2.CopyConstructor) &&
- SCS1.Second == ICK_Derived_To_Base) {
+ if (SCS1.Second == ICK_Derived_To_Base) {
// -- conversion of C to B is better than conversion of C to A,
// -- binding of an expression of type C to a reference of type
// B& is better than binding an expression of type C to a
@@ -3067,7 +3085,7 @@
OverloadCandidateSet& CandidateSet) {
assert(!Conversion->getDescribedFunctionTemplate() &&
"Conversion function templates use AddTemplateConversionCandidate");
-
+ QualType ConvType = Conversion->getConversionType().getNonReferenceType();
if (!CandidateSet.isNewCandidate(Conversion))
return;
@@ -3082,7 +3100,7 @@
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.FinalConversion.setAsIdentityConversion();
- Candidate.FinalConversion.setFromType(Conversion->getConversionType());
+ Candidate.FinalConversion.setFromType(ConvType);
Candidate.FinalConversion.setAllToTypes(ToType);
// Determine the implicit conversion sequence for the implicit
@@ -3115,7 +3133,6 @@
return;
}
-
// To determine what the conversion from the result of calling the
// conversion function to the type we're eventually trying to
// convert to (ToType), we need to synthesize a call to the
Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Sat Apr 17 17:01:05 2010
@@ -381,6 +381,33 @@
assert(isInitialized() && "querying uninitialized conversion");
return Kind(ConversionKind);
}
+
+ /// \brief Return a ranking of the implicit conversion sequence
+ /// kind, where smaller ranks represent better conversion
+ /// sequences.
+ ///
+ /// In particular, this routine gives user-defined conversion
+ /// sequences and ambiguous conversion sequences the same rank,
+ /// per C++ [over.best.ics]p10.
+ unsigned getKindRank() const {
+ switch (getKind()) {
+ case StandardConversion:
+ return 0;
+
+ case UserDefinedConversion:
+ case AmbiguousConversion:
+ return 1;
+
+ case EllipsisConversion:
+ return 2;
+
+ case BadConversion:
+ return 3;
+ }
+
+ return 3;
+ }
+
bool isBad() const { return getKind() == BadConversion; }
bool isStandard() const { return getKind() == StandardConversion; }
bool isEllipsis() const { return getKind() == EllipsisConversion; }
Modified: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp Sat Apr 17 17:01:05 2010
@@ -60,10 +60,10 @@
void f() {
A as1[1] = { };
- A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted copy constructor}}
+ A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted constructor}}
B b1 = { };
- B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted copy constructor}}
+ B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted constructor}}
C c1 = { 1 };
}
Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Sat Apr 17 17:01:05 2010
@@ -224,7 +224,7 @@
struct Foo3 {
Foo3();
- Foo3(Foo3&);
+ Foo3(Foo3&); // expected-note{{would lose const qualifier}}
};
struct Bar {
@@ -236,7 +236,6 @@
void f() {
(void)(true ? Bar() : Foo1()); // okay
(void)(true ? Bar() : Foo2()); // okay
- // FIXME: Diagnostic below could be improved
- (void)(true ? Bar() : Foo3()); // expected-error{{incompatible operand types ('PR6757::Bar' and 'PR6757::Foo3')}}
+ (void)(true ? Bar() : Foo3()); // expected-error{{no viable constructor copying temporary}}
}
}
Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/conversion-function.cpp Sat Apr 17 17:01:05 2010
@@ -129,7 +129,7 @@
};
A1 f() {
- return "Hello"; // expected-error{{invokes deleted copy constructor}}
+ return "Hello"; // expected-error{{invokes deleted constructor}}
}
namespace source_locations {
@@ -176,3 +176,29 @@
*operator int(); // expected-error {{must use a typedef to declare a conversion to 'int *'}}
};
}
+
+namespace smart_ptr {
+ class Y {
+ class YRef { };
+
+ Y(Y&);
+
+ public:
+ Y();
+ Y(YRef);
+
+ operator YRef(); // expected-note{{candidate function}}
+ };
+
+ struct X { // expected-note{{candidate constructor (the implicit copy constructor) not}}
+ explicit X(Y);
+ };
+
+ Y make_Y();
+
+ X f() {
+ X x = make_Y(); // expected-error{{no viable conversion from 'smart_ptr::Y' to 'smart_ptr::X'}}
+ X x2(make_Y());
+ return X(Y());
+ }
+}
Modified: cfe/trunk/test/SemaCXX/copy-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/copy-initialization.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/copy-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/copy-initialization.cpp Sat Apr 17 17:01:05 2010
@@ -25,19 +25,17 @@
namespace PR6757 {
struct Foo {
Foo();
- Foo(Foo&);
+ Foo(Foo&); // expected-note{{candidate constructor not viable}}
};
struct Bar {
operator const Foo&() const;
};
- void f(Foo); // expected-note{{candidate function not viable: no known conversion from 'PR6757::Bar' to 'PR6757::Foo' for 1st argument}}
+ void f(Foo);
- // FIXME: This isn't really the right reason for the failure. We
- // should fail after overload resolution.
void g(Foo foo) {
- f(Bar()); // expected-error{{no matching function for call to 'f'}}
+ f(Bar()); // expected-error{{no viable constructor copying parameter of type 'PR6757::Foo const'}}
f(foo);
}
}
Modified: cfe/trunk/test/SemaCXX/user-defined-conversions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/user-defined-conversions.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/user-defined-conversions.cpp (original)
+++ cfe/trunk/test/SemaCXX/user-defined-conversions.cpp Sat Apr 17 17:01:05 2010
@@ -67,3 +67,18 @@
Base b4(ctd);
Base b5 = ctfd;
}
+
+struct X1 {
+ X1(X1&); // expected-note{{candidate constructor not viable: no known conversion from 'X1' to 'X1 &' for 1st argument}}
+};
+
+struct X2 {
+ operator X1();
+};
+
+int &f(X1);
+float &f(...);
+
+void g(X2 b) {
+ int &ir = f(b); // expected-error{{no viable constructor copying parameter of type 'X1'}}
+}
Modified: cfe/trunk/test/SemaTemplate/constructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/constructor-template.cpp?rev=101680&r1=101679&r2=101680&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/constructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/constructor-template.cpp Sat Apr 17 17:01:05 2010
@@ -94,3 +94,18 @@
}
template void default_ctor_inst<int>();
+
+template<typename T>
+struct X5 {
+ X5();
+ X5(const T &);
+};
+
+struct X6 {
+ template<typename T> X6(T);
+};
+
+void test_X5_X6() {
+ X5<X6> tf;
+ X5<X6> tf2(tf);
+}
More information about the cfe-commits
mailing list