Preserve access bits through overload resolution much better. Some

general refactoring in operator resolution.

llvm-svn: 94498
This commit is contained in:
John McCall 2010-01-26 03:27:55 +00:00
parent 47751d6c21
commit 4c4c1dfc2b
7 changed files with 90 additions and 103 deletions

View File

@ -1137,6 +1137,10 @@ public:
UnresolvedSetImpl::const_iterator End,
const TemplateArgumentListInfo *Args);
void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) {
Results.append(Begin, End);
}
void addDecl(NamedDecl *Decl) {
Results.addDecl(Decl);
}

View File

@ -224,6 +224,10 @@ public:
return Ambiguity;
}
const UnresolvedSetImpl &asUnresolvedSet() const {
return Decls;
}
iterator begin() const { return iterator(Decls.begin()); }
iterator end() const { return iterator(Decls.end()); }

View File

@ -950,10 +950,15 @@ public:
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
// TODO: make this is a typesafe union.
typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet;
typedef llvm::SmallPtrSet<AnyFunctionDecl, 16> FunctionSet;
// Members have to be a function or function template.
typedef llvm::SmallPtrSet<NamedDecl*, 16> ADLFunctionSet;
typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet;
void AddOverloadCandidate(NamedDecl *Function,
AccessSpecifier Access,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet &CandidateSet);
void AddOverloadCandidate(FunctionDecl *Function,
AccessSpecifier Access,
Expr **Args, unsigned NumArgs,
@ -961,7 +966,7 @@ public:
bool SuppressUserConversions = false,
bool ForceRValue = false,
bool PartialOverloading = false);
void AddFunctionCandidates(const FunctionSet &Functions,
void AddFunctionCandidates(const UnresolvedSetImpl &Functions,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false);
@ -1029,6 +1034,7 @@ public:
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet);
void AddArgumentDependentLookupCandidates(DeclarationName Name,
bool Operator,
Expr **Args, unsigned NumArgs,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
@ -1080,12 +1086,12 @@ public:
OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
unsigned Opc,
FunctionSet &Functions,
const UnresolvedSetImpl &Fns,
ExprArg input);
OwningExprResult CreateOverloadedBinOp(SourceLocation OpLoc,
unsigned Opc,
FunctionSet &Functions,
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS);
OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
@ -1230,11 +1236,11 @@ public:
void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
FunctionSet &Functions);
UnresolvedSetImpl &Functions);
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
FunctionSet &Functions);
ADLFunctionSet &Functions);
void LookupVisibleDecls(Scope *S, LookupNameKind Kind,
VisibleDeclConsumer &Consumer);

View File

@ -6337,17 +6337,11 @@ Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
// the arguments.
FunctionSet Functions;
UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc);
if (OverOp != OO_None) {
if (S)
LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
Functions);
Expr *Args[2] = { lhs, rhs };
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions);
}
if (S && OverOp != OO_None)
LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(),
Functions);
// Build the (potentially-overloaded, potentially-dependent)
// binary operation.
@ -6456,16 +6450,11 @@ Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
// point. We perform both an operator-name lookup from the local
// scope and an argument-dependent lookup based on the types of
// the arguments.
FunctionSet Functions;
UnresolvedSet<16> Functions;
OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc);
if (OverOp != OO_None) {
if (S)
LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
Functions);
DeclarationName OpName
= Context.DeclarationNames.getCXXOperatorName(OverOp);
ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions);
}
if (S && OverOp != OO_None)
LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(),
Functions);
return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input));
}

View File

@ -1693,7 +1693,7 @@ ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) {
void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
QualType T1, QualType T2,
FunctionSet &Functions) {
UnresolvedSetImpl &Functions) {
// C++ [over.match.oper]p3:
// -- The set of non-member candidates is the result of the
// unqualified lookup of operator@ in the context of the
@ -1719,29 +1719,21 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
Op != OpEnd; ++Op) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) {
if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context))
Functions.insert(FD); // FIXME: canonical FD
Functions.addDecl(FD, Op.getAccess()); // FIXME: canonical FD
} else if (FunctionTemplateDecl *FunTmpl
= dyn_cast<FunctionTemplateDecl>(*Op)) {
// FIXME: friend operators?
// FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate,
// later?
if (!FunTmpl->getDeclContext()->isRecord())
Functions.insert(FunTmpl);
Functions.addDecl(FunTmpl, Op.getAccess());
}
}
}
static void CollectFunctionDecl(Sema::FunctionSet &Functions,
Decl *D) {
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
Functions.insert(Func);
else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
Functions.insert(FunTmpl);
}
void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
Expr **Args, unsigned NumArgs,
FunctionSet &Functions) {
ADLFunctionSet &Functions) {
// Find all of the associated namespaces and classes based on the
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
@ -1784,7 +1776,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
// lookup (11.4).
DeclContext::lookup_iterator I, E;
for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) {
Decl *D = *I;
NamedDecl *D = *I;
// If the only declaration here is an ordinary friend, consider
// it only if it was declared in an associated classes.
if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
@ -1793,10 +1785,16 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator,
continue;
}
// FIXME: using decls? canonical decls?
FunctionDecl *Fn;
if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) ||
IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context))
CollectFunctionDecl(Functions, D);
IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context)) {
if (isa<FunctionDecl>(D))
Functions.insert(D);
else if (isa<FunctionTemplateDecl>(D))
Functions.insert(D);
}
}
}
}

