Extract a common base class between UnresolvedLookupExpr and

UnresolvedMemberExpr and employ it in a few places where it's useful.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95072 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
John McCall 2010-02-02 06:20:04 +00:00
Родитель b217bcce14
Коммит 7bb12da2b0
5 изменённых файлов: 205 добавлений и 254 удалений

Просмотреть файл

@ -1129,6 +1129,112 @@ public:
virtual child_iterator child_end();
};
/// \brief A reference to an overloaded function set, either an
/// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr.
class OverloadExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls. Access is relative to the naming
/// class.
UnresolvedSet<4> Results;
/// The common name of these declarations.
DeclarationName Name;
/// The scope specifier, if any.
NestedNameSpecifier *Qualifier;
/// The source range of the scope specifier.
SourceRange QualifierRange;
/// The location of the name.
SourceLocation NameLoc;
/// True if the name was a template-id.
bool HasExplicitTemplateArgs;
protected:
OverloadExpr(StmtClass K, QualType T, bool Dependent,
NestedNameSpecifier *Qualifier, SourceRange QRange,
DeclarationName Name, SourceLocation NameLoc,
bool HasTemplateArgs)
: Expr(K, T, Dependent, Dependent),
Name(Name), Qualifier(Qualifier), QualifierRange(QRange),
NameLoc(NameLoc), HasExplicitTemplateArgs(HasTemplateArgs)
{}
public:
/// Computes whether an unresolved lookup on the given declarations
/// and optional template arguments is type- and value-dependent.
static bool ComputeDependence(UnresolvedSetIterator Begin,
UnresolvedSetIterator End,
const TemplateArgumentListInfo *Args);
/// Finds the overloaded expression in the given expression of
/// OverloadTy.
///
/// \return the expression (which must be there) and true if it is
/// within an address-of operator.
static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) {
assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
bool op = false;
E = E->IgnoreParens();
if (isa<UnaryOperator>(E))
op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op);
}
void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) {
Results.append(Begin, End);
}
typedef UnresolvedSetImpl::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }
/// Gets the decls as an unresolved set.
const UnresolvedSetImpl &getDecls() { return Results; }
/// Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return Results.size(); }
/// Gets the name looked up.
DeclarationName getName() const { return Name; }
void setName(DeclarationName N) { Name = N; }
/// Gets the location of the name.
SourceLocation getNameLoc() const { return NameLoc; }
void setNameLoc(SourceLocation Loc) { NameLoc = Loc; }
/// Fetches the nested-name qualifier, if one was given.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
/// Fetches the range of the nested-name qualifier.
SourceRange getQualifierRange() const { return QualifierRange; }
/// \brief Determines whether this expression had an explicit
/// template argument list, e.g. f<int>.
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
ExplicitTemplateArgumentList &getExplicitTemplateArgs(); // defined far below
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs();
}
ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
if (hasExplicitTemplateArgs())
return &getExplicitTemplateArgs();
return 0;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedLookupExprClass ||
T->getStmtClass() == UnresolvedMemberExprClass;
}
static bool classof(const OverloadExpr *) { return true; }
};
/// \brief A reference to a name which we were able to look up during
/// parsing but could not resolve to a specific declaration. This
/// arises in several ways:
@ -1139,30 +1245,7 @@ public:
/// These never include UnresolvedUsingValueDecls, which are always
/// class members and therefore appear only in
/// UnresolvedMemberLookupExprs.
class UnresolvedLookupExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
UnresolvedSet<4> Results;
/// The name declared.
DeclarationName Name;
/// The naming class (C++ [class.access.base]p5) of the lookup, if
/// any. This can generally be recalculated from the context chain,
/// but that can be fairly expensive for unqualified lookups. If we
/// want to improve memory use here, this could go in a union
/// against the qualified-lookup bits.
CXXRecordDecl *NamingClass;
/// The qualifier given, if any.
NestedNameSpecifier *Qualifier;
/// The source range of the nested name specifier.
SourceRange QualifierRange;
/// The location of the name.
SourceLocation NameLoc;
class UnresolvedLookupExpr : public OverloadExpr {
/// True if these lookup results should be extended by
/// argument-dependent lookup if this is the operand of a function
/// call.
@ -1172,19 +1255,20 @@ class UnresolvedLookupExpr : public Expr {
/// trivially rederivable if we urgently need to kill this field.
bool Overloaded;
/// True if the name looked up had explicit template arguments.
/// This requires all the results to be function templates.
bool HasExplicitTemplateArgs;
/// The naming class (C++ [class.access.base]p5) of the lookup, if
/// any. This can generally be recalculated from the context chain,
/// but that can be fairly expensive for unqualified lookups. If we
/// want to improve memory use here, this could go in a union
/// against the qualified-lookup bits.
CXXRecordDecl *NamingClass;
UnresolvedLookupExpr(QualType T, bool Dependent, CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier, SourceRange QRange,
DeclarationName Name, SourceLocation NameLoc,
bool RequiresADL, bool Overloaded, bool HasTemplateArgs)
: Expr(UnresolvedLookupExprClass, T, Dependent, Dependent),
Name(Name), NamingClass(NamingClass),
Qualifier(Qualifier), QualifierRange(QRange),
NameLoc(NameLoc), RequiresADL(RequiresADL), Overloaded(Overloaded),
HasExplicitTemplateArgs(HasTemplateArgs)
: OverloadExpr(UnresolvedLookupExprClass, T, Dependent, Qualifier, QRange,
Name, NameLoc, HasTemplateArgs),
RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass)
{}
public:
@ -1212,23 +1296,6 @@ public:
bool ADL,
const TemplateArgumentListInfo &Args);
/// Computes whether an unresolved lookup on the given declarations
/// and optional template arguments is type- and value-dependent.
static bool ComputeDependence(UnresolvedSetImpl::const_iterator Begin,
UnresolvedSetImpl::const_iterator End,
const TemplateArgumentListInfo *Args);
void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) {
Results.append(Begin, End);
}
typedef UnresolvedSetImpl::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }
/// Retrieves the decls as an unresolved set.
const UnresolvedSetImpl &getDecls() { return Results; }
/// True if this declaration should be extended by
/// argument-dependent lookup.
bool requiresADL() const { return RequiresADL; }
@ -1236,30 +1303,20 @@ public:
/// True if this lookup is overloaded.
bool isOverloaded() const { return Overloaded; }
/// Fetches the name looked up.
DeclarationName getName() const { return Name; }
/// Gets the location of the name.
SourceLocation getNameLoc() const { return NameLoc; }
/// Gets the 'naming class' (in the sense of C++0x
/// [class.access.base]p5) of the lookup. This is the scope
/// that was looked in to find these results.
CXXRecordDecl *getNamingClass() const { return NamingClass; }
/// Fetches the nested-name qualifier, if one was given.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
/// Fetches the range of the nested-name qualifier.
SourceRange getQualifierRange() const { return QualifierRange; }
/// Determines whether this lookup had explicit template arguments.
bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; }
// Note that, inconsistently with the explicit-template-argument AST
// nodes, users are *forbidden* from calling these methods on objects
// without explicit template arguments.
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1);
}
/// Gets a reference to the explicit template argument list.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
assert(hasExplicitTemplateArgs());
@ -1289,8 +1346,8 @@ public:
}
virtual SourceRange getSourceRange() const {
SourceRange Range(NameLoc);
if (Qualifier) Range.setBegin(QualifierRange.getBegin());
SourceRange Range(getNameLoc());
if (getQualifier()) Range.setBegin(getQualifierRange().getBegin());
if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
return Range;
}
@ -1802,10 +1859,14 @@ public:
/// In the final AST, an explicit access always becomes a MemberExpr.
/// An implicit access may become either a MemberExpr or a
/// DeclRefExpr, depending on whether the member is static.
class UnresolvedMemberExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
UnresolvedSet<4> Results;
class UnresolvedMemberExpr : public OverloadExpr {
/// \brief Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
/// \brief Whether the lookup results contain an unresolved using
/// declaration.
bool HasUnresolvedUsing : 1;
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f. This can be null if this is an 'unbased'
@ -1815,47 +1876,9 @@ class UnresolvedMemberExpr : public Expr {
/// \brief The type of the base expression; never null.
QualType BaseType;
/// \brief Whether this member expression used the '->' operator or
/// the '.' operator.
bool IsArrow : 1;
/// \brief Whether the lookup results contain an unresolved using
/// declaration.
bool HasUnresolvedUsing : 1;
/// \brief Whether this member expression has explicitly-specified template
/// arguments.
bool HasExplicitTemplateArgs : 1;
/// \brief The location of the '->' or '.' operator.
SourceLocation OperatorLoc;
/// \brief The nested-name-specifier that precedes the member name, if any.
NestedNameSpecifier *Qualifier;
/// \brief The source range covering the nested name specifier.
SourceRange QualifierRange;
/// \brief The member to which this member expression refers, which
/// can be a name or an overloaded operator.
DeclarationName MemberName;
/// \brief The location of the member name.
SourceLocation MemberLoc;
/// \brief Retrieve the explicit template argument list that followed the
/// member template name.
ExplicitTemplateArgumentList *getExplicitTemplateArgs() {
assert(HasExplicitTemplateArgs);
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
const ExplicitTemplateArgumentList *getExplicitTemplateArgs() const {
return const_cast<UnresolvedMemberExpr*>(this)->getExplicitTemplateArgs();
}
UnresolvedMemberExpr(QualType T, bool Dependent,
bool HasUnresolvedUsing,
Expr *Base, QualType BaseType, bool IsArrow,
@ -1877,22 +1900,6 @@ public:
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs);
/// Adds a declaration to the unresolved set. By assumption, all of
/// these happen at initialization time and properties like
/// 'Dependent' and 'HasUnresolvedUsing' take them into account.
void addDecls(UnresolvedSetIterator Begin, UnresolvedSetIterator End) {
Results.append(Begin, End);
}
typedef UnresolvedSetImpl::iterator decls_iterator;
decls_iterator decls_begin() const { return Results.begin(); }
decls_iterator decls_end() const { return Results.end(); }
unsigned getNumDecls() const { return Results.size(); }
/// Retrieves the decls as an unresolved set.
const UnresolvedSetImpl &getDecls() { return Results; }
/// \brief True if this is an implicit access, i.e. one in which the
/// member being accessed was not written in the source. The source
/// location of the operator is invalid in this case.
@ -1917,60 +1924,60 @@ public:
SourceLocation getOperatorLoc() const { return OperatorLoc; }
void setOperatorLoc(SourceLocation L) { OperatorLoc = L; }
/// \brief Retrieve the nested-name-specifier that qualifies the member
/// name.
NestedNameSpecifier *getQualifier() const { return Qualifier; }
/// \brief Retrieve the source range covering the nested-name-specifier
/// that qualifies the member name.
SourceRange getQualifierRange() const { return QualifierRange; }
/// \brief Retrieves the naming class of this lookup.
CXXRecordDecl *getNamingClass() const;
/// \brief Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMemberName() const { return MemberName; }
void setMemberName(DeclarationName N) { MemberName = N; }
DeclarationName getMemberName() const { return getName(); }
void setMemberName(DeclarationName N) { setName(N); }
// \brief Retrieve the location of the name of the member that this
// expression refers to.
SourceLocation getMemberLoc() const { return MemberLoc; }
void setMemberLoc(SourceLocation L) { MemberLoc = L; }
SourceLocation getMemberLoc() const { return getNameLoc(); }
void setMemberLoc(SourceLocation L) { setNameLoc(L); }
/// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>.
bool hasExplicitTemplateArgs() const {
return HasExplicitTemplateArgs;
/// \brief Retrieve the explicit template argument list that followed the
/// member template name.
ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
}
/// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any.
const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
assert(hasExplicitTemplateArgs());
return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1);
}
/// \brief Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs()->copyInto(List);
getExplicitTemplateArgs().copyInto(List);
}
/// \brief Retrieve the location of the left angle bracket following
/// the member name ('<').
SourceLocation getLAngleLoc() const {
return getExplicitTemplateArgs()->LAngleLoc;
return getExplicitTemplateArgs().LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
return getExplicitTemplateArgs()->getTemplateArgs();
return getExplicitTemplateArgs().getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as
/// part of this template-id.
unsigned getNumTemplateArgs() const {
return getExplicitTemplateArgs()->NumTemplateArgs;
return getExplicitTemplateArgs().NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket
/// following the template arguments ('>').
SourceLocation getRAngleLoc() const {
return getExplicitTemplateArgs()->RAngleLoc;
return getExplicitTemplateArgs().RAngleLoc;
}
virtual SourceRange getSourceRange() const {
@ -1980,12 +1987,12 @@ public:
else if (getQualifier())
Range.setBegin(getQualifierRange().getBegin());
else
Range.setBegin(MemberLoc);
Range.setBegin(getMemberLoc());
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
else
Range.setEnd(MemberLoc);
Range.setEnd(getMemberLoc());
return Range;
}
@ -1999,6 +2006,13 @@ public:
virtual child_iterator child_end();
};
inline ExplicitTemplateArgumentList &OverloadExpr::getExplicitTemplateArgs() {
if (isa<UnresolvedLookupExpr>(this))
return cast<UnresolvedLookupExpr>(this)->getExplicitTemplateArgs();
else
return cast<UnresolvedMemberExpr>(this)->getExplicitTemplateArgs();
}
} // end namespace clang
#endif

