diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-09-23 20:55:32 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-09-23 20:55:32 +0000 |
commit | 51bebc83e74001ed0412d82aadae9eb247fee2d4 (patch) | |
tree | 57a7c5823fb7daed74616f8bb5fbd2020bc2d4d1 | |
parent | f7469a38ca835681a64959d71c4792d93a7b1d00 (diff) |
This patch addresses a few issues related to 8.5.3 [dcl.init.ref]
It uses a recent API to find inherited conversion functions to do
the initializer to reference lvalue conversion (and removes a FIXME).
It issues the ambiguity diagnostics when multiple conversions are found.
WIP.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82649 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 26 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 9 | ||||
-rw-r--r-- | test/SemaCXX/decl-init-ref.cpp | 24 |
5 files changed, 63 insertions, 3 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2ae2cbe009..cc7bb31638 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -476,6 +476,8 @@ def err_destructor_name : Error< // C++ initialization def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">; +def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue " + "due to multiple conversion functions">; // FIXME: passing in an English string as %1! def err_not_reference_to_const_init : Error< "non-const lvalue reference to type %0 cannot be initialized " diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 875da1a1d9..771af4bf0c 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3469,6 +3469,11 @@ public: bool AllowExplicit = false, bool Elidable = false); bool PerformImplicitConversion(Expr *&From, QualType ToType, + const char *Flavor, + bool AllowExplicit, + bool Elidable, + ImplicitConversionSequence& ICS); + bool PerformImplicitConversion(Expr *&From, QualType ToType, const ImplicitConversionSequence& ICS, const char *Flavor); bool PerformImplicitConversion(Expr *&From, QualType ToType, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 1896fb0dc3..a4679e0e28 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3478,7 +3478,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, OverloadCandidateSet CandidateSet; OverloadedFunctionDecl *Conversions - = T2RecordDecl->getConversionFunctions(); + = T2RecordDecl->getVisibleConversionFunctions(); for (OverloadedFunctionDecl::function_iterator Func = Conversions->function_begin(); Func != Conversions->function_end(); ++Func) { @@ -3489,7 +3489,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); else Conv = cast<CXXConversionDecl>(*Func); - + // If the conversion function doesn't return a reference type, // it can't be considered for this conversion. if (Conv->getConversionType()->isLValueReferenceType() && @@ -3688,7 +3688,27 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, } return ICS->ConversionKind == ImplicitConversionSequence::BadConversion; } else { - return PerformImplicitConversion(Init, T1, "initializing"); + ImplicitConversionSequence Conversions; + bool badConversion = PerformImplicitConversion(Init, T1, "initializing", + false, false, + Conversions); + if (badConversion) { + if ((Conversions.ConversionKind == + ImplicitConversionSequence::BadConversion) + && Conversions.ConversionFunctionSet.size() > 0) { + Diag(Init->getSourceRange().getBegin(), + diag::err_lvalue_to_rvalue_ambig_ref) << Init->getSourceRange(); + for (int j = Conversions.ConversionFunctionSet.size()-1; + j >= 0; j--) { + FunctionDecl *Func = Conversions.ConversionFunctionSet[j]; + Diag(Func->getLocation(), diag::err_ovl_candidate); + } + } + else + Diag(Init->getSourceRange().getBegin(), diag::err_lvalue_to_rvalue_ref) + << Init->getSourceRange(); + } + return badConversion; } } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 79909b557d..f500e132de 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -996,6 +996,15 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, const char *Flavor, bool AllowExplicit, bool Elidable) { ImplicitConversionSequence ICS; + return PerformImplicitConversion(From, ToType, Flavor, AllowExplicit, + Elidable, ICS); +} + +bool +Sema::PerformImplicitConversion(Expr *&From, QualType ToType, + const char *Flavor, bool AllowExplicit, + bool Elidable, + ImplicitConversionSequence& ICS) { ICS.ConversionKind = ImplicitConversionSequence::BadConversion; if (Elidable && getLangOptions().CPlusPlus0x) { ICS = TryImplicitConversion(From, ToType, diff --git a/test/SemaCXX/decl-init-ref.cpp b/test/SemaCXX/decl-init-ref.cpp new file mode 100644 index 0000000000..a87c0efae2 --- /dev/null +++ b/test/SemaCXX/decl-init-ref.cpp @@ -0,0 +1,24 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s + +struct A {}; // expected-note {{candidate function}} + +struct BASE { + operator A(); // expected-note {{candidate function}} +}; + +struct BASE1 { + operator A(); // expected-note {{candidate function}} +}; + +class B : public BASE , public BASE1 +{ + public: + B(); +} b; + +extern B f(); + +int main() { + const A& rca = f(); // expected-error {{rvalue reference cannot bind to lvalue due to multiple conversion functions}} + A& ra = f(); // expected-error {{non-const lvalue reference to type 'struct A' cannot be initialized with a temporary of type 'class B'}} +} |