[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