Eliminate the use of OverloadedFunctionDecl in member expressions.

Create a new UnresolvedMemberExpr for these lookups.  Assorted hackery
around qualified member expressions;  this will all go away when we
implement the correct (i.e. extremely delayed) implicit-member semantics.

llvm-svn: 90161
This commit is contained in:
John McCall 2009-11-30 22:42:35 +00:00
parent 120037fec7
commit 10eae1851d
18 changed files with 1049 additions and 546 deletions

View File

@ -73,6 +73,8 @@ public:
return false;
}
unsigned size() const { return Decls.size(); }
typedef DeclsTy::const_iterator iterator;
iterator begin() const { return Decls.begin(); }
iterator end() const { return Decls.end(); }

View File

@ -1617,6 +1617,179 @@ public:
virtual child_iterator child_end();
};
/// \brief Represents a C++ member access expression for which lookup
/// produced a set of overloaded functions. These are replaced with
/// MemberExprs in the final AST.
class UnresolvedMemberExpr : public Expr {
/// The results. These are undesugared, which is to say, they may
/// include UsingShadowDecls.
UnresolvedSet Results;
/// \brief The expression for the base pointer or class reference,
/// e.g., the \c x in x.f.
Stmt *Base;
/// \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, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Member,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs);
public:
static UnresolvedMemberExpr *
Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Member,
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 addDecl(NamedDecl *Decl) {
Results.addDecl(Decl);
}
typedef UnresolvedSet::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(); }
/// \brief Retrieve the base object of this member expressions,
/// e.g., the \c x in \c x.m.
Expr *getBase() { return cast<Expr>(Base); }
void setBase(Expr *E) { Base = E; }
/// \brief Determine whether this member expression used the '->'
/// operator; otherwise, it used the '.' operator.
bool isArrow() const { return IsArrow; }
void setArrow(bool A) { IsArrow = A; }
/// \brief Retrieve the location of the '->' or '.' operator.
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 Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMemberName() const { return MemberName; }
void setMemberName(DeclarationName N) { MemberName = 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; }
/// \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 Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs()->copyInto(List);
}
/// \brief Retrieve the location of the left angle bracket following
/// the member name ('<').
SourceLocation getLAngleLoc() const {
return getExplicitTemplateArgs()->LAngleLoc;
}
/// \brief Retrieve the template arguments provided as part of this
/// template-id.
const TemplateArgumentLoc *getTemplateArgs() const {
return getExplicitTemplateArgs()->getTemplateArgs();
}
/// \brief Retrieve the number of template arguments provided as
/// part of this template-id.
unsigned getNumTemplateArgs() const {
return getExplicitTemplateArgs()->NumTemplateArgs;
}
/// \brief Retrieve the location of the right angle bracket
/// following the template arguments ('>').
SourceLocation getRAngleLoc() const {
return getExplicitTemplateArgs()->RAngleLoc;
}
virtual SourceRange getSourceRange() const {
SourceRange Range = Base->getSourceRange();
if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc());
else
Range.setEnd(MemberLoc);
return Range;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnresolvedMemberExprClass;
}
static bool classof(const UnresolvedMemberExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
} // end namespace clang
#endif

View File

