Remember the "found declaration" for an overload candidate, which is the

entity (if applicable) which was actually looked up.  If a candidate was found
via a using declaration, this is the UsingShadowDecl;  otherwise, if
the candidate is template specialization, this is the template;  otherwise,
this is the function.

The point of this exercise is that "found declarations" are the entities
we do access control for, not their underlying declarations.  Broadly speaking,
this patch fixes access control for using declarations.

There is a *lot* of redundant code calling into the overload-resolution APIs;
we really ought to clean that up.

llvm-svn: 98945
This commit is contained in:
John McCall 2010-03-19 07:35:19 +00:00
parent 3cab275783
commit a0296f7987
10 changed files with 225 additions and 201 deletions

View File

@ -94,6 +94,7 @@ public:
NamedDecl *getDecl() const { return ir->getDecl(); }
AccessSpecifier getAccess() const { return ir->getAccess(); }
DeclAccessPair getPair() const { return *ir; }
NamedDecl *operator*() const { return getDecl(); }

View File

@ -321,6 +321,14 @@ public:
Diag(0) {
}
AccessedEntity(MemberNonce _,
CXXRecordDecl *NamingClass,
DeclAccessPair FoundDecl)
: Access(FoundDecl.getAccess()), IsMember(true),
Target(FoundDecl.getDecl()), NamingClass(NamingClass),
Diag(0) {
}
AccessedEntity(BaseNonce _,
CXXRecordDecl *BaseClass,
CXXRecordDecl *DerivedClass,
@ -1131,12 +1139,12 @@ public:
typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
void AddOverloadCandidate(NamedDecl *Function,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet);
void AddOverloadCandidate(FunctionDecl *Function,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
@ -1146,20 +1154,21 @@ public:
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false);
void AddMethodCandidate(NamedDecl *Decl, AccessSpecifier Access,
void AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversion = false,
bool ForceRValue = false);
void AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access,
void AddMethodCandidate(CXXMethodDecl *Method,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool ForceRValue = false);
void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
@ -1168,24 +1177,24 @@ public:
bool SuppressUserConversions = false,
bool ForceRValue = false);
void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool ForceRValue = false);
void AddConversionCandidate(CXXConversionDecl *Conversion,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet);
void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet);
void AddSurrogateCandidate(CXXConversionDecl *Conversion,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
QualType ObjectTy, Expr **Args, unsigned NumArgs,
@ -2623,16 +2632,13 @@ public:
AccessSpecifier LexicalAS);
AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
NamedDecl *D,
AccessSpecifier Access);
DeclAccessPair FoundDecl);
AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
NamedDecl *D,
AccessSpecifier Access);
DeclAccessPair FoundDecl);
AccessResult CheckAllocationAccess(SourceLocation OperatorLoc,
SourceRange PlacementRange,
CXXRecordDecl *NamingClass,
NamedDecl *Allocator,
AccessSpecifier Access);
DeclAccessPair FoundDecl);
AccessResult CheckConstructorAccess(SourceLocation Loc,
CXXConstructorDecl *D,
AccessSpecifier Access);
@ -2645,8 +2651,7 @@ public:
AccessResult CheckMemberOperatorAccess(SourceLocation Loc,
Expr *ObjectExpr,
Expr *ArgExpr,
NamedDecl *D,
AccessSpecifier Access);
DeclAccessPair FoundDecl);
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
QualType Base, QualType Derived,
const CXXBasePath &Path,

View File

