[cfe-commits] r58988 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp test/SemaCXX/user-defined-conversions.cpp
Douglas Gregor
doug.gregor at gmail.com
Mon Nov 10 08:14:25 PST 2008
Author: dgregor
Date: Mon Nov 10 10:14:15 2008
New Revision: 58988
URL: http://llvm.org/viewvc/llvm-project?rev=58988&view=rev
Log:
Allow user-defined conversions during reference binding
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaCXX/user-defined-conversions.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=58988&r1=58987&r2=58988&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Nov 10 10:14:15 2008
@@ -1591,9 +1591,69 @@
// 92) (this conversion is selected by enumerating the
// applicable conversion functions (13.3.1.6) and choosing
// the best one through overload resolution (13.3)),
- // FIXME: Implement this second bullet, once we have conversion
- // functions. Also remember C++ [over.ics.ref]p1, second part.
+ if (!SuppressUserConversions && T2->isRecordType()) {
+ // FIXME: Look for conversions in base classes!
+ CXXRecordDecl *T2RecordDecl
+ = dyn_cast<CXXRecordDecl>(T2->getAsRecordType()->getDecl());
+
+ OverloadCandidateSet CandidateSet;
+ OverloadedFunctionDecl *Conversions
+ = T2RecordDecl->getConversionFunctions();
+ for (OverloadedFunctionDecl::function_iterator Func
+ = Conversions->function_begin();
+ Func != Conversions->function_end(); ++Func) {
+ CXXConversionDecl *Conv = cast<CXXConversionDecl>(*Func);
+
+ // If the conversion function doesn't return a reference type,
+ // it can't be considered for this conversion.
+ // FIXME: This will change when we support rvalue references.
+ if (Conv->getConversionType()->isReferenceType())
+ AddConversionCandidate(Conv, Init, DeclType, CandidateSet);
+ }
+
+ OverloadCandidateSet::iterator Best;
+ switch (BestViableFunction(CandidateSet, Best)) {
+ case OR_Success:
+ // This is a direct binding.
+ BindsDirectly = true;
+
+ if (ICS) {
+ // C++ [over.ics.ref]p1:
+ //
+ // [...] If the parameter binds directly to the result of
+ // applying a conversion function to the argument
+ // expression, the implicit conversion sequence is a
+ // user-defined conversion sequence (13.3.3.1.2), with the
+ // second standard conversion sequence either an identity
+ // conversion or, if the conversion function returns an
+ // entity of a type that is a derived class of the parameter
+ // type, a derived-to-base Conversion.
+ ICS->ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
+ ICS->UserDefined.Before = Best->Conversions[0].Standard;
+ ICS->UserDefined.After = Best->FinalConversion;
+ ICS->UserDefined.ConversionFunction = Best->Function;
+ assert(ICS->UserDefined.After.ReferenceBinding &&
+ ICS->UserDefined.After.DirectBinding &&
+ "Expected a direct reference binding!");
+ return false;
+ } else {
+ // Perform the conversion.
+ // FIXME: Binding to a subobject of the lvalue is going to require
+ // more AST annotation than this.
+ ImpCastExprToType(Init, T1);
+ }
+ break;
+ case OR_Ambiguous:
+ assert(false && "Ambiguous reference binding conversions not implemented.");
+ return true;
+
+ case OR_No_Viable_Function:
+ // There was no suitable conversion; continue with other checks.
+ break;
+ }
+ }
+
if (BindsDirectly) {
// C++ [dcl.init.ref]p4:
// [...] In all cases where the reference-related or
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=58988&r1=58987&r2=58988&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/user-defined-conversions.cpp (original)
+++ cfe/trunk/test/SemaCXX/user-defined-conversions.cpp Mon Nov 10 10:14:15 2008
@@ -19,4 +19,19 @@
void g_test(Y y) {
g(y);
+ short s;
+ s = y;
+}
+
+struct A { };
+struct B : A { };
+
+struct C {
+ operator B&();
+};
+
+// Test reference binding via an lvalue conversion function.
+void h(volatile A&);
+void h_test(C c) {
+ h(c);
}
More information about the cfe-commits
mailing list