@ -171,6 +171,14 @@ public:
}
virtual ~Stmt() {}
#ifndef NDEBUG
/// \brief True if this statement's refcount is in a valid state.
/// Should be used only in assertions.
bool isRetained() const {
return (RefCount >= 1);
}
#endif
/// \brief Destroy the current statement and its children.
void Destroy(ASTContext &Ctx) {
assert(RefCount >= 1);

View File

@ -133,6 +133,7 @@ EXPR(CXXExprWithTemporaries , Expr)
EXPR(CXXTemporaryObjectExpr , CXXConstructExpr)
EXPR(CXXUnresolvedConstructExpr, Expr)
EXPR(CXXDependentScopeMemberExpr, Expr)
EXPR(UnresolvedMemberExpr , Expr)
// Obj-C Expressions.
EXPR(ObjCStringLiteral , Expr)

View File

@ -2085,6 +2085,8 @@ def err_base_init_direct_and_virtual : Error<
"inherited virtual base class">;
def err_not_direct_base_or_virtual : Error<
"type %0 is not a direct or virtual base of '%1'">;
def err_not_direct_base_or_virtual_multi : Error<
"type %0 is not a direct or virtual base of '%1'">;
def err_in_class_initializer_non_integral_type : Error<
"in-class initializer has non-integral, non-enumeration type %0">;

View File

@ -1525,6 +1525,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
case Expr::CXXTemporaryObjectExprClass:
case Expr::CXXUnresolvedConstructExprClass:
case Expr::CXXDependentScopeMemberExprClass:
case Expr::UnresolvedMemberExprClass:
case Expr::ObjCStringLiteralClass:
case Expr::ObjCEncodeExprClass:
case Expr::ObjCMessageExprClass:

View File

@ -573,3 +573,52 @@ Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() {
Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() {
return child_iterator(&Base + 1);
}
UnresolvedMemberExpr::UnresolvedMemberExpr(QualType T, bool Dependent,
bool HasUnresolvedUsing,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName MemberName,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs)
: Expr(UnresolvedMemberExprClass, T, Dependent, Dependent),
Base(Base), IsArrow(IsArrow), HasUnresolvedUsing(HasUnresolvedUsing),
HasExplicitTemplateArgs(TemplateArgs != 0),
OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange),
MemberName(MemberName), MemberLoc(MemberLoc) {
if (TemplateArgs)
getExplicitTemplateArgs()->initializeFrom(*TemplateArgs);
}
UnresolvedMemberExpr *
UnresolvedMemberExpr::Create(ASTContext &C, bool Dependent,
bool HasUnresolvedUsing,
Expr *Base, bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
DeclarationName Member,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs) {
std::size_t size = sizeof(UnresolvedMemberExpr);
if (TemplateArgs)
size += ExplicitTemplateArgumentList::sizeFor(*TemplateArgs);
void *Mem = C.Allocate(size, llvm::alignof<UnresolvedMemberExpr>());
return new (Mem) UnresolvedMemberExpr(
Dependent ? C.DependentTy : C.OverloadTy,
Dependent, HasUnresolvedUsing, Base, IsArrow,
OperatorLoc, Qualifier, QualifierRange,
Member, MemberLoc, TemplateArgs);
}
Stmt::child_iterator UnresolvedMemberExpr::child_begin() {
return child_iterator(&Base);
}
Stmt::child_iterator UnresolvedMemberExpr::child_end() {
return child_iterator(&Base + 1);
}

View File

@ -1163,6 +1163,24 @@ void StmtPrinter::VisitCXXDependentScopeMemberExpr(
}
}
void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
PrintExpr(Node->getBase());
OS << (Node->isArrow() ? "->" : ".");
if (NestedNameSpecifier *Qualifier = Node->getQualifier())
Qualifier->print(OS, Policy);
// FIXME: this might originally have been written with 'template'
OS << Node->getMemberName().getAsString();
if (Node->hasExplicitTemplateArgs()) {
OS << TemplateSpecializationType::PrintTemplateArgumentList(
Node->getTemplateArgs(),
Node->getNumTemplateArgs(),
Policy);
}
}
static const char *getTypeTraitName(UnaryTypeTrait UTT) {
switch (UTT) {
default: assert(false && "Unknown type trait");

View File

@ -558,6 +558,19 @@ StmtProfiler::VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *S) {
ID.AddBoolean(S->isArrow());
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getMember());
ID.AddBoolean(S->hasExplicitTemplateArgumentList());
if (S->hasExplicitTemplateArgumentList())
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *S) {
VisitExpr(S);
ID.AddBoolean(S->isArrow());
VisitNestedNameSpecifier(S->getQualifier());
VisitName(S->getMemberName());
ID.AddBoolean(S->hasExplicitTemplateArgs());
if (S->hasExplicitTemplateArgs())
VisitTemplateArguments(S->getTemplateArgs(), S->getNumTemplateArgs());
}
void StmtProfiler::VisitObjCStringLiteral(ObjCStringLiteral *S) {

View File

@ -213,6 +213,10 @@ public:
return getResultKind() == FoundOverloaded;
}
bool isUnresolvableResult() const {
return getResultKind() == FoundUnresolvedValue;
}
LookupResultKind getResultKind() const {
sanity();
return ResultKind;

View File

@ -459,13 +459,20 @@ public:
virtual void DeleteExpr(ExprTy *E);
virtual void DeleteStmt(StmtTy *S);
OwningExprResult Owned(Expr* E) { return OwningExprResult(*this, E); }
OwningExprResult Owned(Expr* E) {
assert(!E || E->isRetained());
return OwningExprResult(*this, E);
}
OwningExprResult Owned(ExprResult R) {
if (R.isInvalid())
return ExprError();
assert(!R.get() || ((Expr*) R.get())->isRetained());
return OwningExprResult(*this, R.get());
}
OwningStmtResult Owned(Stmt* S) { return OwningStmtResult(*this, S); }
OwningStmtResult Owned(Stmt* S) {
assert(!S || S->isRetained());
return OwningStmtResult(*this, S);
}
virtual void ActOnEndOfTranslationUnit();
@ -516,7 +523,7 @@ public:
/// \brief Create a LocInfoType to hold the given QualType and DeclaratorInfo.
QualType CreateLocInfoType(QualType T, DeclaratorInfo *DInfo);
DeclarationName GetNameForDeclarator(Declarator &D);
DeclarationName GetNameFromUnqualifiedId(UnqualifiedId &Name);
DeclarationName GetNameFromUnqualifiedId(const UnqualifiedId &Name);
static QualType GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo = 0);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
@ -1517,31 +1524,40 @@ public:
ExprArg Idx,
SourceLocation RLoc);
OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
DeclarationName MemberName,
DeclPtrTy ImplDecl,
const CXXScopeSpec *SS = 0,
NamedDecl *FirstQualifierInScope = 0) {
// FIXME: Temporary helper while we migrate existing calls to
// BuildMemberReferenceExpr to support explicitly-specified template
// arguments.
return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc,
MemberName, 0, ImplDecl, SS,
FirstQualifierInScope);
}
bool IsArrow,
const CXXScopeSpec &SS,
NamedDecl *FirstQualifierInScope,
DeclarationName Name,
SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs);
OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base,
OwningExprResult BuildMemberReferenceExpr(ExprArg Base,
SourceLocation OpLoc, bool IsArrow,
const CXXScopeSpec &SS,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs);
OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base,
bool IsArrow, SourceLocation OpLoc,
const CXXScopeSpec &SS,
NamedDecl *FirstQualifierInScope,
DeclPtrTy ObjCImpDecl);
bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
const LookupResult &R);
OwningExprResult ActOnDependentMemberExpr(ExprArg Base,
bool IsArrow,
SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
DeclarationName MemberName,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
DeclPtrTy ImplDecl,
const CXXScopeSpec *SS,
NamedDecl *FirstQualifierInScope = 0);
const CXXScopeSpec &SS,
NamedDecl *FirstQualifierInScope,
DeclarationName Name,
SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs);
virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
@ -2140,9 +2156,7 @@ public:
FunctionDecl::StorageClass& SC);
DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion);
bool isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
SourceLocation NameLoc, QualType &ThisType,
QualType &MemberType);
bool isImplicitMemberReference(const LookupResult &R, QualType &ThisType);
//===--------------------------------------------------------------------===//
// C++ Derived Classes