@ -527,15 +527,13 @@ void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) {
}
Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
NamedDecl *D,
AccessSpecifier Access) {
DeclAccessPair Found) {
if (!getLangOptions().AccessControl ||
!E->getNamingClass() ||
Access == AS_public)
Found.getAccess() == AS_public)
return AR_accessible;
AccessedEntity Entity(AccessedEntity::Member,
E->getNamingClass(), Access, D);
AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found);
Entity.setDiag(diag::err_access) << E->getSourceRange();
return CheckAccess(*this, E->getNameLoc(), Entity);
@ -544,14 +542,12 @@ Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
/// Perform access-control checking on a previously-unresolved member
/// access which has now been resolved to a member.
Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
NamedDecl *D,
AccessSpecifier Access) {
DeclAccessPair Found) {
if (!getLangOptions().AccessControl ||
Access == AS_public)
Found.getAccess() == AS_public)
return AR_accessible;
AccessedEntity Entity(AccessedEntity::Member,
E->getNamingClass(), Access, D);
AccessedEntity Entity(AccessedEntity::Member, E->getNamingClass(), Found);
Entity.setDiag(diag::err_access) << E->getSourceRange();
return CheckAccess(*this, E->getMemberLoc(), Entity);
@ -569,7 +565,8 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc,
return AR_accessible;
CXXRecordDecl *NamingClass = Dtor->getParent();
AccessedEntity Entity(AccessedEntity::Member, NamingClass, Access, Dtor);
AccessedEntity Entity(AccessedEntity::Member, NamingClass,
DeclAccessPair::make(Dtor, Access));
Entity.setDiag(PDiag); // TODO: avoid copy
return CheckAccess(*this, Loc, Entity);
@ -584,8 +581,8 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc,
return AR_accessible;
CXXRecordDecl *NamingClass = Constructor->getParent();
AccessedEntity Entity(AccessedEntity::Member,
NamingClass, Access, Constructor);
AccessedEntity Entity(AccessedEntity::Member, NamingClass,
DeclAccessPair::make(Constructor, Access));
Entity.setDiag(diag::err_access_ctor);
return CheckAccess(*this, UseLoc, Entity);
@ -602,7 +599,8 @@ Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
return AR_accessible;
CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext());
AccessedEntity Entity(AccessedEntity::Member, NamingClass, Access, Target);
AccessedEntity Entity(AccessedEntity::Member, NamingClass,
DeclAccessPair::make(Target, Access));
Entity.setDiag(Diag);
return CheckAccess(*this, UseLoc, Entity);
}
@ -612,14 +610,13 @@ Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc,
Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
SourceRange PlacementRange,
CXXRecordDecl *NamingClass,
NamedDecl *Fn,
AccessSpecifier Access) {
DeclAccessPair Found) {
if (!getLangOptions().AccessControl ||
!NamingClass ||
Access == AS_public)
Found.getAccess() == AS_public)
return AR_accessible;
AccessedEntity Entity(AccessedEntity::Member, NamingClass, Access, Fn);
AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found);
Entity.setDiag(diag::err_access)
<< PlacementRange;
@ -631,18 +628,16 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc,
Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
Expr *ObjectExpr,
Expr *ArgExpr,
NamedDecl *MemberOperator,
AccessSpecifier Access) {
DeclAccessPair Found) {
if (!getLangOptions().AccessControl ||
Access == AS_public)
Found.getAccess() == AS_public)
return AR_accessible;
const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>();
assert(RT && "found member operator but object expr not of record type");
CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl());
AccessedEntity Entity(AccessedEntity::Member,
NamingClass, Access, MemberOperator);
AccessedEntity Entity(AccessedEntity::Member, NamingClass, Found);
Entity.setDiag(diag::err_access)
<< ObjectExpr->getSourceRange()
<< (ArgExpr ? ArgExpr->getSourceRange() : SourceRange());
@ -694,7 +689,8 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
if (I.getAccess() != AS_public) {
AccessedEntity Entity(AccessedEntity::Member,
R.getNamingClass(), I.getAccess(), *I);
R.getNamingClass(),
I.getPair());
Entity.setDiag(diag::err_access);
CheckAccess(*this, R.getNameLoc(), Entity);

View File

@ -2253,7 +2253,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
Results.push_back(ResultCandidate(FDecl));
else
// FIXME: access?
AddOverloadCandidate(FDecl, AS_none, Args, NumArgs, CandidateSet,
AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
Args, NumArgs, CandidateSet,
false, false, /*PartialOverloading*/ true);
}
}

View File

@ -4204,6 +4204,8 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef,
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName);
Con != ConEnd; ++Con) {
DeclAccessPair FoundDecl = DeclAccessPair::make(*Con, (*Con)->getAccess());
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl= dyn_cast<FunctionTemplateDecl>(*Con);
@ -4220,12 +4222,11 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef,
((Kind.getKind() == InitializationKind::IK_Default) &&
Constructor->isDefaultConstructor())) {
if (ConstructorTmpl)
SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl,
ConstructorTmpl->getAccess(),
SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
Args, NumArgs, CandidateSet);
else
SemaRef.AddOverloadCandidate(Constructor, Constructor->getAccess(),
SemaRef.AddOverloadCandidate(Constructor, FoundDecl,
Args, NumArgs, CandidateSet);
}
}
@ -4535,10 +4536,10 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
if (Conv->getConversionType()->isLValueReferenceType() &&
(AllowExplicit || !Conv->isExplicit())) {
if (ConvTemplate)
AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), ActingDC,
AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
Init, DeclType, CandidateSet);
else
AddConversionCandidate(Conv, I.getAccess(), ActingDC, Init,
AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
DeclType, CandidateSet);
}
}

View File

