return BuildMemberReferenceExpr(ExprArg(*this, This), ThisType,
/*OpLoc*/ SourceLocation(),
/*IsArrow*/ true,
- SS, R, TemplateArgs);
+ SS,
+ /*FirstQualifierInScope*/ 0,
+ R, TemplateArgs);
}
bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS,
} else {
OwningExprResult Result =
LookupMemberExpr(R, Base, IsArrow, OpLoc,
- SS, FirstQualifierInScope,
- /*ObjCImpDecl*/ DeclPtrTy());
+ SS, /*ObjCImpDecl*/ DeclPtrTy());
if (Result.isInvalid()) {
Owned(Base);
}
return BuildMemberReferenceExpr(ExprArg(*this, Base), BaseType,
- OpLoc, IsArrow, SS, R, TemplateArgs);
+ OpLoc, IsArrow, SS, FirstQualifierInScope,
+ R, TemplateArgs);
}
Sema::OwningExprResult
Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
SourceLocation OpLoc, bool IsArrow,
const CXXScopeSpec &SS,
+ NamedDecl *FirstQualifierInScope,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
Expr *BaseExpr = Base.takeAs<Expr>();
return ExprError();
}
- // Diagnose qualified lookups that find only declarations from a
- // non-base type. Note that it's okay for lookup to find
- // declarations from a non-base type as long as those aren't the
- // ones picked by overload resolution.
- if (SS.isSet() && CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
+ // Diagnose lookups that find only declarations from a non-base
+ // type. This is possible for either qualified lookups (which may
+ // have been qualified with an unrelated type) or implicit member
+ // expressions (which were found with unqualified lookup and thus
+ // may have come from an enclosing scope). Note that it's okay for
+ // lookup to find declarations from a non-base type as long as those
+ // aren't the ones picked by overload resolution.
+ if ((SS.isSet() || !BaseExpr ||
+ (isa<CXXThisExpr>(BaseExpr) &&
+ cast<CXXThisExpr>(BaseExpr)->isImplicit())) &&
+ CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
return ExprError();
// Construct an unresolved result if we in fact got an unresolved
Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
bool &IsArrow, SourceLocation OpLoc,
const CXXScopeSpec &SS,
- NamedDecl *FirstQualifierInScope,
DeclPtrTy ObjCImpDecl) {
assert(BaseExpr && "no base expression");
<< Property->getDeclName();
return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS,
- FirstQualifierInScope, ObjCImpDecl);
+ ObjCImpDecl);
}
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
DecomposeTemplateName(R, Id);
} else {
Result = LookupMemberExpr(R, Base, IsArrow, OpLoc,
- SS, FirstQualifierInScope,
- ObjCImpDecl);
+ SS, ObjCImpDecl);
if (Result.isInvalid()) {
Owned(Base);
}
Result = BuildMemberReferenceExpr(ExprArg(*this, Base), Base->getType(),
- OpLoc, IsArrow, SS, R, TemplateArgs);
+ OpLoc, IsArrow, SS, FirstQualifierInScope,
+ R, TemplateArgs);
}
return move(Result);
QualType BaseType = ((Expr*) Base.get())->getType();
- // FIXME: wait, this is re-performing lookup?
+ LookupResult R(getSema(), Member->getDeclName(), MemberLoc,
+ Sema::LookupMemberName);
+ R.addDecl(Member);
+ R.resolveKind();
+
return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
OpLoc, isArrow,
SS, FirstQualifierInScope,
- Member->getDeclName(), MemberLoc,
- ExplicitTemplateArgs);
+ R, ExplicitTemplateArgs);
}
/// \brief Build a new binary operator expression.
bool IsArrow,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
+ NamedDecl *FirstQualifierInScope,
LookupResult &R,
const TemplateArgumentListInfo *TemplateArgs) {
CXXScopeSpec SS;
return SemaRef.BuildMemberReferenceExpr(move(BaseE), BaseType,
OperatorLoc, IsArrow,
- SS, R, TemplateArgs);
+ SS, FirstQualifierInScope,
+ R, TemplateArgs);
}
/// \brief Build a new Objective-C @encode expression.
SourceLocation FakeOperatorLoc
= SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd());
+ // FIXME: to do this check properly, we will need to preserve the
+ // first-qualifier-in-scope here, just in case we had a dependent
+ // base (and therefore couldn't do the check) and a
+ // nested-name-qualifier (and therefore could do the lookup).
+ NamedDecl *FirstQualifierInScope = 0;
+
return getDerived().RebuildMemberExpr(move(Base), FakeOperatorLoc,
E->isArrow(),
Qualifier,
Member,
(E->hasExplicitTemplateArgumentList()
? &TransArgs : 0),
- 0);
+ FirstQualifierInScope);
}
template<typename Derived>
TransArgs.addArgument(Loc);
}
}
+
+ // FIXME: to do this check properly, we will need to preserve the
+ // first-qualifier-in-scope here, just in case we had a dependent
+ // base (and therefore couldn't do the check) and a
+ // nested-name-qualifier (and therefore could do the lookup).
+ NamedDecl *FirstQualifierInScope = 0;
return getDerived().RebuildUnresolvedMemberExpr(move(Base),
BaseType,
Old->isArrow(),
Qualifier,
Old->getQualifierRange(),
+ FirstQualifierInScope,
R,
(Old->hasExplicitTemplateArgs()
? &TransArgs : 0));