View File

@ -1757,7 +1757,7 @@ DeclarationName Sema::GetNameForDeclarator(Declarator &D) {
}
/// \brief Retrieves the canonicalized name from a parsed unqualified-id.
DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) {
DeclarationName Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) {
switch (Name.getKind()) {
case UnqualifiedId::IK_Identifier:
return DeclarationName(Name.Identifier);

File diff suppressed because it is too large Load Diff

View File

@ -2236,9 +2236,6 @@ Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
///
/// FIXME: Should Objective-C also use this approach?
///
/// \param SS if non-NULL, the C++ nested-name-specifier that precedes the
/// name of the declaration referenced.
///
/// \param D the declaration being referenced from the current scope.
///
/// \param NameLoc the location of the name in the source.
@ -2247,16 +2244,11 @@ Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
/// access, will be set to the type of the "this" pointer to be used when
/// building that implicit member access.
///
/// \param MemberType if the reference to this declaration is an implicit
/// member access, will be set to the type of the member being referenced
/// (for use at the type of the resulting member access expression).
///
/// \returns true if this is an implicit member reference (in which case
/// \p ThisType and \p MemberType will be set), or false if it is not an
/// implicit member reference.
bool Sema::isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
SourceLocation NameLoc, QualType &ThisType,
QualType &MemberType) {
bool Sema::isImplicitMemberReference(const LookupResult &R,
QualType &ThisType) {
// If this isn't a C++ method, then it isn't an implicit member reference.
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext);
if (!MD || MD->isStatic())
@ -2269,33 +2261,21 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
// class member access expression (5.2.5) using (*this) (9.3.2)
// as the postfix-expression to the left of the '.' operator.
DeclContext *Ctx = 0;
if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
if (R.isUnresolvableResult()) {
// FIXME: this is just picking one at random
Ctx = R.getRepresentativeDecl()->getDeclContext();
} else if (FieldDecl *FD = R.getAsSingle<FieldDecl>()) {
Ctx = FD->getDeclContext();
MemberType = FD->getType();
if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>())
MemberType = RefType->getPointeeType();
else if (!FD->isMutable())
MemberType
= Context.getQualifiedType(MemberType,
Qualifiers::fromCVRMask(MD->getTypeQualifiers()));
} else if (isa<UnresolvedUsingValueDecl>(D)) {
Ctx = D->getDeclContext();
MemberType = Context.DependentTy;
} else {
for (OverloadIterator Ovl(D), OvlEnd; Ovl != OvlEnd; ++Ovl) {
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl);
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I);
FunctionTemplateDecl *FunTmpl = 0;
if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)))
if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*I)))
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
// FIXME: Do we have to know if there are explicit template arguments?
if (Method && !Method->isStatic()) {
Ctx = Method->getParent();
if (isa<CXXMethodDecl>(D) && !FunTmpl)
MemberType = Method->getType();
else
MemberType = Context.OverloadTy;
break;
}
}
@ -2307,6 +2287,8 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec &SS, NamedDecl *D,
// Determine whether the declaration(s) we found are actually in a base
// class. If not, this isn't an implicit member reference.
ThisType = MD->getThisType(Context);
// FIXME: this doesn't really work for overloaded lookups.
QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx));
QualType ClassType

