aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h47
-rw-r--r--lib/AST/Expr.cpp51
-rw-r--r--lib/Sema/Sema.h16
-rw-r--r--lib/Sema/SemaAccess.cpp25
-rw-r--r--lib/Sema/SemaCXXCast.cpp9
-rw-r--r--lib/Sema/SemaDeclCXX.cpp8
-rw-r--r--lib/Sema/SemaExpr.cpp130
-rw-r--r--lib/Sema/SemaExprCXX.cpp13
-rw-r--r--lib/Sema/SemaInit.cpp27
-rw-r--r--lib/Sema/SemaInit.h3
-rw-r--r--lib/Sema/SemaOverload.cpp68
-rw-r--r--lib/Sema/SemaStmt.cpp41
-rw-r--r--lib/Sema/SemaTemplate.cpp7
-rw-r--r--lib/Sema/SemaType.cpp4
-rw-r--r--lib/Sema/TreeTransform.h20
-rw-r--r--test/CXX/class.access/p4.cpp18
16 files changed, 338 insertions, 149 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 39530dba36..96436f511b 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1263,6 +1263,11 @@ public:
/// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F.
///
class MemberExpr : public Expr {
+ /// Extra data stored in some member expressions.
+ struct MemberNameQualifier : public NameQualifier {
+ NamedDecl *FoundDecl;
+ };
+
/// Base - the expression for the base pointer or structure references. In
/// X.F, this is "X".
Stmt *Base;
@@ -1278,27 +1283,26 @@ class MemberExpr : public Expr {
bool IsArrow : 1;
/// \brief True if this member expression used a nested-name-specifier to
- /// refer to the member, e.g., "x->Base::f". When true, a NameQualifier
+ /// refer to the member, e.g., "x->Base::f", or found its member via a using
+ /// declaration. When true, a MemberNameQualifier
/// structure is allocated immediately after the MemberExpr.
- bool HasQualifier : 1;
+ bool HasQualifierOrFoundDecl : 1;
/// \brief True if this member expression specified a template argument list
/// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList
/// structure (and its TemplateArguments) are allocated immediately after
/// the MemberExpr or, if the member expression also has a qualifier, after
- /// the NameQualifier structure.
+ /// the MemberNameQualifier structure.
bool HasExplicitTemplateArgumentList : 1;
/// \brief Retrieve the qualifier that preceded the member name, if any.
- NameQualifier *getMemberQualifier() {
- if (!HasQualifier)
- return 0;
-
- return reinterpret_cast<NameQualifier *> (this + 1);
+ MemberNameQualifier *getMemberQualifier() {
+ assert(HasQualifierOrFoundDecl);
+ return reinterpret_cast<MemberNameQualifier *> (this + 1);
}
/// \brief Retrieve the qualifier that preceded the member name, if any.
- const NameQualifier *getMemberQualifier() const {
+ const MemberNameQualifier *getMemberQualifier() const {
return const_cast<MemberExpr *>(this)->getMemberQualifier();
}
@@ -1308,7 +1312,7 @@ class MemberExpr : public Expr {
if (!HasExplicitTemplateArgumentList)
return 0;
- if (!HasQualifier)
+ if (!HasQualifierOrFoundDecl)
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
return reinterpret_cast<ExplicitTemplateArgumentList *>(
@@ -1321,26 +1325,22 @@ class MemberExpr : public Expr {
return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList();
}
- MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
- SourceRange qualrange, ValueDecl *memberdecl, SourceLocation l,
- const TemplateArgumentListInfo *targs, QualType ty);
-
public:
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
SourceLocation l, QualType ty)
: Expr(MemberExprClass, ty,
base->isTypeDependent(), base->isValueDependent()),
Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
- HasQualifier(false), HasExplicitTemplateArgumentList(false) {}
+ HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
/// \brief Build an empty member reference expression.
explicit MemberExpr(EmptyShell Empty)
- : Expr(MemberExprClass, Empty), HasQualifier(false),
+ : Expr(MemberExprClass, Empty), HasQualifierOrFoundDecl(false),
HasExplicitTemplateArgumentList(false) { }
static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifier *qual, SourceRange qualrange,
- ValueDecl *memberdecl,
+ ValueDecl *memberdecl, NamedDecl *founddecl,
SourceLocation l,
const TemplateArgumentListInfo *targs,
QualType ty);
@@ -1355,16 +1355,23 @@ public:
ValueDecl *getMemberDecl() const { return MemberDecl; }
void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
+ /// \brief Retrieves the declaration found by lookup.
+ NamedDecl *getFoundDecl() const {
+ if (!HasQualifierOrFoundDecl)
+ return getMemberDecl();
+ return getMemberQualifier()->FoundDecl;
+ }
+
/// \brief Determines whether this member expression actually had
/// a C++ nested-name-specifier prior to the name of the member, e.g.,
/// x->Base::foo.
- bool hasQualifier() const { return HasQualifier; }
+ bool hasQualifier() const { return getQualifier() != 0; }
/// \brief If the member name was qualified, retrieves the source range of
/// the nested-name-specifier that precedes the member name. Otherwise,
/// returns an empty source range.
SourceRange getQualifierRange() const {
- if (!HasQualifier)
+ if (!HasQualifierOrFoundDecl)
return SourceRange();
return getMemberQualifier()->Range;
@@ -1374,7 +1381,7 @@ public:
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
NestedNameSpecifier *getQualifier() const {
- if (!HasQualifier)
+ if (!HasQualifierOrFoundDecl)
return 0;
return getMemberQualifier()->NNS;
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 935a2080dc..a9b5f36a98 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -499,44 +499,45 @@ QualType CallExpr::getCallReturnType() const {
return FnType->getResultType();
}
-MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
- SourceRange qualrange, ValueDecl *memberdecl,
- SourceLocation l, const TemplateArgumentListInfo *targs,
- QualType ty)
- : Expr(MemberExprClass, ty,
- base->isTypeDependent() || (qual && qual->isDependent()),
- base->isValueDependent() || (qual && qual->isDependent())),
- Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
- HasQualifier(qual != 0), HasExplicitTemplateArgumentList(targs) {
- // Initialize the qualifier, if any.
- if (HasQualifier) {
- NameQualifier *NQ = getMemberQualifier();
- NQ->NNS = qual;
- NQ->Range = qualrange;
- }
-
- // Initialize the explicit template argument list, if any.
- if (targs)
- getExplicitTemplateArgumentList()->initializeFrom(*targs);
-}
-
MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
NestedNameSpecifier *qual,
SourceRange qualrange,
ValueDecl *memberdecl,
+ NamedDecl *founddecl,
SourceLocation l,
const TemplateArgumentListInfo *targs,
QualType ty) {
std::size_t Size = sizeof(MemberExpr);
- if (qual != 0)
- Size += sizeof(NameQualifier);
+
+ bool hasQualOrFound = (qual != 0 || founddecl != memberdecl);
+ if (hasQualOrFound)
+ Size += sizeof(MemberNameQualifier);
if (targs)
Size += ExplicitTemplateArgumentList::sizeFor(*targs);
void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
- return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
- targs, ty);
+ MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, l, ty);
+
+ if (hasQualOrFound) {
+ if (qual && qual->isDependent()) {
+ E->setValueDependent(true);
+ E->setTypeDependent(true);
+ }
+ E->HasQualifierOrFoundDecl = true;
+
+ MemberNameQualifier *NQ = E->getMemberQualifier();
+ NQ->NNS = qual;
+ NQ->Range = qualrange;
+ NQ->FoundDecl = founddecl;
+ }
+
+ if (targs) {
+ E->HasExplicitTemplateArgumentList = true;
+ E->getExplicitTemplateArgumentList()->initializeFrom(*targs);
+ }
+
+ return E;
}
const char *CastExpr::getCastKindName() const {
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 859e497576..d3e55f381e 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1119,6 +1119,7 @@ public:
CXXRecordDecl *ActingContext);
bool PerformObjectArgumentInitialization(Expr *&From,
NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
CXXMethodDecl *Method);
ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From);
@@ -1126,6 +1127,7 @@ public:
bool PerformObjectMemberConversion(Expr *&From,
NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
NamedDecl *Member);
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
@@ -1246,11 +1248,15 @@ public:
const PartialDiagnostic &PDiag);
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
- bool Complain);
+ bool Complain,
+ DeclAccessPair &Found);
FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From);
- Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
+ Expr *FixOverloadedFunctionReference(Expr *E,
+ NamedDecl *FoundDecl,
+ FunctionDecl *Fn);
OwningExprResult FixOverloadedFunctionReference(OwningExprResult,
+ NamedDecl *FoundDecl,
FunctionDecl *Fn);
void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
@@ -2395,7 +2401,9 @@ public:
Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
QualType EncodedType,
SourceLocation RParenLoc);
- CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp, CXXMethodDecl *Method);
+ CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp,
+ NamedDecl *FoundDecl,
+ CXXMethodDecl *Method);
virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
SourceLocation EncodeLoc,
@@ -2640,6 +2648,8 @@ public:
Expr *ObjectExpr,
Expr *ArgExpr,
DeclAccessPair FoundDecl);
+ AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr,
+ DeclAccessPair FoundDecl);
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
QualType Base, QualType Derived,
const CXXBasePath &Path,
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index e7ea204137..e356c52a68 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -907,6 +907,31 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
return CheckAccess(*this, OpLoc, Entity);
}
+Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
+ DeclAccessPair Found) {
+ if (!getLangOptions().AccessControl ||
+ Found.getAccess() == AS_public)
+ return AR_accessible;
+
+ OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer();
+ NestedNameSpecifier *Qualifier = Ovl->getQualifier();
+ assert(Qualifier && "address of overloaded member without qualifier");
+
+ CXXScopeSpec SS;
+ SS.setScopeRep(Qualifier);
+ SS.setRange(Ovl->getQualifierRange());
+ DeclContext *DC = computeDeclContext(SS);
+ assert(DC && DC->isRecord() && "scope did not resolve to record");
+ CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(DC);
+
+ AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, Found);
+ Entity.setDiag(diag::err_access)
+ << Ovl->getSourceRange();
+
+ return CheckAccess(*this, Ovl->getNameLoc(), Entity);
+}
+
+
/// Checks access for a hierarchy conversion.
///
/// \param IsBaseToDerived whether this is a base-to-derived conversion (true)
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 2b93d38e2a..11c8e6ddab 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -808,8 +808,10 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
return TC_NotApplicable;
bool WasOverloadedFunction = false;
+ DeclAccessPair FoundOverload;
if (FunctionDecl *Fn
- = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false)) {
+ = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
+ FoundOverload)) {
CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
SrcType = Self.Context.getMemberPointerType(Fn->getType(),
Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
@@ -870,13 +872,14 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
// allowing complaints if something goes wrong.
FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr,
DestType,
- true);
+ true,
+ FoundOverload);
if (!Fn) {
msg = 0;
return TC_Failed;
}
- SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, Fn);
+ SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
if (!SrcExpr) {
msg = 0;
return TC_Failed;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 49352b5f4e..dfaa85559b 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4409,16 +4409,18 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// to resolve the overloaded function. If all goes well, T2 is the
// type of the resulting function.
if (Context.getCanonicalType(T2) == Context.OverloadTy) {
+ DeclAccessPair Found;
FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Init, DeclType,
- ICS != 0);
+ ICS != 0, Found);
if (Fn) {
// Since we're performing this reference-initialization for
// real, update the initializer with the resulting function.
if (!ICS) {
if (DiagnoseUseOfDecl(Fn, DeclLoc))
- return true;
+ return true;
- Init = FixOverloadedFunctionReference(Init, Fn);
+ CheckAddressOfMemberAccess(Init, Found);
+ Init = FixOverloadedFunctionReference(Init, Found, Fn);
}
T2 = Fn->getType();
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0c9b3bd44b..406b8201a3 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -635,7 +635,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
MemberType = Context.getQualifiedType(MemberType, NewQuals);
MarkDeclarationReferenced(Loc, *FI);
- PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI);
+ PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI);
// FIXME: Might this end up being a qualified name?
Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
OpLoc, MemberType);
@@ -1355,10 +1355,27 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
return Owned((Expr*) 0);
}
-/// \brief Cast member's object to its own class if necessary.
+/// \brief Cast a base object to a member's actual type.
+///
+/// Logically this happens in three phases:
+///
+/// * First we cast from the base type to the naming class.
+/// The naming class is the class into which we were looking
+/// when we found the member; it's the qualifier type if a
+/// qualifier was provided, and otherwise it's the base type.
+///
+/// * Next we cast from the naming class to the declaring class.
+/// If the member we found was brought into a class's scope by
+/// a using declaration, this is that class; otherwise it's
+/// the class declaring the member.
+///
+/// * Finally we cast from the declaring class to the "true"
+/// declaring class of the member. This conversion does not
+/// obey access control.
bool
Sema::PerformObjectMemberConversion(Expr *&From,
NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
NamedDecl *Member) {
CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
if (!RD)
@@ -1406,6 +1423,9 @@ Sema::PerformObjectMemberConversion(Expr *&From,
if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
return false;
+ SourceRange FromRange = From->getSourceRange();
+ SourceLocation FromLoc = FromRange.getBegin();
+
// C++ [class.member.lookup]p8:
// [...] Ambiguities can often be resolved by qualifying a name with its
// class name.
@@ -1424,51 +1444,89 @@ Sema::PerformObjectMemberConversion(Expr *&From,
// x = 17; // error: ambiguous base subobjects
// Derived1::x = 17; // okay, pick the Base subobject of Derived1
// }
- QualType IntermediateRecordType;
- QualType IntermediateType;
if (Qualifier) {
- if (const RecordType *IntermediateRecord
- = Qualifier->getAsType()->getAs<RecordType>()) {
- IntermediateRecordType = QualType(IntermediateRecord, 0);
- IntermediateType = IntermediateRecordType;
+ QualType QType = QualType(Qualifier->getAsType(), 0);
+ assert(!QType.isNull() && "lookup done with dependent qualifier?");
+ assert(QType->isRecordType() && "lookup done with non-record type");
+
+ QualType QRecordType = QualType(QType->getAs<RecordType>(), 0);
+
+ // In C++98, the qualifier type doesn't actually have to be a base
+ // type of the object type, in which case we just ignore it.
+ // Otherwise build the appropriate casts.
+ if (IsDerivedFrom(FromRecordType, QRecordType)) {
+ if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
+ FromLoc, FromRange))
+ return true;
+
if (PointerConversions)
- IntermediateType = Context.getPointerType(IntermediateType);
+ QType = Context.getPointerType(QType);
+ ImpCastExprToType(From, QType, CastExpr::CK_DerivedToBase,
+ /*isLvalue*/ !PointerConversions);
+
+ FromType = QType;
+ FromRecordType = QRecordType;
+
+ // If the qualifier type was the same as the destination type,
+ // we're done.
+ if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
+ return false;
}
}
- if (!IntermediateType.isNull() &&
- IsDerivedFrom(FromRecordType, IntermediateRecordType) &&
- IsDerivedFrom(IntermediateRecordType, DestRecordType)) {
- if (CheckDerivedToBaseConversion(FromRecordType, IntermediateRecordType,
- From->getSourceRange().getBegin(),
- From->getSourceRange()) ||
- CheckDerivedToBaseConversion(IntermediateRecordType, DestRecordType,
- From->getSourceRange().getBegin(),
- From->getSourceRange()))
- return true;
+ bool IgnoreAccess = false;
- ImpCastExprToType(From, IntermediateType, CastExpr::CK_DerivedToBase,
- /*isLvalue=*/!PointerConversions);
- ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase,
- /*isLvalue=*/!PointerConversions);
- return false;
+ // If we actually found the member through a using declaration, cast
+ // down to the using declaration's type.
+ //
+ // Pointer equality is fine here because only one declaration of a
+ // class ever has member declarations.
+ if (FoundDecl->getDeclContext() != Member->getDeclContext()) {
+ assert(isa<UsingShadowDecl>(FoundDecl));
+ QualType URecordType = Context.getTypeDeclType(
+ cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
+
+ // We only need to do this if the naming-class to declaring-class
+ // conversion is non-trivial.
+ if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
+ assert(IsDerivedFrom(FromRecordType, URecordType));
+ if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
+ FromLoc, FromRange))
+ return true;
+
+ QualType UType = URecordType;
+ if (PointerConversions)
+ UType = Context.getPointerType(UType);
+ ImpCastExprToType(From, UType, CastExpr::CK_DerivedToBase,
+ /*isLvalue*/ !PointerConversions);
+ FromType = UType;
+ FromRecordType = URecordType;
+ }
+
+ // We don't do access control for the conversion from the
+ // declaring class to the true declaring class.
+ IgnoreAccess = true;
}
if (CheckDerivedToBaseConversion(FromRecordType,
DestRecordType,
- From->getSourceRange().getBegin(),
- From->getSourceRange()))
+ FromLoc,
+ FromRange,
+ IgnoreAccess))
return true;
+ // FIXME: isLvalue should be !PointerConversions here, but codegen
+ // does very silly things.
ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase,
- /*isLvalue=*/true);
+ /*isLvalue=*/ true);
return false;
}
/// \brief Build a MemberExpr AST node.
static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
const CXXScopeSpec &SS, ValueDecl *Member,
- SourceLocation Loc, QualType Ty,
+ NamedDecl *FoundDecl, SourceLocation Loc,
+ QualType Ty,
const TemplateArgumentListInfo *TemplateArgs = 0) {
NestedNameSpecifier *Qualifier = 0;
SourceRange QualifierRange;
@@ -1478,7 +1536,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
}
return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
- Member, Loc, TemplateArgs, Ty);
+ Member, FoundDecl, Loc, TemplateArgs, Ty);
}
/// Builds an implicit member access expression. The current context
@@ -2692,6 +2750,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
}
assert(R.isSingleResult());
+ NamedDecl *FoundDecl = *R.begin();
NamedDecl *MemberDecl = R.getFoundDecl();
// FIXME: diagnose the presence of template arguments now.
@@ -2754,30 +2813,30 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,
}
MarkDeclarationReferenced(MemberLoc, FD);
- if (PerformObjectMemberConversion(BaseExpr, Qualifier, FD))
+ if (PerformObjectMemberConversion(BaseExpr, Qualifier, FoundDecl, FD))
return ExprError();
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
- FD, MemberLoc, MemberType));
+ FD, FoundDecl, MemberLoc, MemberType));
}
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, Var);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
- Var, MemberLoc,
+ Var, FoundDecl, MemberLoc,
Var->getType().getNonReferenceType()));
}
if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
- MemberFn, MemberLoc,
+ MemberFn, FoundDecl, MemberLoc,
MemberFn->getType()));
}
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
- Enum, MemberLoc, Enum->getType()));
+ Enum, FoundDecl, MemberLoc, Enum->getType()));
}
Owned(BaseExpr);
@@ -6752,7 +6811,8 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
Res = BuildAnonymousStructUnionMemberReference(
OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
} else {
- PerformObjectMemberConversion(Res, /*Qualifier=*/0, MemberDecl);
+ PerformObjectMemberConversion(Res, /*Qualifier=*/0,
+ *R.begin(), MemberDecl);
// MemberDecl->getType() doesn't get the right qualifiers, but it
// doesn't matter here.
Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index c31d93416d..9baa6ac079 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1650,14 +1650,16 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
case ICK_Function_To_Pointer:
if (Context.getCanonicalType(FromType) == Context.OverloadTy) {
- FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true);
+ DeclAccessPair Found;
+ FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
+ true, Found);
if (!Fn)
return true;
if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
return true;
- From = FixOverloadedFunctionReference(From, Fn);
+ From = FixOverloadedFunctionReference(From, Found, Fn);
FromType = From->getType();
// If there's already an address-of operator in the expression, we have
@@ -2847,8 +2849,10 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
}
CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
+ NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
- if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, Method))
+ if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0,
+ FoundDecl, Method))
assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?");
MemberExpr *ME =
@@ -2892,7 +2896,8 @@ Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,
assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");
// Create an implicit call expr that calls it.
- CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method);
+ // FIXME: pass the FoundDecl for the user-defined conversion here
+ CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method, Method);
return MaybeBindToTemporary(CE);
}
}
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 0b2e1db6a0..4612bda7b2 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2036,13 +2036,13 @@ bool InitializationSequence::isAmbiguous() const {
}
void InitializationSequence::AddAddressOverloadResolutionStep(
- FunctionDecl *Function) {
+ FunctionDecl *Function,
+ DeclAccessPair Found) {
Step S;
S.Kind = SK_ResolveAddressOfOverloadedFunction;
S.Type = Function->getType();
- // Access is currently ignored for these.
S.Function.Function = Function;
- S.Function.FoundDecl = DeclAccessPair::make(Function, AS_none);
+ S.Function.FoundDecl = Found;
Steps.push_back(S);
}
@@ -2375,15 +2375,17 @@ static void TryReferenceInitialization(Sema &S,
// to resolve the overloaded function. If all goes well, T2 is the
// type of the resulting function.
if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+ DeclAccessPair Found;
FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer,
T1,
- false);
+ false,
+ Found);
if (!Fn) {
Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
return;
}
- Sequence.AddAddressOverloadResolutionStep(Fn);
+ Sequence.AddAddressOverloadResolutionStep(Fn, Found);
cv2T2 = Fn->getType();
T2 = cv2T2.getUnqualifiedType();
}
@@ -3348,8 +3350,9 @@ InitializationSequence::Perform(Sema &S,
case SK_ResolveAddressOfOverloadedFunction:
// Overload resolution determined which function invoke; update the
// initializer to reflect that choice.
- // Access control was done in overload resolution.
+ S.CheckAddressOfMemberAccess(CurInitExpr, Step->Function.FoundDecl);
CurInit = S.FixOverloadedFunctionReference(move(CurInit),
+ Step->Function.FoundDecl,
Step->Function.Function);
break;
@@ -3457,7 +3460,7 @@ InitializationSequence::Perform(Sema &S,
// derived-to-base conversion? I believe the answer is "no", because
// we don't want to turn off access control here for c-style casts.
if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0,
- Conversion))
+ FoundFn, Conversion))
return S.ExprError();
// Do a little dance to make sure that CurInit has the proper
@@ -3465,7 +3468,8 @@ InitializationSequence::Perform(Sema &S,
CurInit.release();
// Build the actual call to the conversion function.
- CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, Conversion));
+ CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn,
+ Conversion));
if (CurInit.isInvalid() || !CurInit.get())
return S.ExprError();
@@ -3649,11 +3653,14 @@ bool InitializationSequence::Diagnose(Sema &S,
<< (Failure == FK_ArrayNeedsInitListOrStringLiteral);
break;
- case FK_AddressOfOverloadFailed:
+ case FK_AddressOfOverloadFailed: {
+ DeclAccessPair Found;
S.ResolveAddressOfOverloadedFunction(Args[0],
DestType.getNonReferenceType(),
- true);
+ true,
+ Found);
break;
+ }
case FK_ReferenceInitOverloadFailed:
case FK_UserConversionOverloadFailed:
diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h
index d57679ab75..7c6327f8c7 100644
--- a/lib/Sema/SemaInit.h
+++ b/lib/Sema/SemaInit.h
@@ -611,7 +611,8 @@ public:
///
/// \param Function the function to which the overloaded function reference
/// resolves.
- void AddAddressOverloadResolutionStep(FunctionDecl *Function);
+ void AddAddressOverloadResolutionStep(FunctionDecl *Function,
+ DeclAccessPair Found);
/// \brief Add a new step in the initialization that performs a derived-to-
/// base cast.
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 58d7d67508..8d3313982c 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -567,6 +567,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// array-to-pointer conversion, or function-to-pointer conversion
// (C++ 4p1).
+ DeclAccessPair AccessPair;
+
// Lvalue-to-rvalue conversion (C++ 4.1):
// An lvalue (3.10) of a non-function, non-array type T can be
// converted to an rvalue.
@@ -612,7 +614,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// function. (C++ 4.3p1).
FromType = Context.getPointerType(FromType);
} else if (FunctionDecl *Fn
- = ResolveAddressOfOverloadedFunction(From, ToType, false)) {
+ = ResolveAddressOfOverloadedFunction(From, ToType, false,
+ AccessPair)) {
// Address of overloaded function (C++ [over.over]).
SCS.First = ICK_Function_To_Pointer;
@@ -2278,6 +2281,7 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType,
bool
Sema::PerformObjectArgumentInitialization(Expr *&From,
NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
QualType FromRecordType, DestType;
QualType ImplicitParamRecordType =
@@ -2302,7 +2306,7 @@ Sema::PerformObjectArgumentInitialization(Expr *&From,
<< ImplicitParamRecordType << FromRecordType << From->getSourceRange();
if (ICS.Standard.Second == ICK_Derived_To_Base)
- return PerformObjectMemberConversion(From, Qualifier, Method);
+ return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
if (!Context.hasSameType(From->getType(), DestType))
ImpCastExprToType(From, DestType, CastExpr::CK_NoOp,
@@ -4942,7 +4946,8 @@ static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {
/// routine will emit diagnostics if there is an error.
FunctionDecl *
Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
- bool Complain) {
+ bool Complain,
+ DeclAccessPair &FoundResult) {
QualType FunctionType = ToType;
bool IsMember = false;
if (const PointerType *ToTypePtr = ToType->getAs<PointerType>())
@@ -5059,9 +5064,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
return 0;
else if (