@ -921,7 +921,9 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
}
FoundDelete.suppressDiagnostics();
UnresolvedSet<4> Matches;
llvm::SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches;
if (NumPlaceArgs > 0) {
// C++ [expr.new]p20:
// A declaration of a placement deallocation function matches the
@ -964,7 +966,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl());
if (Context.hasSameType(Fn->getType(), ExpectedFunctionType))
Matches.addDecl(Fn, D.getAccess());
Matches.push_back(std::make_pair(D.getPair(), Fn));
}
} else {
// C++ [expr.new]p20:
@ -975,7 +977,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
D != DEnd; ++D) {
if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl()))
if (isNonPlacementDeallocationFunction(Fn))
Matches.addDecl(D.getDecl(), D.getAccess());
Matches.push_back(std::make_pair(D.getPair(), Fn));
}
}
@ -984,7 +986,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
// function, that function will be called; otherwise, no
// deallocation function will be called.
if (Matches.size() == 1) {
OperatorDelete = cast<FunctionDecl>(Matches[0]->getUnderlyingDecl());
OperatorDelete = Matches[0].second;
// C++0x [expr.new]p20:
// If the lookup finds the two-parameter form of a usual
@ -1001,7 +1003,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
<< DeleteName;
} else {
CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(),
Matches[0].getDecl(), Matches[0].getAccess());
Matches[0].first);
}
}
@ -1033,18 +1035,18 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
Alloc != AllocEnd; ++Alloc) {
// Even member operator new/delete are implicitly treated as
// static, so don't use AddMemberCandidate.
NamedDecl *D = (*Alloc)->getUnderlyingDecl();
if (FunctionTemplateDecl *FnTemplate =
dyn_cast<FunctionTemplateDecl>((*Alloc)->getUnderlyingDecl())) {
AddTemplateOverloadCandidate(FnTemplate, Alloc.getAccess(),
if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) {
AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(),
/*ExplicitTemplateArgs=*/0, Args, NumArgs,
Candidates,
/*SuppressUserConversions=*/false);
continue;
}
FunctionDecl *Fn = cast<FunctionDecl>((*Alloc)->getUnderlyingDecl());
AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates,
FunctionDecl *Fn = cast<FunctionDecl>(D);
AddOverloadCandidate(Fn, Alloc.getPair(), Args, NumArgs, Candidates,
/*SuppressUserConversions=*/false);
}
@ -1066,8 +1068,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
return true;
}
Operator = FnDecl;
CheckAllocationAccess(StartLoc, Range, R.getNamingClass(),
FnDecl, Best->getAccess());
CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl);
return false;
}

View File

