[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/Sem
Daniel Dunbar
daniel at zuster.org
Tue Mar 30 19:11:43 PDT 2010
On Tue, Mar 30, 2010 at 2:47 PM, John McCall <rjmccall at apple.com> wrote:
> 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.
Congrats John, that is another excellent milestone!
- Daniel
> 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;
> + }
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
More information about the cfe-commits
mailing list