aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h25
-rw-r--r--lib/Sema/SemaCXXCast.cpp5
-rw-r--r--lib/Sema/SemaDecl.cpp34
-rw-r--r--lib/Sema/SemaDeclCXX.cpp23
-rw-r--r--lib/Sema/SemaExprCXX.cpp20
-rw-r--r--lib/Sema/SemaInit.cpp970
-rw-r--r--lib/Sema/SemaInit.h530
-rw-r--r--lib/Sema/SemaOverload.cpp26
-rw-r--r--lib/Sema/SemaOverload.h21
9 files changed, 1602 insertions, 52 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 6f47cd0bc9..ad903a0816 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -95,7 +95,10 @@ namespace clang {
class CXXBasePaths;
class CXXTemporary;
class LookupResult;
-
+ class InitializedEntity;
+ class InitializationKind;
+ class InitializationSequence;
+
/// BlockSemaInfo - When a block is being parsed, this contains information
/// about the block. It is pointed to from Sema::CurBlock.
struct BlockSemaInfo {
@@ -812,16 +815,6 @@ public:
return NULL;
}
- /// OverloadingResult - Capture the result of performing overload
- /// resolution.
- enum OverloadingResult {
- OR_Success, ///< Overload resolution succeeded.
- OR_No_Viable_Function, ///< No viable function found.
- OR_Ambiguous, ///< Ambiguous candidates found.
- OR_Deleted ///< Overload resoltuion refers to a deleted function.
- };
-
-
/// Subroutines of ActOnDeclarator().
TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
TypeSourceInfo *TInfo);
@@ -1011,6 +1004,8 @@ public:
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
bool Complain);
Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
+ OwningExprResult FixOverloadedFunctionReference(OwningExprResult,
+ FunctionDecl *Fn);
void AddOverloadedCallCandidates(llvm::SmallVectorImpl<NamedDecl*>& Callees,
DeclarationName &UnqualifiedName,
@@ -1854,14 +1849,6 @@ public:
/// it simply returns the passed in expression.
OwningExprResult MaybeBindToTemporary(Expr *E);
- /// InitializationKind - Represents which kind of C++ initialization
- /// [dcl.init] a routine is to perform.
- enum InitializationKind {
- IK_Direct, ///< Direct initialization
- IK_Copy, ///< Copy initialization
- IK_Default ///< Default initialization
- };
-
CXXConstructorDecl *
TryInitializationByConstructor(QualType ClassType,
Expr **Args, unsigned NumArgs,
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index f9138902a6..857241d714 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -864,7 +865,9 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
if (CXXConstructorDecl *Constructor
= Self.TryInitializationByConstructor(DestType, &SrcExpr, 1,
OpRange.getBegin(),
- Sema::IK_Direct)) {
+ InitializationKind::CreateDirect(OpRange.getBegin(),
+ OpRange.getBegin(),
+ OpRange.getEnd()))) {
ConversionDecl = Constructor;
Kind = CastExpr::CK_ConstructorConversion;
return TC_Success;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 96b6c16485..bf6863bbf4 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "Lookup.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTConsumer.h"
@@ -3486,8 +3487,35 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {
Diag(VDecl->getLocation(), diag::err_block_extern_cant_init);
VDecl->setInvalidDecl();
} else if (!VDecl->isInvalidDecl()) {
- if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
- VDecl->getDeclName(), DirectInit))
+ if (VDecl->getType()->isReferenceType()) {
+ InitializedEntity Entity
+ = InitializedEntity::InitializeVariable(VDecl);
+
+ // FIXME: Poor source location information.
+ InitializationKind Kind
+ = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(),
+ SourceLocation(),
+ SourceLocation())
+ : InitializationKind::CreateCopy(VDecl->getLocation(),
+ SourceLocation());
+ InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1);
+ if (InitSeq) {
+ OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind,
+ MultiExprArg(*this, (void**)&Init, 1));
+ if (Result.isInvalid()) {
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ Init = Result.takeAs<Expr>();
+ } else {
+ InitSeq.Diagnose(*this, Entity, Kind, &Init, 1);
+ VDecl->setInvalidDecl();
+ return;
+ }
+
+ } else if (CheckInitializerTypes(Init, DclT, VDecl->getLocation(),
+ VDecl->getDeclName(), DirectInit))
VDecl->setInvalidDecl();
// C++ 3.6.2p2, allow dynamic initialization of static initializers.
@@ -3677,7 +3705,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl,
SourceRange(Var->getLocation(),
Var->getLocation()),
Var->getDeclName(),
- IK_Default,
+ InitializationKind::CreateDefault(Var->getLocation()),
ConstructorArgs);
// FIXME: Location info for the variable initialization?
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 6f8a4f16d3..d977ad6000 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "Lookup.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@@ -1108,7 +1109,8 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args,
NumArgs),
IdLoc,
SourceRange(IdLoc, RParenLoc),
- Member->getDeclName(), IK_Direct,
+ Member->getDeclName(),
+ InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc),
ConstructorArgs);
if (C) {
@@ -1232,7 +1234,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
(void**)Args, NumArgs),
BaseLoc,
SourceRange(BaseLoc, RParenLoc),
- Name, IK_Direct,
+ Name,
+ InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc),
ConstructorArgs);
if (C) {
// Take over the constructor arguments as our own.
@@ -3656,7 +3659,9 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
SourceRange(VDecl->getLocation(),
RParenLoc),
VDecl->getDeclName(),
- IK_Direct,
+ InitializationKind::CreateDirect(VDecl->getLocation(),
+ LParenLoc,
+ RParenLoc),
ConstructorArgs);
if (!Constructor)
RealDecl->setInvalidDecl();
@@ -3692,7 +3697,7 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef,
QualType ClassType,
Expr **Args,
unsigned NumArgs,
- Sema::InitializationKind Kind,
+ InitializationKind Kind,
OverloadCandidateSet &CandidateSet) {
// C++ [dcl.init]p14:
// If the initialization is direct-initialization, or if it is
@@ -3727,10 +3732,12 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef,
else
Constructor = cast<CXXConstructorDecl>(*Con);
- if ((Kind == Sema::IK_Direct) ||
- (Kind == Sema::IK_Copy &&
+ if ((Kind.getKind() == InitializationKind::IK_Direct) ||
+ (Kind.getKind() == InitializationKind::IK_Value) ||
+ (Kind.getKind() == InitializationKind::IK_Copy &&
Constructor->isConvertingConstructor(/*AllowExplicit=*/false)) ||
- (Kind == Sema::IK_Default && Constructor->isDefaultConstructor())) {
+ ((Kind.getKind() == InitializationKind::IK_Default) &&
+ Constructor->isDefaultConstructor())) {
if (ConstructorTmpl)
SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl,
/*ExplicitArgs*/ 0,
@@ -4002,7 +4009,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// real, update the initializer with the resulting function.
if (!ICS) {
if (DiagnoseUseOfDecl(Fn, DeclLoc))
- return true;
+ return true;
Init = FixOverloadedFunctionReference(Init, Fn);
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 16c5275d7d..5e0ce666ea 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "SemaInit.h"
#include "Lookup.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
@@ -225,7 +226,9 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep,
SourceRange(TypeRange.getBegin(),
RParenLoc),
DeclarationName(),
- IK_Direct,
+ InitializationKind::CreateDirect(TypeRange.getBegin(),
+ LParenLoc,
+ RParenLoc),
ConstructorArgs);
if (!Constructor)
@@ -449,12 +452,17 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,
// Skip all the checks.
} else if ((RT = AllocType->getAs<RecordType>()) &&
!AllocType->isAggregateType()) {
+ InitializationKind InitKind = InitializationKind::CreateDefault(TypeLoc);
+ if (NumConsArgs > 0)
+ InitKind = InitializationKind::CreateDirect(TypeLoc,
+ PlacementLParen,
+ PlacementRParen);
Constructor = PerformInitializationByConstructor(
AllocType, move(ConstructorArgs),
TypeLoc,
SourceRange(TypeLoc, ConstructorRParen),
RT->getDecl()->getDeclName(),
- NumConsArgs != 0 ? IK_Direct : IK_Default,
+ InitKind,
ConvertedConstructorArgs);
if (!Constructor)
return ExprError();
@@ -1584,7 +1592,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
OverloadCandidateSet::iterator Best;
switch (Self.BestViableFunction(CandidateSet, Loc, Best)) {
- case Sema::OR_Success:
+ case OR_Success:
// We found a match. Perform the conversions on the arguments and move on.
if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0],
Best->Conversions[0], "converting") ||
@@ -1593,13 +1601,13 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
break;
return false;
- case Sema::OR_No_Viable_Function:
+ case OR_No_Viable_Function:
Self.Diag(Loc, diag::err_typecheck_cond_incompatible_operands)
<< LHS->getType() << RHS->getType()
<< LHS->getSourceRange() << RHS->getSourceRange();
return true;
- case Sema::OR_Ambiguous:
+ case OR_Ambiguous:
Self.Diag(Loc, diag::err_conditional_ambiguous_ovl)
<< LHS->getType() << RHS->getType()
<< LHS->getSourceRange() << RHS->getSourceRange();
@@ -1607,7 +1615,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
// the viable candidates.
break;
- case Sema::OR_Deleted:
+ case OR_Deleted:
assert(false && "Conditional operator has only built-in overloads");
break;
}
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 4b0fc84b30..d2ae906eff 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -15,11 +15,13 @@
//
//===----------------------------------------------------------------------===//
+#include "SemaInit.h"
#include "Sema.h"
#include "clang/Parse/Designator.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
+#include "llvm/Support/ErrorHandling.h"
#include <map>
using namespace clang;
@@ -76,7 +78,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType,
OverloadCandidateSet CandidateSet;
if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined,
CandidateSet,
- true, false, false) != S.OR_Ambiguous)
+ true, false, false) != OR_Ambiguous)
return S.Diag(Init->getSourceRange().getBegin(),
diag::err_typecheck_convert_incompatible)
<< DeclType << Init->getType() << "initializing"
@@ -230,13 +232,20 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+ // FIXME: Poor location information
+ InitializationKind InitKind
+ = InitializationKind::CreateCopy(Init->getLocStart(),
+ SourceLocation());
+ if (DirectInit)
+ InitKind = InitializationKind::CreateDirect(Init->getLocStart(),
+ SourceLocation(),
+ SourceLocation());
CXXConstructorDecl *Constructor
= PerformInitializationByConstructor(DeclType,
MultiExprArg(*this,
(void **)&Init, 1),
InitLoc, Init->getSourceRange(),
- InitEntity,
- DirectInit? IK_Direct : IK_Copy,
+ InitEntity, InitKind,
ConstructorArgs);
if (!Constructor)
return true;
@@ -1875,12 +1884,13 @@ bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) {
if (ClassDecl->hasUserDeclaredConstructor()) {
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
+ // FIXME: Poor location information
CXXConstructorDecl *Constructor
= PerformInitializationByConstructor(Type,
MultiExprArg(*this, 0, 0),
Loc, SourceRange(Loc),
DeclarationName(),
- IK_Direct,
+ InitializationKind::CreateValue(Loc, Loc, Loc),
ConstructorArgs);
if (!Constructor)
return true;
@@ -1908,3 +1918,955 @@ bool Sema::CheckValueInitialization(QualType Type, SourceLocation Loc) {
return false;
}
+
+//===----------------------------------------------------------------------===//
+// Initialization entity
+//===----------------------------------------------------------------------===//
+
+void InitializedEntity::InitDeclLoc() {
+ assert((Kind == EK_Variable || Kind == EK_Parameter || Kind == EK_Member) &&
+ "InitDeclLoc cannot be used with non-declaration entities.");
+
+ if (TypeSourceInfo *DI = VariableOrMember->getTypeSourceInfo()) {
+ TL = DI->getTypeLoc();
+ return;
+ }
+
+ // FIXME: Once we've gone through the effort to create the fake
+ // TypeSourceInfo, should we cache it in the declaration?
+ // (If not, we "leak" it).
+ TypeSourceInfo *DI = VariableOrMember->getASTContext()
+ .CreateTypeSourceInfo(VariableOrMember->getType());
+ DI->getTypeLoc().initialize(VariableOrMember->getLocation());
+ TL = DI->getTypeLoc();
+}
+
+InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context,
+ CXXBaseSpecifier *Base)
+{
+ InitializedEntity Result;
+ Result.Kind = EK_Base;
+ Result.Base = Base;
+ // FIXME: CXXBaseSpecifier should store a TypeLoc.
+ TypeSourceInfo *DI = Context.CreateTypeSourceInfo(Base->getType());
+ DI->getTypeLoc().initialize(Base->getSourceRange().getBegin());
+ Result.TL = DI->getTypeLoc();
+ return Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Initialization sequence
+//===----------------------------------------------------------------------===//
+
+void InitializationSequence::Step::Destroy() {
+ switch (Kind) {
+ case SK_ResolveAddressOfOverloadedFunction:
+ case SK_CastDerivedToBaseRValue:
+ case SK_CastDerivedToBaseLValue:
+ case SK_BindReference:
+ case SK_BindReferenceToTemporary:
+ case SK_UserConversion:
+ case SK_QualificationConversionRValue:
+ case SK_QualificationConversionLValue:
+ break;
+
+ case SK_ConversionSequence:
+ delete ICS;
+ }
+}
+
+void InitializationSequence::AddAddressOverloadResolutionStep(
+ FunctionDecl *Function) {
+ Step S;
+ S.Kind = SK_ResolveAddressOfOverloadedFunction;
+ S.Type = Function->getType();
+ S.Function = Function;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType,
+ bool IsLValue) {
+ Step S;
+ S.Kind = IsLValue? SK_CastDerivedToBaseLValue : SK_CastDerivedToBaseRValue;
+ S.Type = BaseType;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddReferenceBindingStep(QualType T,
+ bool BindingTemporary) {
+ Step S;
+ S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference;
+ S.Type = T;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddUserConversionStep(FunctionDecl *Function) {
+ Step S;
+ S.Kind = SK_UserConversion;
+ S.Type = Function->getResultType().getNonReferenceType();
+ S.Function = Function;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddQualificationConversionStep(QualType Ty,
+ bool IsLValue) {
+ Step S;
+ S.Kind = IsLValue? SK_QualificationConversionLValue
+ : SK_QualificationConversionRValue;
+ S.Type = Ty;
+ Steps.push_back(S);
+}
+
+void InitializationSequence::AddConversionSequenceStep(
+ const ImplicitConversionSequence &ICS,
+ QualType T) {
+ Step S;
+ S.Kind = SK_ConversionSequence;
+ S.Type = T;
+ S.ICS = new ImplicitConversionSequence(ICS);
+ Steps.push_back(S);
+}
+
+void InitializationSequence::SetOverloadFailure(FailureKind Failure,
+ OverloadingResult Result) {
+ SequenceKind = FailedSequence;
+ this->Failure = Failure;
+ this->FailedOverloadResult = Result;
+}
+
+//===----------------------------------------------------------------------===//
+// Attempt initialization
+//===----------------------------------------------------------------------===//
+
+/// \brief Attempt list initialization (C++0x [dcl.init.list])
+static bool TryListInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ InitListExpr *InitList,
+ InitializationSequence &Sequence) {
+ // FIXME: For now, it is safe to assume that list initialization always
+ // works. When we actually perform list initialization, we'll do all of the
+ // necessary checking.
+ // C++0x initializer lists will force us to perform more checking here.
+ return true;
+}
+
+/// \brief Try a reference initialization that involves calling a conversion
+/// function.
+///
+/// FIXME: look intos DRs 656, 896
+static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ bool AllowRValues,
+ InitializationSequence &Sequence) {
+ QualType DestType = Entity.getType().getType();
+ QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+ QualType T1 = cv1T1.getUnqualifiedType();
+ QualType cv2T2 = Initializer->getType();
+ QualType T2 = cv2T2.getUnqualifiedType();
+
+ bool DerivedToBase;
+ assert(!S.CompareReferenceRelationship(Initializer->getLocStart(),
+ T1, T2, DerivedToBase) &&
+ "Must have incompatible references when binding via conversion");
+
+ // Build the candidate set directly in the initialization sequence
+ // structure, so that it will persist if we fail.
+ OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+ CandidateSet.clear();
+
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
+
+ const RecordType *T1RecordType = 0;
+ if (AllowRValues && (T1RecordType = T1->getAs<RecordType>())) {
+ // The type we're converting to is a class type. Enumerate its constructors
+ // to see if there is a suitable conversion.
+ CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
+
+ DeclarationName ConstructorName
+ = S.Context.DeclarationNames.getCXXConstructorName(
+ S.Context.getCanonicalType(T1).getUnqualifiedType());
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = T1RecordDecl->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl
+ = dyn_cast<FunctionTemplateDecl>(*Con);
+ if (ConstructorTmpl)
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ else
+ Constructor = cast<CXXConstructorDecl>(*Con);
+
+ if (!Constructor->isInvalidDecl() &&
+ Constructor->isConvertingConstructor(AllowExplicit)) {
+ if (ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
+ &Initializer, 1, CandidateSet);
+ else
+ S.AddOverloadCandidate(Constructor, &Initializer, 1, CandidateSet);
+ }
+ }
+ }
+
+ if (const RecordType *T2RecordType = T2->getAs<RecordType>()) {
+ // The type we're converting from is a class type, enumerate its conversion
+ // functions.
+ CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl());
+
+ // Determine the type we are converting to. If we are allowed to
+ // convert to an rvalue, take the type that the destination type
+ // refers to.
+ QualType ToType = AllowRValues? cv1T1 : DestType;
+
+ const UnresolvedSet *Conversions
+ = T2RecordDecl->getVisibleConversionFunctions();
+ for (UnresolvedSet::iterator I = Conversions->begin(),
+ E = Conversions->end();
+ I != E; ++I) {
+ NamedDecl *D = *I;
+ CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+ if (isa<UsingShadowDecl>(D))
+ D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+ FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D);
+ CXXConversionDecl *Conv;
+ if (ConvTemplate)
+ Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+ else
+ Conv = cast<CXXConversionDecl>(*I);
+
+ // If the conversion function doesn't return a reference type,
+ // it can't be considered for this conversion unless we're allowed to
+ // consider rvalues.
+ // FIXME: Do we need to make sure that we only consider conversion
+ // candidates with reference-compatible results? That might be needed to
+ // break recursion.
+ if ((AllowExplicit || !Conv->isExplicit()) &&
+ (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
+ if (ConvTemplate)
+ S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, Initializer,
+ ToType, CandidateSet);
+ else
+ S.AddConversionCandidate(Conv, ActingDC, Initializer, cv1T1,
+ CandidateSet);
+ }
+ }
+ }
+
+ SourceLocation DeclLoc = Initializer->getLocStart();
+
+ // Perform overload resolution. If it fails, return the failed result.
+ OverloadCandidateSet::iterator Best;
+ if (OverloadingResult Result
+ = S.BestViableFunction(CandidateSet, DeclLoc, Best))
+ return Result;
+
+ // Add the user-defined conversion step.
+ FunctionDecl *Function = Best->Function;
+ Sequence.AddUserConversionStep(Function);
+
+ // Determine whether we need to perform derived-to-base or
+ // cv-qualification adjustments.
+ if (isa<CXXConversionDecl>(Function))
+ T2 = Function->getResultType();
+ else
+ T2 = cv1T1;
+
+ bool NewDerivedToBase = false;
+ Sema::ReferenceCompareResult NewRefRelationship
+ = S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(),
+ NewDerivedToBase);
+ assert(NewRefRelationship != Sema::Ref_Incompatible &&
+ "Overload resolution picked a bad conversion function");
+ (void)NewRefRelationship;
+ if (NewDerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(
+ S.Context.getQualifiedType(T1,
+ T2.getNonReferenceType().getQualifiers()),
+ /*isLValue=*/true);
+
+ if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers())
+ Sequence.AddQualificationConversionStep(cv1T1, T2->isReferenceType());
+
+ Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType());
+ return OR_Success;
+}
+
+/// \brief Attempt reference initialization (C++0x [dcl.init.list])
+static void TryReferenceInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr *Initializer,
+ InitializationSequence &Sequence) {
+ Sequence.setSequenceKind(InitializationSequence::ReferenceBinding);
+
+ QualType DestType = Entity.getType().getType();
+ QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType();
+ QualType T1 = cv1T1.getUnqualifiedType();
+ QualType cv2T2 = Initializer->getType();
+ QualType T2 = cv2T2.getUnqualifiedType();
+ SourceLocation DeclLoc = Initializer->getLocStart();
+
+ // If the initializer is the address of an overloaded function, try
+ // to resolve the overloaded function. If all goes well, T2 is the
+ // type of the resulting function.
+ if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+ FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer,
+ T1,
+ false);
+ if (!Fn) {
+ Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+ return;
+ }
+
+ Sequence.AddAddressOverloadResolutionStep(Fn);
+ cv2T2 = Fn->getType();
+ T2 = cv2T2.getUnqualifiedType();
+ }
+
+ // FIXME: Rvalue references
+ bool ForceRValue = false;
+
+ // Compute some basic properties of the types and the initializer.
+ bool isLValueRef = DestType->isLValueReferenceType();
+ bool isRValueRef = !isLValueRef;
+ bool DerivedToBase = false;
+ Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
+ Initializer->isLvalue(S.Context);
+ Sema::ReferenceCompareResult RefRelationship
+ = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase);
+
+ // C++0x [dcl.init.ref]p5:
+ // A reference to type "cv1 T1" is initialized by an expression of type
+ // "cv2 T2" as follows:
+ //
+ // - If the reference is an lvalue reference and the initializer
+ // expression
+ OverloadingResult ConvOvlResult = OR_Success;
+ if (isLValueRef) {
+ if (InitLvalue == Expr::LV_Valid &&
+ RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+ // - is an lvalue (but is not a bit-field), and "cv1 T1" is
+ // reference-compatible with "cv2 T2," or
+ //
+ // Per C++ [over.best.ics]p2, we ignore whether the lvalue is a
+ // bit-field when we're determining whether the reference initialization
+ // can occur. This property will be checked by PerformInitialization.
+ if (DerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(
+ S.Context.getQualifiedType(T1, cv2T2.getQualifiers()),
+ /*isLValue=*/true);
+ if (cv1T1.getQualifiers() != cv2T2.getQualifiers())
+ Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true);
+ Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/false);
+ return;
+ }
+
+ // - has a class type (i.e., T2 is a class type), where T1 is not
+ // reference-related to T2, and can be implicitly converted to an
+ // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible
+ // with "cv3 T3" (this conversion is selected by enumerating the
+ // applicable conversion functions (13.3.1.6) and choosing the best
+ // one through overload resolution (13.3)),
+ if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType()) {
+ ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind,
+ Initializer,
+ /*AllowRValues=*/false,
+ Sequence);
+ if (ConvOvlResult == OR_Success)
+ return;
+ }
+ }
+
+ // - Otherwise, the reference shall be an lvalue reference to a
+ // non-volatile const type (i.e., cv1 shall be const), or the reference
+ // shall be an rvalue reference and the initializer expression shall
+ // be an rvalue.
+ if (!((isLValueRef && cv1T1.getCVRQualifiers() == Qualifiers::Const) ||
+ (isRValueRef && InitLvalue != Expr::LV_Valid))) {
+ if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty())
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+ else if (isLValueRef)
+ Sequence.SetFailed(InitLvalue == Expr::LV_Valid
+ ? (RefRelationship == Sema::Ref_Related
+ ? InitializationSequence::FK_ReferenceInitDropsQualifiers
+ : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated)
+ : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
+ else
+ Sequence.SetFailed(
+ InitializationSequence::FK_RValueReferenceBindingToLValue);
+
+ return;
+ }
+
+ // - If T1 and T2 are class types and
+ if (T1->isRecordType() && T2->isRecordType()) {
+ // - the initializer expression is an rvalue and "cv1 T1" is
+ // reference-compatible with "cv2 T2", or
+ if (InitLvalue != Expr::LV_Valid &&
+ RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+ if (DerivedToBase)
+ Sequence.AddDerivedToBaseCastStep(
+ S.Context.getQualifiedType(T1, cv2T2.getQualifiers()),
+ /*isLValue=*/false);
+ if (cv1T1.getQualifiers() != cv2T2.getQualifiers())
+ Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/false);
+ Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true);
+ return;
+ }
+
+ // - T1 is not reference-related to T2 and the initializer expression
+ // can be implicitly converted to an rvalue of type "cv3 T3" (this
+ // conversion is selected by enumerating the applicable conversion
+ // functions (13.3.1.6) and choosing the best one through overload
+ // resolution (13.3)),
+ if (RefRelationship == Sema::Ref_Incompatible) {
+ ConvOvlResult = TryRefInitWithConversionFunction(S, Entity,
+ Kind, Initializer,
+ /*AllowRValues=*/true,
+ Sequence);
+ if (ConvOvlResult)
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+
+ return;
+ }
+
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
+ return;
+ }
+
+ // - If the initializer expression is an rvalue, with T2 an array type,
+ // and "cv1 T1" is reference-compatible with "cv2 T2," the reference
+ // is bound to the object represented by the rvalue (see 3.10).
+ // FIXME: How can an array type be reference-compatible with anything?
+ // Don't we mean the element types of T1 and T2?
+
+ // - Otherwise, a temporary of type “cv1 T1” is created and initialized
+ // from the initializer expression using the rules for a non-reference
+ // copy initialization (8.5). The reference is then bound to the
+ // temporary. [...]
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct);
+ ImplicitConversionSequence ICS
+ = S.TryImplicitConversion(Initializer, cv1T1,
+ /*SuppressUserConversions=*/false, AllowExplicit,
+ /*ForceRValue=*/false,
+ /*FIXME:InOverloadResolution=*/false,
+ /*UserCast=*/Kind.isExplicitCast());
+
+ if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+ // FIXME: Use the conversion function set stored in ICS to turn
+ // this into an overloading ambiguity diagnostic. However, we need
+ // to keep that set as an OverloadCandidateSet rather than as some
+ // other kind of set.
+ Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed);
+ return;
+ }
+
+ // [...] If T1 is reference-related to T2, cv1 must be the
+ // same cv-qualification as, or greater cv-qualification
+ // than, cv2; otherwise, the program is ill-fo