View File

@ -2475,17 +2475,15 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
/// \brief Add all of the function declarations in the given function set to
/// the overload canddiate set.
void Sema::AddFunctionCandidates(const FunctionSet &Functions,
void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions) {
for (FunctionSet::const_iterator F = Functions.begin(),
FEnd = Functions.end();
F != FEnd; ++F) {
for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) {
// FIXME: using declarations
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F)) {
if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic())
AddMethodCandidate(cast<CXXMethodDecl>(FD), /*FIXME*/ FD->getAccess(),
AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getAccess(),
cast<CXXMethodDecl>(FD)->getParent(),
Args[0]->getType(), Args + 1, NumArgs - 1,
CandidateSet, SuppressUserConversions);
@ -2496,7 +2494,7 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions,
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*F);
if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) &&
!cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic())
AddMethodTemplateCandidate(FunTmpl, /*FIXME*/ FunTmpl->getAccess(),
AddMethodTemplateCandidate(FunTmpl, F.getAccess(),
cast<CXXRecordDecl>(FunTmpl->getDeclContext()),
/*FIXME: explicit args */ 0,
Args[0]->getType(), Args + 1, NumArgs - 1,
@ -2986,7 +2984,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
SourceRange OpRange) {
FunctionSet Functions;
UnresolvedSet<16> Fns;
QualType T1 = Args[0]->getType();
QualType T2;
@ -2995,9 +2993,10 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op);
if (S)
LookupOverloadedOperatorName(Op, S, T1, T2, Functions);
ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, Functions);
AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);
LookupOverloadedOperatorName(Op, S, T1, T2, Fns);
AddFunctionCandidates(Fns, Args, NumArgs, CandidateSet, false);
AddArgumentDependentLookupCandidates(OpName, false, Args, NumArgs, 0,
CandidateSet);
AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange);
AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet);
}
@ -4127,31 +4126,19 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,
/// candidate set (C++ [basic.lookup.argdep]).
void
Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
bool Operator,
Expr **Args, unsigned NumArgs,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
OverloadCandidateSet& CandidateSet,
bool PartialOverloading) {
FunctionSet Functions;
ADLFunctionSet Functions;
// FIXME: Should we be trafficking in canonical function decls throughout?
// Record all of the function candidates that we've already
// added to the overload set, so that we don't add those same
// candidates a second time.
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
CandEnd = CandidateSet.end();
Cand != CandEnd; ++Cand)
if (Cand->Function) {
Functions.insert(Cand->Function);
if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate())
Functions.insert(FunTmpl);
}
// FIXME: Pass in the explicit template arguments?
ArgumentDependentLookup(Name, /*Operator*/false, Args, NumArgs, Functions);
ArgumentDependentLookup(Name, Operator, Args, NumArgs, Functions);
// Erase all of the candidates we already knew about.
// FIXME: This is suboptimal. Is there a better way?
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
CandEnd = CandidateSet.end();
Cand != CandEnd; ++Cand)
@ -4163,17 +4150,16 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
// For each of the ADL candidates we found, add it to the overload
// set.
for (FunctionSet::iterator Func = Functions.begin(),
FuncEnd = Functions.end();
Func != FuncEnd; ++Func) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) {
for (ADLFunctionSet::iterator I = Functions.begin(),
E = Functions.end(); I != E; ++I) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
if (ExplicitTemplateArgs)
continue;
AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet,
false, false, PartialOverloading);
} else
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func),
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I),
AS_none, ExplicitTemplateArgs,
Args, NumArgs, CandidateSet);
}
@ -5242,7 +5228,8 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
PartialOverloading);
if (ULE->requiresADL())
AddArgumentDependentLookupCandidates(ULE->getName(), Args, NumArgs,
AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false,
Args, NumArgs,
ExplicitTemplateArgs,
CandidateSet,
PartialOverloading);
@ -5392,7 +5379,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
return ExprError();
}
static bool IsOverloaded(const Sema::FunctionSet &Functions) {
static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
return Functions.size() > 1 ||
(Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
}
@ -5413,10 +5400,10 @@ static bool IsOverloaded(const Sema::FunctionSet &Functions) {
/// by CreateOverloadedUnaryOp().
///
/// \param input The input argument.
Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
unsigned OpcIn,
FunctionSet &Functions,
ExprArg input) {
Sema::OwningExprResult
Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,
const UnresolvedSetImpl &Fns,
ExprArg input) {
UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn);
Expr *Input = (Expr *)input.get();
@ -5441,11 +5428,8 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
0, SourceRange(), OpName, OpLoc,
/*ADL*/ true, IsOverloaded(Functions));
for (FunctionSet::iterator Func = Functions.begin(),
FuncEnd = Functions.end();
Func != FuncEnd; ++Func)
Fn->addDecl(*Func);
/*ADL*/ true, IsOverloaded(Fns));
Fn->addDecls(Fns.begin(), Fns.end());
input.release();
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
@ -5458,11 +5442,17 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
OverloadCandidateSet CandidateSet;
// Add the candidates from the given function set.
AddFunctionCandidates(Functions, &Args[0], NumArgs, CandidateSet, false);
AddFunctionCandidates(Fns, &Args[0], NumArgs, CandidateSet, false);
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
// Add candidates from ADL.
AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
Args, 1,
/*ExplicitTemplateArgs*/ 0,
CandidateSet);
// Add builtin operator candidates.
AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);
@ -5575,7 +5565,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
Sema::OwningExprResult
Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
unsigned OpcIn,
FunctionSet &Functions,
const UnresolvedSetImpl &Fns,
Expr *LHS, Expr *RHS) {
Expr *Args[2] = { LHS, RHS };
LHS=RHS=0; //Please use only Args instead of LHS/RHS couple
@ -5587,7 +5577,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
// If either side is type-dependent, create an appropriate dependent
// expression.
if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) {
if (Functions.empty()) {
if (Fns.empty()) {
// If there are no functions to store, just build a dependent
// BinaryOperator or CompoundAssignment.
if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign)
@ -5601,16 +5591,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
OpLoc));
}
// FIXME: save results of ADL from here?
UnresolvedLookupExpr *Fn
= UnresolvedLookupExpr::Create(Context, /*Dependent*/ true,
0, SourceRange(), OpName, OpLoc,
/* ADL */ true, IsOverloaded(Functions));
for (FunctionSet::iterator Func = Functions.begin(),
FuncEnd = Functions.end();
Func != FuncEnd; ++Func)
Fn->addDecl(*Func);
/*ADL*/ true, IsOverloaded(Fns));
Fn->addDecls(Fns.begin(), Fns.end());
return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn,
Args, 2,
Context.DependentTy,
@ -5635,11 +5622,17 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
OverloadCandidateSet CandidateSet;
// Add the candidates from the given function set.
AddFunctionCandidates(Functions, Args, 2, CandidateSet, false);
AddFunctionCandidates(Fns, Args, 2, CandidateSet, false);
// Add operator candidates that are member functions.
AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);
// Add candidates from ADL.
AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true,
Args, 2,
/*ExplicitTemplateArgs*/ 0,
CandidateSet);
// Add builtin operator candidates.
AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);

View File

@ -5644,28 +5644,21 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
// Compute the transformed set of functions (and function templates) to be
// used during overload resolution.
Sema::FunctionSet Functions;
UnresolvedSet<16> Functions;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(CalleeExpr)) {
assert(ULE->requiresADL());
// FIXME: Do we have to check
// IsAcceptableNonMemberOperatorCandidate for each of these?
for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(),
E = ULE->decls_end(); I != E; ++I)
Functions.insert(AnyFunctionDecl::getFromNamedDecl(*I));
Functions.append(ULE->decls_begin(), ULE->decls_end());
} else {
Functions.insert(AnyFunctionDecl::getFromNamedDecl(
cast<DeclRefExpr>(CalleeExpr)->getDecl()));
Functions.addDecl(cast<DeclRefExpr>(CalleeExpr)->getDecl());
}
// Add any functions found via argument-dependent lookup.
Expr *Args[2] = { FirstExpr, SecondExpr };
unsigned NumArgs = 1 + (SecondExpr != 0);
DeclarationName OpName
= SemaRef.Context.DeclarationNames.getCXXOperatorName(Op);
SemaRef.ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs,
Functions);
// Create the overloaded operator invocation for unary operators.
if (NumArgs == 1 || isPostIncDec) {