View File

@ -4341,9 +4341,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
llvm::SmallVector<NamedDecl*,8> Fns;
// Try to dig out the overloaded function.
OverloadedFunctionDecl *Ovl = 0;
FunctionTemplateDecl *FunctionTemplate = 0;
// Look into the overloaded expression.
if (UnresolvedLookupExpr *UL
= dyn_cast<UnresolvedLookupExpr>(OvlExpr)) {
Fns.append(UL->decls_begin(), UL->decls_end());
@ -4351,17 +4349,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
HasExplicitTemplateArgs = true;
UL->copyTemplateArgumentsInto(ExplicitTemplateArgs);
}
} else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) {
Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());
FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());
HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList();
if (HasExplicitTemplateArgs)
} else if (UnresolvedMemberExpr *ME
= dyn_cast<UnresolvedMemberExpr>(OvlExpr)) {
Fns.append(ME->decls_begin(), ME->decls_end());
if (ME->hasExplicitTemplateArgs()) {
HasExplicitTemplateArgs = true;
ME->copyTemplateArgumentsInto(ExplicitTemplateArgs);
}
}
if (Ovl) Fns.append(Ovl->function_begin(), Ovl->function_end());
if (FunctionTemplate) Fns.push_back(FunctionTemplate);
// If we didn't actually find anything, we're done.
if (Fns.empty())
return 0;
@ -5133,29 +5129,34 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
SourceLocation RParenLoc) {
// Dig out the member expression. This holds both the object
// argument and the member function we're referring to.
MemberExpr *MemExpr = 0;
if (ParenExpr *ParenE = dyn_cast<ParenExpr>(MemExprE))
MemExpr = dyn_cast<MemberExpr>(ParenE->getSubExpr());
else
MemExpr = dyn_cast<MemberExpr>(MemExprE);
assert(MemExpr && "Building member call without member expression");
Expr *NakedMemExpr = MemExprE->IgnoreParens();
// Extract the object argument.
Expr *ObjectArg = MemExpr->getBase();
Expr *ObjectArg;
MemberExpr *MemExpr;
CXXMethodDecl *Method = 0;
if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
isa<FunctionTemplateDecl>(MemExpr->getMemberDecl())) {
if (isa<MemberExpr>(NakedMemExpr)) {
MemExpr = cast<MemberExpr>(NakedMemExpr);
ObjectArg = MemExpr->getBase();
Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
} else {
UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
ObjectArg = UnresExpr->getBase();
// Add overload candidates
OverloadCandidateSet CandidateSet;
DeclarationName DeclName = MemExpr->getMemberDecl()->getDeclName();
for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd;
Func != FuncEnd; ++Func) {
if ((Method = dyn_cast<CXXMethodDecl>(*Func))) {
for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(),
E = UnresExpr->decls_end(); I != E; ++I) {
// TODO: note if we found something through a using declaration
NamedDecl *Func = (*I)->getUnderlyingDecl();
if ((Method = dyn_cast<CXXMethodDecl>(Func))) {
// If explicit template arguments were provided, we can't call a
// non-template member function.
if (MemExpr->hasExplicitTemplateArgumentList())
if (UnresExpr->hasExplicitTemplateArgs())
continue;
AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet,
@ -5163,11 +5164,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
} else {
// FIXME: avoid copy.
TemplateArgumentListInfo TemplateArgs;
if (MemExpr->hasExplicitTemplateArgumentList())
MemExpr->copyTemplateArgumentsInto(TemplateArgs);
if (UnresExpr->hasExplicitTemplateArgs())
UnresExpr->copyTemplateArgumentsInto(TemplateArgs);
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func),
(MemExpr->hasExplicitTemplateArgumentList()
AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func),
(UnresExpr->hasExplicitTemplateArgs()
? &TemplateArgs : 0),
ObjectArg, Args, NumArgs,
CandidateSet,
@ -5175,14 +5176,16 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
}
}
DeclarationName DeclName = UnresExpr->getMemberName();
OverloadCandidateSet::iterator Best;
switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) {
switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
break;
case OR_No_Viable_Function:
Diag(MemExpr->getSourceRange().getBegin(),
Diag(UnresExpr->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< DeclName << MemExprE->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
@ -5190,16 +5193,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
return true;
case OR_Ambiguous:
Diag(MemExpr->getSourceRange().getBegin(),
diag::err_ovl_ambiguous_member_call)
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
// FIXME: Leaking incoming expressions!
return true;
case OR_Deleted:
Diag(MemExpr->getSourceRange().getBegin(),
diag::err_ovl_deleted_member_call)
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
<< DeclName << MemExprE->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
@ -5208,13 +5209,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
}
MemExprE = FixOverloadedFunctionReference(MemExprE, Method);
if (ParenExpr *ParenE = dyn_cast<ParenExpr>(MemExprE))
MemExpr = dyn_cast<MemberExpr>(ParenE->getSubExpr());
else
MemExpr = dyn_cast<MemberExpr>(MemExprE);
} else {
Method = dyn_cast<CXXMethodDecl>(MemExpr->getMemberDecl());
MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens());
}
assert(Method && "Member call to something that isn't a method?");
@ -5660,15 +5655,10 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
Fn->getType());
}
if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {
assert((isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
isa<FunctionTemplateDecl>(MemExpr->getMemberDecl()) ||
isa<FunctionDecl>(MemExpr->getMemberDecl())) &&
"Expected member function or member function template");
if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
// FIXME: avoid copy.
TemplateArgumentListInfo TemplateArgs;
if (MemExpr->hasExplicitTemplateArgumentList())
if (MemExpr->hasExplicitTemplateArgs())
MemExpr->copyTemplateArgumentsInto(TemplateArgs);
return MemberExpr::Create(Context, MemExpr->getBase()->Retain(),
@ -5677,7 +5667,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
MemExpr->getQualifierRange(),
Fn,
MemExpr->getMemberLoc(),
(MemExpr->hasExplicitTemplateArgumentList()
(MemExpr->hasExplicitTemplateArgs()
? &TemplateArgs : 0),
Fn->getType());
}

View File

@ -867,13 +867,10 @@ public:
= SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(DestroyedType));
return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base),
OperatorLoc,
isArrow? tok::arrow : tok::period,
DestroyedTypeLoc,
Name,
Sema::DeclPtrTy::make((Decl *)0),
&SS);
return getSema().BuildMemberReferenceExpr(move(Base), OperatorLoc, isArrow,
SS, /*FIXME: FirstQualifier*/ 0,
Name, DestroyedTypeLoc,
/*TemplateArgs*/ 0);
}
/// \brief Build a new unary operator expression.
@ -967,14 +964,10 @@ public:
SS.setScopeRep(Qualifier);
}
return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
isArrow? tok::arrow : tok::period,
MemberLoc,
Member->getDeclName(),
ExplicitTemplateArgs,
/*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
&SS,
FirstQualifierInScope);
return getSema().BuildMemberReferenceExpr(move(Base), OpLoc, isArrow,
SS, FirstQualifierInScope,
Member->getDeclName(), MemberLoc,
ExplicitTemplateArgs);
}
/// \brief Build a new binary operator expression.
@ -1049,10 +1042,13 @@ public:
SourceLocation OpLoc,
SourceLocation AccessorLoc,
IdentifierInfo &Accessor) {
return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc,
tok::period, AccessorLoc,
CXXScopeSpec SS;
return getSema().BuildMemberReferenceExpr(move(Base),
OpLoc, /*IsArrow*/ false,
SS, /*FirstQualifierInScope*/ 0,
DeclarationName(&Accessor),
/*FIXME?*/Sema::DeclPtrTy::make((Decl*)0));
AccessorLoc,
/* TemplateArgs */ 0);
}
/// \brief Build a new initializer list expression.
@ -1530,67 +1526,38 @@ public:
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
NamedDecl *FirstQualifierInScope,
DeclarationName Name,
SourceLocation MemberLoc,
NamedDecl *FirstQualifierInScope) {
OwningExprResult Base = move(BaseE);
tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period;
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
SS.setRange(QualifierRange);
SS.setScopeRep(Qualifier);
return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0,
move(Base), OperatorLoc, OpKind,
MemberLoc,
Name,
/*FIXME?*/Sema::DeclPtrTy::make((Decl*)0),
&SS,
FirstQualifierInScope);
return SemaRef.BuildMemberReferenceExpr(move(BaseE), OperatorLoc, IsArrow,
SS, FirstQualifierInScope,
Name, MemberLoc, TemplateArgs);
}
/// \brief Build a new member reference expression with explicit template
/// arguments.
/// \brief Build a new member reference expression.
///
/// By default, performs semantic analysis to build the new expression.
/// Subclasses may override this routine to provide different behavior.
OwningExprResult RebuildCXXDependentScopeMemberExpr(ExprArg BaseE,
bool IsArrow,
SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
TemplateName Template,
SourceLocation TemplateNameLoc,
NamedDecl *FirstQualifierInScope,
const TemplateArgumentListInfo &TemplateArgs) {
OwningExprResult RebuildUnresolvedMemberExpr(ExprArg BaseE,
SourceLocation OperatorLoc,
bool IsArrow,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
OwningExprResult Base = move(BaseE);
tok::TokenKind OpKind = IsArrow? tok::arrow : tok::period;
CXXScopeSpec SS;
SS.setRange(QualifierRange);
SS.setScopeRep(Qualifier);
// FIXME: We're going to end up looking up the template based on its name,
// twice! Also, duplicates part of Sema::BuildMemberAccessExpr.
DeclarationName Name;
if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl())
Name = ActualTemplate->getDeclName();
else if (OverloadedFunctionDecl *Ovl
= Template.getAsOverloadedFunctionDecl())
Name = Ovl->getDeclName();
else {
DependentTemplateName *DTN = Template.getAsDependentTemplateName();
if (DTN->isIdentifier())
Name = DTN->getIdentifier();
else
Name = SemaRef.Context.DeclarationNames.getCXXOperatorName(
DTN->getOperator());
}
return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0, move(Base),
OperatorLoc, OpKind,
TemplateNameLoc, Name,
&TemplateArgs,
Sema::DeclPtrTy(), &SS);
return SemaRef.BuildMemberReferenceExpr(move(Base), OperatorLoc, IsArrow,
SS, R, TemplateArgs);
}
/// \brief Build a new Objective-C @encode expression.
@ -4903,28 +4870,12 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
E->getOperatorLoc(),
Qualifier,
E->getQualifierRange(),
FirstQualifierInScope,
Name,
E->getMemberLoc(),
FirstQualifierInScope);
/*TemplateArgs*/ 0);
}
// FIXME: This is an ugly hack, which forces the same template name to
// be looked up multiple times. Yuck!
TemporaryBase Rebase(*this, E->getMemberLoc(), DeclarationName());
TemplateName OrigTemplateName;
if (const IdentifierInfo *II = Name.getAsIdentifierInfo())
OrigTemplateName = SemaRef.Context.getDependentTemplateName(0, II);
else
OrigTemplateName
= SemaRef.Context.getDependentTemplateName(0,
Name.getCXXOverloadedOperator());
TemplateName Template
= getDerived().TransformTemplateName(OrigTemplateName,
QualType::getFromOpaquePtr(ObjectType));
if (Template.isNull())
return SemaRef.ExprError();
TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc());
for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
TemplateArgumentLoc Loc;
@ -4938,10 +4889,75 @@ TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr(
E->getOperatorLoc(),
Qualifier,
E->getQualifierRange(),
Template,
E->getMemberLoc(),
FirstQualifierInScope,
TransArgs);
Name,
E->getMemberLoc(),
&TransArgs);
}
template<typename Derived>
Sema::OwningExprResult
TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old,
bool isAddressOfOperand) {
// Transform the base of the expression.
OwningExprResult Base = getDerived().TransformExpr(Old->getBase());
if (Base.isInvalid())
return SemaRef.ExprError();
NestedNameSpecifier *Qualifier = 0;
if (Old->getQualifier()) {
Qualifier
= getDerived().TransformNestedNameSpecifier(Old->getQualifier(),
Old->getQualifierRange());
if (Qualifier == 0)
return SemaRef.ExprError();
}
LookupResult R(SemaRef, Old->getMemberName(), Old->getMemberLoc(),
Sema::LookupOrdinaryName);
// Transform all the decls.
for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
E = Old->decls_end(); I != E; ++I) {
NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I));
if (!InstD)
return SemaRef.ExprError();
// Expand using declarations.
if (isa<UsingDecl>(InstD)) {
UsingDecl *UD = cast<UsingDecl>(InstD);
for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
E = UD->shadow_end(); I != E; ++I)
R.addDecl(*I);
continue;
}
R.addDecl(InstD);
}
R.resolveKind();
TemplateArgumentListInfo TransArgs;
if (Old->hasExplicitTemplateArgs()) {
TransArgs.setLAngleLoc(Old->getLAngleLoc());
TransArgs.setRAngleLoc(Old->getRAngleLoc());
for (unsigned I = 0, N = Old->getNumTemplateArgs(); I != N; ++I) {
TemplateArgumentLoc Loc;
if (getDerived().TransformTemplateArgument(Old->getTemplateArgs()[I],
Loc))
return SemaRef.ExprError();
TransArgs.addArgument(Loc);
}
}
return getDerived().RebuildUnresolvedMemberExpr(move(Base),
Old->getOperatorLoc(),
Old->isArrow(),
Qualifier,
Old->getQualifierRange(),
R,
(Old->hasExplicitTemplateArgs()
? &TransArgs : 0));
}
template<typename Derived>

View File

@ -48,7 +48,7 @@ namespace C
a.A::sub::x();
a.A::B::base::x();
a.bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''struct A::sub''}}
a.bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''A::sub''}}
a->foo();
a->member::foo();
@ -69,7 +69,7 @@ namespace C
a->A::sub::x();
a->A::B::base::x();
a->bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''struct A::sub''}}
a->bad::x(); // expected-error{{type 'struct bad' is not a direct or virtual base of ''A::sub''}}
(*a)->foo();
(*a)->member::foo();

View File

@ -95,7 +95,9 @@ struct X0 : X0Base {
template<typename U>
struct X1 : X0<U> {
int &f2() {
return X0Base::f(); // expected-error{{call to non-static member function without an object argument}}
// FIXME: We should be able to do this lookup and diagnose the error
// *despite* the fact that we can't decide the relationship yet.
return X0Base::f(); // expected-FIXME-error{{call to non-static member function without an object argument}}
}
};