forked from OSchip/llvm-project
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:
parent
120037fec7
commit
10eae1851d
|
@ -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(); }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -213,6 +213,10 @@ public:
|
|||
return getResultKind() == FoundOverloaded;
|
||||
}
|
||||
|
||||
bool isUnresolvableResult() const {
|
||||
return getResultKind() == FoundUnresolvedValue;
|
||||
}
|
||||
|
||||
LookupResultKind getResultKind() const {
|
||||
sanity();
|
||||
return ResultKind;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue