[cfe-commits] r99936 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/Sema/Sema.h lib/Sema/SemaAccess.cpp lib/Sema/SemaCXXCast.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaInit.h lib/Sema/SemaOverload.cpp lib/Sema/SemaStmt.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h test/CXX/class.access/p4.cpp
John McCall
rjmccall at apple.com
Tue Mar 30 14:47:33 PDT 2010
Author: rjmccall
Date: Tue Mar 30 16:47:33 2010
New Revision: 99936
URL: http://llvm.org/viewvc/llvm-project?rev=99936&view=rev
Log:
Propagate the "found declaration" (i.e. the using declaration instead of
the underlying/instantiated decl) through a lot of API, including "intermediate"
MemberExprs required for (e.g.) template instantiation. This is necessary
because of the access semantics of member accesses to using declarations:
only the base class *containing the using decl* need be accessible from the
naming class.
This allows us to complete an access-controlled selfhost, if there are no
recent regressions.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaAccess.cpp
cfe/trunk/lib/Sema/SemaCXXCast.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaInit.h
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/class.access/p4.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Mar 30 16:47:33 2010
@@ -1263,6 +1263,11 @@
/// 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 @@
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 @@
if (!HasExplicitTemplateArgumentList)
return 0;
- if (!HasQualifier)
+ if (!HasQualifierOrFoundDecl)
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
return reinterpret_cast<ExplicitTemplateArgumentList *>(
@@ -1321,26 +1325,22 @@
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 @@
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 @@
/// nested-name-specifier that precedes the member name. Otherwise, returns
/// NULL.
NestedNameSpecifier *getQualifier() const {
- if (!HasQualifier)
+ if (!HasQualifierOrFoundDecl)
return 0;
return getMemberQualifier()->NNS;
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Mar 30 16:47:33 2010
@@ -499,44 +499,45 @@
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 {
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 30 16:47:33 2010
@@ -1119,6 +1119,7 @@
CXXRecordDecl *ActingContext);
bool PerformObjectArgumentInitialization(Expr *&From,
NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
CXXMethodDecl *Method);
ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From);
@@ -1126,6 +1127,7 @@
bool PerformObjectMemberConversion(Expr *&From,
NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
NamedDecl *Member);
// Members have to be NamespaceDecl* or TranslationUnitDecl*.
@@ -1246,11 +1248,15 @@
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 @@
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 @@
Expr *ObjectExpr,
Expr *ArgExpr,
DeclAccessPair FoundDecl);
+ AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr,
+ DeclAccessPair FoundDecl);
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
QualType Base, QualType Derived,
const CXXBasePath &Path,
Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Tue Mar 30 16:47:33 2010
@@ -907,6 +907,31 @@
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)
Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Tue Mar 30 16:47:33 2010
@@ -808,8 +808,10 @@
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 @@
// 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;
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar 30 16:47:33 2010
@@ -4409,16 +4409,18 @@
// 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();
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Mar 30 16:47:33 2010
@@ -635,7 +635,7 @@
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
}
assert(R.isSingleResult());
+ NamedDecl *FoundDecl = *R.begin();
NamedDecl *MemberDecl = R.getFoundDecl();
// FIXME: diagnose the presence of template arguments now.
@@ -2754,30 +2813,30 @@
}
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 @@
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,
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Mar 30 16:47:33 2010
@@ -1650,14 +1650,16 @@
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 @@
}
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 @@
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);
}
}
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Mar 30 16:47:33 2010
@@ -2036,13 +2036,13 @@
}
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
<< (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:
Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Tue Mar 30 16:47:33 2010
@@ -611,7 +611,8 @@
///
/// \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.
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Mar 30 16:47:33 2010
@@ -567,6 +567,8 @@
// 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 @@
// 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 @@
bool
Sema::PerformObjectArgumentInitialization(Expr *&From,
NestedNameSpecifier *Qualifier,
+ NamedDecl *FoundDecl,
CXXMethodDecl *Method) {
QualType FromRecordType, DestType;
QualType ImplicitParamRecordType =
@@ -2302,7 +2306,7 @@
<< 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 @@
/// 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 @@
return 0;
else if (Matches.size() == 1) {
FunctionDecl *Result = Matches[0].second;
+ FoundResult = Matches[0].first;
MarkDeclarationReferenced(From->getLocStart(), Result);
if (Complain)
- CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
+ CheckAddressOfMemberAccess(OvlExpr, Matches[0].first);
return Result;
}
@@ -5093,10 +5099,9 @@
<< (unsigned) oc_function_template);
assert(Result != MatchesCopy.end() && "no most-specialized template");
MarkDeclarationReferenced(From->getLocStart(), *Result);
- if (Complain) {
- DeclAccessPair FoundDecl = Matches[Result - MatchesCopy.begin()].first;
- CheckUnresolvedAccess(*this, OvlExpr, FoundDecl);
- }
+ FoundResult = Matches[Result - MatchesCopy.begin()].first;
+ if (Complain)
+ CheckUnresolvedAccess(*this, OvlExpr, FoundResult);
return cast<FunctionDecl>(*Result);
}
@@ -5115,6 +5120,7 @@
// selected function.
if (Matches.size() == 1) {
MarkDeclarationReferenced(From->getLocStart(), Matches[0].second);
+ FoundResult = Matches[0].first;
if (Complain)
CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
return cast<FunctionDecl>(Matches[0].second);
@@ -5395,7 +5401,7 @@
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
- Fn = FixOverloadedFunctionReference(Fn, FDecl);
+ Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
}
@@ -5522,7 +5528,8 @@
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
- if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, Method))
+ if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0,
+ Best->FoundDecl, Method))
return ExprError();
} else {
// Convert the arguments.
@@ -5716,7 +5723,7 @@
return ExprError();
if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
- Method))
+ Best->FoundDecl, Method))
return ExprError();
Args[1] = RHS = Arg1.takeAs<Expr>();
@@ -5883,7 +5890,7 @@
// Convert the arguments.
CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,
- Method))
+ Best->FoundDecl, Method))
return ExprError();
// Convert the arguments.
@@ -5988,10 +5995,12 @@
MemberExpr *MemExpr;
CXXMethodDecl *Method = 0;
+ NamedDecl *FoundDecl = 0;
NestedNameSpecifier *Qualifier = 0;
if (isa<MemberExpr>(NakedMemExpr)) {
MemExpr = cast<MemberExpr>(NakedMemExpr);
Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+ FoundDecl = MemExpr->getFoundDecl();
Qualifier = MemExpr->getQualifier();
} else {
UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
@@ -6041,6 +6050,7 @@
switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
+ FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
break;
@@ -6068,7 +6078,7 @@
return ExprError();
}
- MemExprE = FixOverloadedFunctionReference(MemExprE, Method);
+ MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
// If overload resolution picked a static member, build a
// non-member call based on that function.
@@ -6093,9 +6103,12 @@
return ExprError();
// Convert the object argument (for a non-static member function call).
+ // We only need to do this if there was actually an overload; otherwise
+ // it was done at lookup.
Expr *ObjectArg = MemExpr->getBase();
if (!Method->isStatic() &&
- PerformObjectArgumentInitialization(ObjectArg, Qualifier, Method))
+ PerformObjectArgumentInitialization(ObjectArg, Qualifier,
+ FoundDecl, Method))
return ExprError();
MemExpr->setBase(ObjectArg);
@@ -6255,7 +6268,8 @@
// Create an implicit member expr to refer to the conversion operator.
// and then call it.
- CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Conv);
+ CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Best->FoundDecl,
+ Conv);
return ActOnCallExpr(S, ExprArg(*this, CE), LParenLoc,
MultiExprArg(*this, (ExprTy**)Args, NumArgs),
@@ -6315,7 +6329,7 @@
// Initialize the implicit object parameter.
IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0,
- Method);
+ Best->FoundDecl, Method);
TheCall->setArg(0, Object);
@@ -6436,7 +6450,8 @@
// Convert the object parameter.
CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
- if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, Method))
+ if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0,
+ Best->FoundDecl, Method))
return ExprError();
// No concerns about early exits now.
@@ -6463,9 +6478,11 @@
/// perhaps a '&' around it). We have resolved the overloaded function
/// to the function declaration Fn, so patch up the expression E to
/// refer (possibly indirectly) to Fn. Returns the new expr.
-Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
+Expr *Sema::FixOverloadedFunctionReference(Expr *E, NamedDecl *Found,
+ FunctionDecl *Fn) {
if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
- Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
+ Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(),
+ Found, Fn);
if (SubExpr == PE->getSubExpr())
return PE->Retain();
@@ -6473,7 +6490,8 @@
}
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
- Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn);
+ Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(),
+ Found, Fn);
assert(Context.hasSameType(ICE->getSubExpr()->getType(),
SubExpr->getType()) &&
"Implicit cast type cannot be determined from overload");
@@ -6497,7 +6515,8 @@
// Fix the sub expression, which really has to be an
// UnresolvedLookupExpr holding an overloaded member function
// or template.
- Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+ Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
+ Found, Fn);
if (SubExpr == UnOp->getSubExpr())
return UnOp->Retain();
@@ -6518,7 +6537,8 @@
MemPtrType, UnOp->getOperatorLoc());
}
}
- Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+ Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
+ Found, Fn);
if (SubExpr == UnOp->getSubExpr())
return UnOp->Retain();
@@ -6580,6 +6600,7 @@
MemExpr->getQualifier(),
MemExpr->getQualifierRange(),
Fn,
+ Found,
MemExpr->getMemberLoc(),
TemplateArgs,
Fn->getType());
@@ -6590,8 +6611,9 @@
}
Sema::OwningExprResult Sema::FixOverloadedFunctionReference(OwningExprResult E,
+ NamedDecl *Found,
FunctionDecl *Fn) {
- return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Fn));
+ return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn));
}
} // end namespace clang
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Mar 30 16:47:33 2010
@@ -437,32 +437,35 @@
<< CondExpr->getSourceRange()))
return true;
- llvm::SmallVector<CXXConversionDecl *, 4> ViableConversions;
- llvm::SmallVector<CXXConversionDecl *, 4> ExplicitConversions;
+ UnresolvedSet<4> ViableConversions;
+ UnresolvedSet<4> ExplicitConversions;
if (const RecordType *RecordTy = CondType->getAs<RecordType>()) {
const UnresolvedSetImpl *Conversions
= cast<CXXRecordDecl>(RecordTy->getDecl())
->getVisibleConversionFunctions();
for (UnresolvedSetImpl::iterator I = Conversions->begin(),
E = Conversions->end(); I != E; ++I) {
- if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(*I))
+ if (CXXConversionDecl *Conversion
+ = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl()))
if (Conversion->getConversionType().getNonReferenceType()
->isIntegralType()) {
if (Conversion->isExplicit())
- ExplicitConversions.push_back(Conversion);
+ ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
else
- ViableConversions.push_back(Conversion);
+ ViableConversions.addDecl(I.getDecl(), I.getAccess());
}
}
switch (ViableConversions.size()) {
case 0:
if (ExplicitConversions.size() == 1) {
+ DeclAccessPair Found = ExplicitConversions[0];
+ CXXConversionDecl *Conversion =
+ cast<CXXConversionDecl>(Found->getUnderlyingDecl());
// The user probably meant to invoke the given explicit
// conversion; use it.
QualType ConvTy
- = ExplicitConversions[0]->getConversionType()
- .getNonReferenceType();
+ = Conversion->getConversionType().getNonReferenceType();
std::string TypeStr;
ConvTy.getAsStringInternal(TypeStr, S.Context.PrintingPolicy);
@@ -473,8 +476,7 @@
<< CodeModificationHint::CreateInsertion(
S.PP.getLocForEndOfToken(CondExpr->getLocEnd()),
")");
- S.Diag(ExplicitConversions[0]->getLocation(),
- diag::note_switch_conversion)
+ S.Diag(Conversion->getLocation(), diag::note_switch_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
// If we aren't in a SFINAE context, build a call to the
@@ -482,25 +484,32 @@
if (S.isSFINAEContext())
return true;
- CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ExplicitConversions[0]);
+ S.CheckMemberOperatorAccess(CondExpr->getExprLoc(),
+ CondExpr, 0, Found);
+ CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found, Conversion);
}
// We'll complain below about a non-integral condition type.
break;
- case 1:
+ case 1: {
// Apply this conversion.
- CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ViableConversions[0]);
+ DeclAccessPair Found = ViableConversions[0];
+ S.CheckMemberOperatorAccess(CondExpr->getExprLoc(),
+ CondExpr, 0, Found);
+ CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found,
+ cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
break;
+ }
default:
S.Diag(SwitchLoc, diag::err_switch_multiple_conversions)
<< CondType << CondExpr->getSourceRange();
for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
- QualType ConvTy
- = ViableConversions[I]->getConversionType().getNonReferenceType();
- S.Diag(ViableConversions[I]->getLocation(),
- diag::note_switch_conversion)
+ CXXConversionDecl *Conv
+ = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
+ QualType ConvTy = Conv->getConversionType().getNonReferenceType();
+ S.Diag(Conv->getLocation(), diag::note_switch_conversion)
<< ConvTy->isEnumeralType() << ConvTy;
}
return true;
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Mar 30 16:47:33 2010
@@ -2617,6 +2617,8 @@
return false;
}
+ DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
+
// Handle pointer-to-function, reference-to-function, and
// pointer-to-member-function all in (roughly) the same way.
if (// -- For a non-type template-parameter of type pointer to
@@ -2656,11 +2658,12 @@
ArgType = Context.getPointerType(ArgType);
ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay);
} else if (FunctionDecl *Fn
- = ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) {
+ = ResolveAddressOfOverloadedFunction(Arg, ParamType, true,
+ FoundResult)) {
if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
return true;
- Arg = FixOverloadedFunctionReference(Arg, Fn);
+ Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
ArgType = Arg->getType();
if (ArgType->isFunctionType() && ParamType->isPointerType()) {
ArgType = Context.getPointerType(Arg->getType());
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Mar 30 16:47:33 2010
@@ -2004,7 +2004,7 @@
// function template specialization wherever deduction cannot occur.
if (FunctionDecl *Specialization
= ResolveSingleFunctionTemplateSpecialization(E)) {
- E = FixOverloadedFunctionReference(E, Specialization);
+ E = FixOverloadedFunctionReference(E, Specialization, Specialization);
if (!E)
return QualType();
} else {
@@ -2024,7 +2024,7 @@
// function template specialization wherever deduction cannot occur.
if (FunctionDecl *Specialization
= ResolveSingleFunctionTemplateSpecialization(E)) {
- E = FixOverloadedFunctionReference(E, Specialization);
+ E = FixOverloadedFunctionReference(E, Specialization, Specialization);
if (!E)
return QualType();
} else {
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Mar 30 16:47:33 2010
@@ -977,6 +977,7 @@
SourceRange QualifierRange,
SourceLocation MemberLoc,
ValueDecl *Member,
+ NamedDecl *FoundDecl,
const TemplateArgumentListInfo *ExplicitTemplateArgs,
NamedDecl *FirstQualifierInScope) {
if (!Member->getDeclName()) {
@@ -984,7 +985,8 @@
assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
Expr *BaseExpr = Base.takeAs<Expr>();
- if (getSema().PerformObjectMemberConversion(BaseExpr, Qualifier, Member))
+ if (getSema().PerformObjectMemberConversion(BaseExpr, Qualifier,
+ FoundDecl, Member))
return getSema().ExprError();
MemberExpr *ME =
@@ -1002,9 +1004,11 @@
QualType BaseType = ((Expr*) Base.get())->getType();
+ // FIXME: this involves duplicating earlier analysis in a lot of
+ // cases; we should avoid this when possible.
LookupResult R(getSema(), Member->getDeclName(), MemberLoc,
Sema::LookupMemberName);
- R.addDecl(Member);
+ R.addDecl(FoundDecl);
R.resolveKind();
return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
@@ -3868,10 +3872,21 @@
if (!Member)
return SemaRef.ExprError();
+ NamedDecl *FoundDecl = E->getFoundDecl();
+ if (FoundDecl == E->getMemberDecl()) {
+ FoundDecl = Member;
+ } else {
+ FoundDecl = cast_or_null<NamedDecl>(
+ getDerived().TransformDecl(E->getMemberLoc(), FoundDecl));
+ if (!FoundDecl)
+ return SemaRef.ExprError();
+ }
+
if (!getDerived().AlwaysRebuild() &&
Base.get() == E->getBase() &&
Qualifier == E->getQualifier() &&
Member == E->getMemberDecl() &&
+ FoundDecl == E->getFoundDecl() &&
!E->hasExplicitTemplateArgumentList()) {
// Mark it referenced in the new context regardless.
@@ -3908,6 +3923,7 @@
E->getQualifierRange(),
E->getMemberLoc(),
Member,
+ FoundDecl,
(E->hasExplicitTemplateArgumentList()
? &TransArgs : 0),
FirstQualifierInScope);
Modified: cfe/trunk/test/CXX/class.access/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/p4.cpp (original)
+++ cfe/trunk/test/CXX/class.access/p4.cpp Tue Mar 30 16:47:33 2010
@@ -309,3 +309,21 @@
}
};
}
+
+namespace test13 {
+ struct A {
+ int x;
+ unsigned foo() const;
+ };
+
+ struct B : protected A {
+ using A::foo;
+ using A::x;
+ };
+
+ void test() {
+ A *d;
+ d->foo();
+ (void) d->x;
+ }
+}
More information about the cfe-commits
mailing list