@ -2007,7 +2007,8 @@ void InitializationSequence::AddAddressOverloadResolutionStep(
S.Kind = SK_ResolveAddressOfOverloadedFunction;
S.Type = Function->getType();
// Access is currently ignored for these.
S.Function = DeclAccessPair::make(Function, AccessSpecifier(0));
S.Function.Function = Function;
S.Function.FoundDecl = DeclAccessPair::make(Function, AS_none);
Steps.push_back(S);
}
@ -2028,12 +2029,13 @@ void InitializationSequence::AddReferenceBindingStep(QualType T,
}
void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
QualType T) {
Step S;
S.Kind = SK_UserConversion;
S.Type = T;
S.Function = DeclAccessPair::make(Function, Access);
S.Function.Function = Function;
S.Function.FoundDecl = FoundDecl;
Steps.push_back(S);
}
@ -2071,7 +2073,8 @@ InitializationSequence::AddConstructorInitializationStep(
Step S;
S.Kind = SK_ConstructorInitialization;
S.Type = T;
S.Function = DeclAccessPair::make(Constructor, Access);
S.Function.Function = Constructor;
S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access);
Steps.push_back(S);
}
@ -2198,25 +2201,26 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = T1RecordDecl->lookup(ConstructorName);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(*Con);
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(*Con);
Constructor = cast<CXXConstructorDecl>(D);
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl,
ConstructorTmpl->getAccess(),
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
&Initializer, 1, CandidateSet);
else
S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
S.AddOverloadCandidate(Constructor, FoundDecl,
&Initializer, 1, CandidateSet);
}
}
@ -2257,11 +2261,11 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
if ((AllowExplicit || !Conv->isExplicit()) &&
(AllowRValues || Conv->getConversionType()->isLValueReferenceType())){
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
ActingDC, Initializer,
ToType, CandidateSet);
else
S.AddConversionCandidate(Conv, I.getAccess(), ActingDC,
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
Initializer, ToType, CandidateSet);
}
}
@ -2284,7 +2288,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
T2 = cv1T1;
// Add the user-defined conversion step.
Sequence.AddUserConversionStep(Function, Best->getAccess(),
Sequence.AddUserConversionStep(Function, Best->FoundDecl,
T2.getNonReferenceType());
// Determine whether we need to perform derived-to-base or
@ -2574,25 +2578,26 @@ static void TryConstructorInitialization(Sema &S,
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(*Con);
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(*Con);
Constructor = cast<CXXConstructorDecl>(D);
if (!Constructor->isInvalidDecl() &&
(AllowExplicit || !Constructor->isExplicit())) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl,
ConstructorTmpl->getAccess(),
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
Args, NumArgs, CandidateSet);
else
S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
S.AddOverloadCandidate(Constructor, FoundDecl,
Args, NumArgs, CandidateSet);
}
}
@ -2623,11 +2628,11 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
if (Kind.getKind() == InitializationKind::IK_Copy) {
Sequence.AddUserConversionStep(Best->Function, Best->getAccess(), DestType);
Sequence.AddUserConversionStep(Best->Function, Best->FoundDecl, DestType);
} else {
Sequence.AddConstructorInitializationStep(
cast<CXXConstructorDecl>(Best->Function),
Best->getAccess(),
Best->FoundDecl.getAccess(),
DestType);
}
}
@ -2744,25 +2749,27 @@ static void TryUserDefinedConversion(Sema &S,
DeclContext::lookup_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(*Con);
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(*Con);
Constructor = cast<CXXConstructorDecl>(D);
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl,
ConstructorTmpl->getAccess(),
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
&Initializer, 1, CandidateSet);
else
S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
S.AddOverloadCandidate(Constructor, FoundDecl,
&Initializer, 1, CandidateSet);
}
}
@ -2799,11 +2806,11 @@ static void TryUserDefinedConversion(Sema &S,
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(),
ActingDC, Initializer, DestType,
CandidateSet);
else
S.AddConversionCandidate(Conv, I.getAccess(), ActingDC,
S.AddConversionCandidate(Conv, I.getPair(), ActingDC,
Initializer, DestType, CandidateSet);
}
}
@ -2825,13 +2832,13 @@ static void TryUserDefinedConversion(Sema &S,
if (isa<CXXConstructorDecl>(Function)) {
// Add the user-defined conversion step. Any cv-qualification conversion is
// subsumed by the initialization.
Sequence.AddUserConversionStep(Function, Best->getAccess(), DestType);
Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType);
return;
}
// Add the user-defined conversion step that calls the conversion function.
QualType ConvType = Function->getResultType().getNonReferenceType();
Sequence.AddUserConversionStep(Function, Best->getAccess(), ConvType);
Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType);
// If the conversion following the call to the conversion function is
// interesting, add it as a separate step.
@ -3135,8 +3142,10 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
if (!Constructor || Constructor->isInvalidDecl() ||
!Constructor->isCopyConstructor())
continue;
S.AddOverloadCandidate(Constructor, Constructor->getAccess(),
DeclAccessPair FoundDecl
= DeclAccessPair::make(Constructor, Constructor->getAccess());
S.AddOverloadCandidate(Constructor, FoundDecl,
&CurInitExpr, 1, CandidateSet);
}
@ -3170,6 +3179,10 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S,
return S.ExprError();
}
S.CheckConstructorAccess(Loc,
cast<CXXConstructorDecl>(Best->Function),
Best->FoundDecl.getAccess());
CurInit.release();
return S.BuildCXXConstructExpr(Loc, CurInitExpr->getType(),
cast<CXXConstructorDecl>(Best->Function),
@ -3303,7 +3316,7 @@ InitializationSequence::Perform(Sema &S,
// initializer to reflect that choice.
// Access control was done in overload resolution.
CurInit = S.FixOverloadedFunctionReference(move(CurInit),
cast<FunctionDecl>(Step->Function.getDecl()));
Step->Function.Function);
break;
case SK_CastDerivedToBaseRValue:
@ -3367,8 +3380,8 @@ InitializationSequence::Perform(Sema &S,
// or a conversion function.
CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
bool IsCopy = false;
FunctionDecl *Fn = cast<FunctionDecl>(Step->Function.getDecl());
AccessSpecifier FnAccess = Step->Function.getAccess();
FunctionDecl *Fn = Step->Function.Function;
DeclAccessPair FoundFn = Step->Function.FoundDecl;
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
// Build a call to the selected constructor.
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
@ -3390,7 +3403,8 @@ InitializationSequence::Perform(Sema &S,
if (CurInit.isInvalid())
return S.ExprError();
S.CheckConstructorAccess(Kind.getLocation(), Constructor, FnAccess);
S.CheckConstructorAccess(Kind.getLocation(), Constructor,
FoundFn.getAccess());
CastKind = CastExpr::CK_ConstructorConversion;
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
@ -3402,7 +3416,7 @@ InitializationSequence::Perform(Sema &S,
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, 0,
Conversion, FnAccess);
FoundFn);
// FIXME: Should we move this initialization into a separate
// derived-to-base conversion? I believe the answer is "no", because
@ -3469,7 +3483,7 @@ InitializationSequence::Perform(Sema &S,
case SK_ConstructorInitialization: {
CXXConstructorDecl *Constructor
= cast<CXXConstructorDecl>(Step->Function.getDecl());
= cast<CXXConstructorDecl>(Step->Function.Function);
// Build a call to the selected constructor.
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
@ -3506,7 +3520,8 @@ InitializationSequence::Perform(Sema &S,
return S.ExprError();
// Only check access if all of that succeeded.
S.CheckConstructorAccess(Loc, Constructor, Step->Function.getAccess());
S.CheckConstructorAccess(Loc, Constructor,
Step->Function.FoundDecl.getAccess());
bool Elidable
= cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable();
@ -3972,7 +3987,8 @@ void InitializationSequence::dump(llvm::raw_ostream &OS) const {
break;
case SK_UserConversion:
OS << "user-defined conversion via " << S->Function->getNameAsString();
OS << "user-defined conversion via "
<< S->Function.Function->getNameAsString();
break;
case SK_QualificationConversionRValue:

View File

@ -454,7 +454,10 @@ public:
/// Always a FunctionDecl.
/// For conversion decls, the naming class is the source type.
/// For construct decls, the naming class is the target type.
DeclAccessPair Function;
struct {
FunctionDecl *Function;
DeclAccessPair FoundDecl;
} Function;
/// \brief When Kind = SK_ConversionSequence, the implicit conversion
/// sequence
@ -622,7 +625,7 @@ public:
/// \brief Add a new step invoking a conversion function, which is either
/// a constructor or a conversion function.
void AddUserConversionStep(FunctionDecl *Function,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
QualType T);
/// \brief Add a new step that performs a qualification conversion to the

View File

@ -1525,28 +1525,30 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
for (llvm::tie(Con, ConEnd)
= ToRecordDecl->lookup(ConstructorName);
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = 0;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(*Con);
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(*Con);
Constructor = cast<CXXConstructorDecl>(D);
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
AddTemplateOverloadCandidate(ConstructorTmpl,
ConstructorTmpl->getAccess(),
AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0,
&From, 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, Constructor->getAccess(),
AddOverloadCandidate(Constructor, FoundDecl,
&From, 1, CandidateSet,
SuppressUserConversions, ForceRValue);
}
@ -1569,7 +1571,8 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
= FromRecordDecl->getVisibleConversionFunctions();
for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
NamedDecl *D = *I;
DeclAccessPair FoundDecl = I.getPair();
NamedDecl *D = FoundDecl.getDecl();
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
@ -1583,11 +1586,11 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
if (AllowExplicit || !Conv->isExplicit()) {
if (ConvTemplate)
AddTemplateConversionCandidate(ConvTemplate, I.getAccess(),
AddTemplateConversionCandidate(ConvTemplate, FoundDecl,
ActingContext, From, ToType,
CandidateSet);
else
AddConversionCandidate(Conv, I.getAccess(), ActingContext,
AddConversionCandidate(Conv, FoundDecl, ActingContext,
From, ToType, CandidateSet);
}
}
@ -2383,7 +2386,7 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
/// code completion.
void
Sema::AddOverloadCandidate(FunctionDecl *Function,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
@ -2404,7 +2407,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// function, e.g., X::f(). We use an empty type for the implied
// object argument (C++ [over.call.func]p3), and the acting context
// is irrelevant.
AddMethodCandidate(Method, Access, Method->getParent(),
AddMethodCandidate(Method, FoundDecl, Method->getParent(),
QualType(), Args, NumArgs, CandidateSet,
SuppressUserConversions, ForceRValue);
return;
@ -2434,8 +2437,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Function;
Candidate.Access = Access;
Candidate.Viable = true;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
@ -2500,28 +2503,28 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
// FIXME: using declarations
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F)) {
NamedDecl *D = F.getDecl()->getUnderlyingDecl();
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getAccess(),
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(),
cast<CXXMethodDecl>(FD)->getParent(),
Args[0]->getType(), Args + 1, NumArgs - 1,
CandidateSet, SuppressUserConversions);
else
AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet,
AddOverloadCandidate(FD, F.getPair(), Args, NumArgs, CandidateSet,
SuppressUserConversions);
} else {
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*F);
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D);
if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
!cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
AddMethodTemplateCandidate(FunTmpl, F.getAccess(),
AddMethodTemplateCandidate(FunTmpl, F.getPair(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
/*FIXME: explicit args */ 0,
Args[0]->getType(), Args + 1, NumArgs - 1,
CandidateSet,
SuppressUserConversions);
else
AddTemplateOverloadCandidate(FunTmpl, AS_none,
AddTemplateOverloadCandidate(FunTmpl, F.getPair(),
/*FIXME: explicit args */ 0,
Args, NumArgs, CandidateSet,
SuppressUserConversions);
@ -2531,12 +2534,12 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
/// AddMethodCandidate - Adds a named decl (which is some kind of
/// method) as a method candidate to the given overload set.
void Sema::AddMethodCandidate(NamedDecl *Decl,
AccessSpecifier Access,
void Sema::AddMethodCandidate(DeclAccessPair FoundDecl,
QualType ObjectType,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions, bool ForceRValue) {
NamedDecl *Decl = FoundDecl.getDecl();
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(Decl->getDeclContext());
if (isa<UsingShadowDecl>(Decl))
@ -2545,13 +2548,14 @@ void Sema::AddMethodCandidate(NamedDecl *Decl,
if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) {
assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) &&
"Expected a member function template");
AddMethodTemplateCandidate(TD, Access, ActingContext, /*ExplicitArgs*/ 0,
AddMethodTemplateCandidate(TD, FoundDecl, ActingContext,
/*ExplicitArgs*/ 0,
ObjectType, Args, NumArgs,
CandidateSet,
SuppressUserConversions,
ForceRValue);
} else {
AddMethodCandidate(cast<CXXMethodDecl>(Decl), Access, ActingContext,
AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext,
ObjectType, Args, NumArgs,
CandidateSet, SuppressUserConversions, ForceRValue);
}
@ -2567,7 +2571,7 @@ void Sema::AddMethodCandidate(NamedDecl *Decl,
/// a slightly hacky way to implement the overloading rules for elidable copy
/// initialization in C++0x (C++0x 12.8p15).
void
Sema::AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access,
Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext, QualType ObjectType,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@ -2587,8 +2591,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access,
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Method;
Candidate.Access = Access;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
@ -2666,7 +2670,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access,
/// function template specialization.
void
Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
QualType ObjectType,
@ -2702,7 +2706,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
assert(Specialization && "Missing member function template specialization?");
assert(isa<CXXMethodDecl>(Specialization) &&
"Specialization is not a member function?");
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), Access,
AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl,
ActingContext, ObjectType, Args, NumArgs,
CandidateSet, SuppressUserConversions, ForceRValue);
}
@ -2712,7 +2716,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
/// an appropriate function template specialization.
void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
@ -2737,8 +2741,8 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
Args, NumArgs, Specialization, Info)) {
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate &Candidate = CandidateSet.back();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = FunctionTemplate->getTemplatedDecl();
Candidate.Access = Access;
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_deduction;
Candidate.IsSurrogate = false;
@ -2753,7 +2757,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
// Add the function template specialization produced by template argument
// deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
AddOverloadCandidate(Specialization, Access, Args, NumArgs, CandidateSet,
AddOverloadCandidate(Specialization, FoundDecl, Args, NumArgs, CandidateSet,
SuppressUserConversions, ForceRValue);
}
@ -2765,7 +2769,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
/// conversion function produces).
void
Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet) {
@ -2781,8 +2785,8 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = Conversion;
Candidate.Access = Access;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.FinalConversion.setAsIdentityConversion();
@ -2869,7 +2873,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
/// [temp.deduct.conv]).
void
Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingDC,
Expr *From, QualType ToType,
OverloadCandidateSet &CandidateSet) {
@ -2893,7 +2897,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
// Add the conversion function template specialization produced by
// template argument deduction as a candidate.
assert(Specialization && "Missing function template specialization?");
AddConversionCandidate(Specialization, Access, ActingDC, From, ToType,
AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType,
CandidateSet);
}
@ -2903,7 +2907,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate,
/// with the given arguments (C++ [over.call.object]p2-4). Proto is
/// the type of function that we'll eventually be calling.
void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
CXXRecordDecl *ActingContext,
const FunctionProtoType *Proto,
QualType ObjectType,
@ -2917,8 +2921,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.FoundDecl = FoundDecl;
Candidate.Function = 0;
Candidate.Access = Access;
Candidate.Surrogate = Conversion;
Candidate.Viable = true;
Candidate.IsSurrogate = true;
@ -3066,7 +3070,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op,
OperEnd = Operators.end();
Oper != OperEnd;
++Oper)
AddMethodCandidate(*Oper, Oper.getAccess(), Args[0]->getType(),
AddMethodCandidate(Oper.getPair(), Args[0]->getType(),
Args + 1, NumArgs - 1, CandidateSet,
/* SuppressUserConversions = */ false);
}
@ -3091,8 +3095,8 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
// Add this candidate
CandidateSet.push_back(OverloadCandidate());
OverloadCandidate& Candidate = CandidateSet.back();
Candidate.FoundDecl = DeclAccessPair::make(0, AS_none);
Candidate.Function = 0;
Candidate.Access = AS_none;
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.BuiltinTypes.ResultTy = ResultTy;
@ -4179,15 +4183,16 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
// For each of the ADL candidates we found, add it to the overload
// set.
for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) {
DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none);
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
if (ExplicitTemplateArgs)
continue;
AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet,
AddOverloadCandidate(FD, FoundDecl, Args, NumArgs, CandidateSet,
false, false, PartialOverloading);
} else
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
AS_none, ExplicitTemplateArgs,
FoundDecl, ExplicitTemplateArgs,
Args, NumArgs, CandidateSet);
}
}
@ -4951,12 +4956,11 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
}
}
static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, NamedDecl *D,
AccessSpecifier AS) {
static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
if (isa<UnresolvedLookupExpr>(E))
return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D, AS);
return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D);
return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D, AS);
return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D);
}
/// ResolveAddressOfOverloadedFunction - Try to resolve the address of
@ -5013,7 +5017,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
UnresolvedSet<4> Matches; // contains only FunctionDecls
llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
bool FoundNonTemplateFunction = false;
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
E = OvlExpr->decls_end(); I != E; ++I) {
@ -5057,8 +5061,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// a candidate? Find a testcase before changing the code.
assert(FunctionType
== Context.getCanonicalType(Specialization->getType()));
Matches.addDecl(cast<FunctionDecl>(Specialization->getCanonicalDecl()),
I.getAccess());
Matches.push_back(std::make_pair(I.getPair(),
cast<FunctionDecl>(Specialization->getCanonicalDecl())));
}
continue;
@ -5081,8 +5085,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) ||
IsNoReturnConversion(Context, FunDecl->getType(), FunctionType,
ResultTy)) {
Matches.addDecl(cast<FunctionDecl>(FunDecl->getCanonicalDecl()),
I.getAccess());
Matches.push_back(std::make_pair(I.getPair(),
cast<FunctionDecl>(FunDecl->getCanonicalDecl())));
FoundNonTemplateFunction = true;
}
}
@ -5092,10 +5096,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
if (Matches.empty())
return 0;
else if (Matches.size() == 1) {
FunctionDecl *Result = cast<FunctionDecl>(*Matches.begin());
FunctionDecl *Result = Matches[0].second;
MarkDeclarationReferenced(From->getLocStart(), Result);
if (Complain)
CheckUnresolvedAccess(*this, OvlExpr, Result, Matches.begin().getAccess());
CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
return Result;
}
@ -5112,50 +5116,54 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
// two-pass algorithm (similar to the one used to identify the
// best viable function in an overload set) that identifies the
// best function template (if it exists).
UnresolvedSet<4> MatchesCopy; // TODO: avoid!
for (unsigned I = 0, E = Matches.size(); I != E; ++I)
MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
UnresolvedSetIterator Result =
getMostSpecialized(Matches.begin(), Matches.end(),
getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
TPOC_Other, From->getLocStart(),
PDiag(),
PDiag(diag::err_addr_ovl_ambiguous)
<< Matches[0]->getDeclName(),
<< Matches[0].second->getDeclName(),
PDiag(diag::note_ovl_candidate)
<< (unsigned) oc_function_template);
assert(Result != Matches.end() && "no most-specialized template");
assert(Result != MatchesCopy.end() && "no most-specialized template");
MarkDeclarationReferenced(From->getLocStart(), *Result);
if (Complain)
CheckUnresolvedAccess(*this, OvlExpr, *Result, Result.getAccess());
if (Complain) {
DeclAccessPair FoundDecl = Matches[Result - MatchesCopy.begin()].first;
CheckUnresolvedAccess(*this, OvlExpr, FoundDecl);
}
return cast<FunctionDecl>(*Result);
}
// [...] any function template specializations in the set are
// eliminated if the set also contains a non-template function, [...]
for (unsigned I = 0, N = Matches.size(); I != N; ) {
if (cast<FunctionDecl>(Matches[I].getDecl())->getPrimaryTemplate() == 0)
if (Matches[I].second->getPrimaryTemplate() == 0)
++I;
else {
Matches.erase(I);
--N;
Matches[I] = Matches[--N];
Matches.set_size(N);
}
}
// [...] After such eliminations, if any, there shall remain exactly one
// selected function.
if (Matches.size() == 1) {
UnresolvedSetIterator Match = Matches.begin();
MarkDeclarationReferenced(From->getLocStart(), *Match);
MarkDeclarationReferenced(From->getLocStart(), Matches[0].second);
if (Complain)
CheckUnresolvedAccess(*this, OvlExpr, *Match, Match.getAccess());
return cast<FunctionDecl>(*Match);
CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
return cast<FunctionDecl>(Matches[0].second);
}
// FIXME: We should probably return the same thing that BestViableFunction
// returns (even if we issue the diagnostics here).
Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
<< Matches[0]->getDeclName();
for (UnresolvedSetIterator I = Matches.begin(),
E = Matches.end(); I != E; ++I)
NoteOverloadCandidate(cast<FunctionDecl>(*I));
<< Matches[0].second->getDeclName();
for (unsigned I = 0, E = Matches.size(); I != E; ++I)
NoteOverloadCandidate(Matches[I].second);
return 0;
}
@ -5227,25 +5235,26 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
/// \brief Add a single candidate to the overload set.
static void AddOverloadedCallCandidate(Sema &S,
NamedDecl *Callee,
AccessSpecifier Access,
DeclAccessPair FoundDecl,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet,
bool PartialOverloading) {
NamedDecl *Callee = FoundDecl.getDecl();
if (isa<UsingShadowDecl>(Callee))
Callee = cast<UsingShadowDecl>(Callee)->getTargetDecl();
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) {
assert(!ExplicitTemplateArgs && "Explicit template arguments?");
S.AddOverloadCandidate(Func, Access, Args, NumArgs, CandidateSet,
S.AddOverloadCandidate(Func, FoundDecl, Args, NumArgs, CandidateSet,
false, false, PartialOverloading);
return;
}
if (FunctionTemplateDecl *FuncTemplate
= dyn_cast<FunctionTemplateDecl>(Callee)) {
S.AddTemplateOverloadCandidate(FuncTemplate, Access, ExplicitTemplateArgs,
S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl,
ExplicitTemplateArgs,
Args, NumArgs, CandidateSet);
return;
}
@ -5301,7 +5310,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
E = ULE->decls_end(); I != E; ++I)
AddOverloadedCallCandidate(*this, *I, I.getAccess(), ExplicitTemplateArgs,
AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs,
Args, NumArgs, CandidateSet,
PartialOverloading);
@ -5423,7 +5432,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) {
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
CheckUnresolvedLookupAccess(ULE, FDecl, Best->getAccess());
CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
Fn = FixOverloadedFunctionReference(Fn, FDecl);
return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
}
@ -5549,7 +5558,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], 0, Method, Best->getAccess());
CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, Method))
return ExprError();
@ -5733,8 +5742,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
// Best->Access is only meaningful for class members.
CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Method,
Best->getAccess());
CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl);
OwningExprResult Arg1
= PerformCopyInitialization(
@ -5908,8 +5916,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
// We matched an overloaded operator. Build a call to that
// operator.
CheckMemberOperatorAccess(LLoc, Args[0], Args[1], FnDecl,
Best->getAccess());
CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl);
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
@ -6054,12 +6061,12 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
if (TemplateArgs)
continue;
AddMethodCandidate(Method, I.getAccess(), ActingDC, ObjectType,
AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType,
Args, NumArgs,
CandidateSet, /*SuppressUserConversions=*/false);
} else {
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
I.getAccess(), ActingDC, TemplateArgs,
I.getPair(), ActingDC, TemplateArgs,
ObjectType, Args, NumArgs,
CandidateSet,
/*SuppressUsedConversions=*/false);
@ -6072,7 +6079,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
CheckUnresolvedMemberAccess(UnresExpr, Method, Best->getAccess());
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
break;
case OR_No_Viable_Function:
@ -6176,7 +6183,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
AddMethodCandidate(*Oper, Oper.getAccess(), Object->getType(),
AddMethodCandidate(Oper.getPair(), Object->getType(),
Args, NumArgs, CandidateSet,
/*SuppressUserConversions=*/ false);
}
@ -6221,7 +6228,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
ConvType = ConvPtrType->getPointeeType();
if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>())
AddSurrogateCandidate(Conv, I.getAccess(), ActingContext, Proto,
AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto,
Object->getType(), Args, NumArgs,
CandidateSet);
}
@ -6278,7 +6285,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
= cast<CXXConversionDecl>(
Best->Conversions[0].UserDefined.ConversionFunction);
CheckMemberOperatorAccess(LParenLoc, Object, 0, Conv, Best->getAccess());
CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
// We selected one of the surrogate functions that converts the
// object parameter to a function pointer. Perform the conversion
@ -6293,8 +6300,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
CommaLocs, RParenLoc).release();
}
CheckMemberOperatorAccess(LParenLoc, Object, 0,
Best->Function, Best->getAccess());
CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl);
// We found an overloaded operator(). Build a CXXOperatorCallExpr
// that calls this method, using Object for the implicit object
@ -6429,13 +6435,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end();
Oper != OperEnd; ++Oper) {
NamedDecl *D = *Oper;
CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext());
if (isa<UsingShadowDecl>(D))
D = cast<UsingShadowDecl>(D)->getTargetDecl();
AddMethodCandidate(cast<CXXMethodDecl>(D), Oper.getAccess(), ActingContext,
Base->getType(), 0, 0, CandidateSet,
AddMethodCandidate(Oper.getPair(), Base->getType(), 0, 0, CandidateSet,
/*SuppressUserConversions=*/false);
}
@ -6470,6 +6470,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
return ExprError();
}
CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
// Convert the object parameter.
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, Method))

View File

@ -18,6 +18,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
@ -450,6 +451,11 @@ namespace clang {
/// function pointer or reference (C++ [over.call.object]).
FunctionDecl *Function;
/// FoundDecl - The original declaration that was looked up /
/// invented / otherwise found, together with its access.
/// Might be a UsingShadowDecl or a FunctionTemplateDecl.
DeclAccessPair FoundDecl;
// BuiltinTypes - Provides the return and parameter types of a
// built-in overload candidate. Only valid when Function is NULL.
struct {
@ -486,14 +492,6 @@ namespace clang {
/// Actually an OverloadFailureKind.
unsigned char FailureKind;
/// PathAccess - The 'path access' to the given function/conversion.
/// Actually an AccessSpecifier.
unsigned Access;
AccessSpecifier getAccess() const {
return AccessSpecifier(Access);
}
/// A structure used to record information about a failed
/// template argument deduction.
struct DeductionFailureInfo {