Просмотреть файл

@ -137,10 +137,9 @@ UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
return ULE;
}
bool UnresolvedLookupExpr::
ComputeDependence(UnresolvedSetImpl::const_iterator Begin,
UnresolvedSetImpl::const_iterator End,
const TemplateArgumentListInfo *Args) {
bool OverloadExpr::ComputeDependence(UnresolvedSetIterator Begin,
UnresolvedSetIterator End,
const TemplateArgumentListInfo *Args) {
for (UnresolvedSetImpl::const_iterator I = Begin; I != End; ++I)
if ((*I)->getDeclContext()->isDependentContext())
return true;
@ -646,15 +645,13 @@ UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent,
DeclarationName MemberName,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(UnresolvedMemberExprClass, T, Dependent, Dependent),
Base(Base), BaseType(BaseType), IsArrow(IsArrow),
HasUnresolvedUsing(HasUnresolvedUsing),
HasExplicitTemplateArgs(TemplateArgs != 0),
OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
MemberName(MemberName), MemberLoc(MemberLoc) {
: OverloadExpr(UnresolvedMemberExprClass, T, Dependent,
Qualifier, QualifierRange, MemberName, MemberLoc,
TemplateArgs != 0),
IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
Base(Base), BaseType(BaseType), OperatorLoc(OperatorLoc) {
if (TemplateArgs)
getExplicitTemplateArgs()->initializeFrom(*TemplateArgs);
getExplicitTemplateArgs().initializeFrom(*TemplateArgs);
}
UnresolvedMemberExpr *
@ -686,8 +683,8 @@ CXXRecordDecl *UnresolvedMemberExpr::getNamingClass() const {
// It can't be dependent: after all, we were actually able to do the
// lookup.
const RecordType *RT;
if (Qualifier) {
Type *T = Qualifier->getAsType();
if (getQualifier()) {
Type *T = getQualifier()->getAsType();
assert(T && "qualifier in member expression does not name type");
RT = T->getAs<RecordType>();
assert(RT && "qualifier in member expression does not name record");

Просмотреть файл

@ -2546,7 +2546,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
bool Dependent =
BaseExprType->isDependentType() ||
R.isUnresolvableResult() ||
UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs);
OverloadExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs);
// Suppress any lookup-related diagnostics; we'll do these when we
// pick a member.

Просмотреть файл

@ -4455,11 +4455,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
Expr *E = FromExpr->IgnoreParens();
if (isa<UnaryOperator>(E))
E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
DeclarationName Name;
if (isa<UnresolvedLookupExpr>(E))
Name = cast<UnresolvedLookupExpr>(E)->getName();
else
Name = cast<UnresolvedMemberExpr>(E)->getMemberName();
DeclarationName Name = cast<OverloadExpr>(E)->getName();
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload)
<< (unsigned) FnKind << FnDesc
@ -4950,7 +4946,7 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
}
}
static bool CheckUnresolvedAccess(Sema &S, Expr *E, NamedDecl *D,
static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, NamedDecl *D,
AccessSpecifier AS) {
if (isa<UnresolvedLookupExpr>(E))
return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D, AS);
@ -4994,50 +4990,28 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
return 0;
// Find the actual overloaded function declaration.
if (From->getType() != Context.OverloadTy)
return 0;
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
Expr *OvlExpr = From->IgnoreParens();
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(OvlExpr)) {
if (UnOp->getOpcode() == UnaryOperator::AddrOf)
OvlExpr = UnOp->getSubExpr()->IgnoreParens();
OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0;
if (OvlExpr->hasExplicitTemplateArgs()) {
OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
ExplicitTemplateArgs = &ETABuffer;
}
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo ExplicitTemplateArgs;
const UnresolvedSetImpl *Fns;
// Look into the overloaded expression.
if (UnresolvedLookupExpr *UL
= dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
Fns = &UL->getDecls();
if (UL->hasExplicitTemplateArgs()) {
HasExplicitTemplateArgs = true;
UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
}
} else if (UnresolvedMemberExpr *ME
= dyn_cast<UnresolvedMemberExpr>(OvlExpr)) {
Fns = &ME->getDecls();
if (ME->hasExplicitTemplateArgs()) {
HasExplicitTemplateArgs = true;
ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
}
} else return 0;
// If we didn't actually find anything, we're done.
if (Fns->empty())
return 0;
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
UnresolvedSet<4> Matches; // contains only FunctionDecls
bool FoundNonTemplateFunction = false;
for (UnresolvedSetIterator I = Fns->begin(), E = Fns->end(); I != E; ++I) {
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
E = OvlExpr->decls_end(); I != E; ++I) {
// Look through any using declarations to find the underlying function.
NamedDecl *Fn = (*I)->getUnderlyingDecl();
@ -5069,8 +5043,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
FunctionDecl *Specialization = 0;
TemplateDeductionInfo Info(Context);
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate,
(HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0),
= DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
FunctionType, Specialization, Info)) {
// FIXME: make a note of the failed deduction for diagnostics.
(void)Result;
@ -5093,7 +5066,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
continue;
// If we have explicit template arguments, skip non-templates.
if (HasExplicitTemplateArgs)
if (OvlExpr->hasExplicitTemplateArgs())
continue;
} else if (IsMember)
continue;
@ -5192,45 +5165,27 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) {
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
Expr *OvlExpr = From->IgnoreParens();
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(OvlExpr)) {
if (UnOp->getOpcode() == UnaryOperator::AddrOf)
OvlExpr = UnOp->getSubExpr()->IgnoreParens();
}
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo ExplicitTemplateArgs;
const UnresolvedSetImpl *Fns;
// Look into the overloaded expression.
if (UnresolvedLookupExpr *UL
= dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
Fns = &UL->getDecls();
if (UL->hasExplicitTemplateArgs()) {
HasExplicitTemplateArgs = true;
UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
}
} else if (UnresolvedMemberExpr *ME
= dyn_cast<UnresolvedMemberExpr>(OvlExpr)) {
Fns = &ME->getDecls();
if (ME->hasExplicitTemplateArgs()) {
HasExplicitTemplateArgs = true;
ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
}
} else return 0;
if (From->getType() != Context.OverloadTy)
return 0;
OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer();
// If we didn't actually find any template-ids, we're done.
if (Fns->empty() || !HasExplicitTemplateArgs)
if (!OvlExpr->hasExplicitTemplateArgs())
return 0;
TemplateArgumentListInfo ExplicitTemplateArgs;
OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
FunctionDecl *Matched = 0;
for (UnresolvedSetIterator I = Fns->begin(), E = Fns->end(); I != E; ++I) {
for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
E = OvlExpr->decls_end(); I != E; ++I) {
// C++0x [temp.arg.explicit]p3:
// [...] In contexts where deduction is done and fails, or in contexts
// where deduction is not done, if a template argument list is

Просмотреть файл

@ -1324,34 +1324,19 @@ static QualType GetTypeOfFunction(ASTContext &Context,
static QualType
ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
Expr *Arg, QualType ParamType) {
bool isAddressOfOperand = false;
llvm::PointerIntPair<OverloadExpr*,1> R = OverloadExpr::find(Arg);
Arg = Arg->IgnoreParens();
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
assert(UnOp->getOpcode() == UnaryOperator::AddrOf);
isAddressOfOperand = true;
Arg = UnOp->getSubExpr()->IgnoreParens();
}
const UnresolvedSetImpl *Decls;
bool HasExplicitArgs;
if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg)) {
Decls = &ULE->getDecls();
HasExplicitArgs = ULE->hasExplicitTemplateArgs();
} else {
UnresolvedMemberExpr *UME = cast<UnresolvedMemberExpr>(Arg);
Decls = &UME->getDecls();
HasExplicitArgs = ULE->hasExplicitTemplateArgs();
}
bool isAddressOfOperand = bool(R.getInt());
OverloadExpr *Ovl = R.getPointer();
// If there were explicit template arguments, we can only find
// something via C++ [temp.arg.explicit]p3, i.e. if the arguments
// unambiguously name a full specialization.
if (HasExplicitArgs) {
if (Ovl->hasExplicitTemplateArgs()) {
// But we can still look for an explicit specialization.
if (FunctionDecl *ExplicitSpec
= S.ResolveSingleFunctionTemplateSpecialization(Arg))
return GetTypeOfFunction(S.Context, isAddressOfOperand, ExplicitSpec);
= S.ResolveSingleFunctionTemplateSpecialization(Ovl))
return GetTypeOfFunction(S.Context, isAddressOfOperand, ExplicitSpec);
return QualType();
}
@ -1365,8 +1350,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
return QualType();
QualType Match;
for (UnresolvedSetIterator I = Decls->begin(),
E = Decls->end(); I != E; ++I) {
for (UnresolvedSetIterator I = Ovl->decls_begin(),
E = Ovl->decls_end(); I != E; ++I) {
NamedDecl *D = (*I)->getUnderlyingDecl();
// - If the argument is an overload set containing one or more