[cfe-commits] r99936 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/Sema/Sema.h lib/Sema/SemaAccess.cpp lib/Sema/SemaCXXCast.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaInit.h lib/Sema/SemaOverload.cpp lib/Sema/SemaStmt.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaType.cpp lib/Sema/TreeTransform.h test/CXX/class.access/p4.cpp

John McCall rjmccall at apple.com
Tue Mar 30 14:47:33 PDT 2010


Author: rjmccall
Date: Tue Mar 30 16:47:33 2010
New Revision: 99936

URL: http://llvm.org/viewvc/llvm-project?rev=99936&view=rev
Log:
Propagate the "found declaration" (i.e. the using declaration instead of
the underlying/instantiated decl) through a lot of API, including "intermediate"
MemberExprs required for (e.g.) template instantiation.  This is necessary
because of the access semantics of member accesses to using declarations:
only the base class *containing the using decl* need be accessible from the
naming class.

This allows us to complete an access-controlled selfhost, if there are no
recent regressions.


Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaAccess.cpp
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaInit.h
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CXX/class.access/p4.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Mar 30 16:47:33 2010
@@ -1263,6 +1263,11 @@
 /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
 ///
 class MemberExpr : public Expr {
+  /// Extra data stored in some member expressions.
+  struct MemberNameQualifier : public NameQualifier {
+    NamedDecl *FoundDecl;
+  };
+
   /// Base - the expression for the base pointer or structure references.  In
   /// X.F, this is "X".
   Stmt *Base;
@@ -1278,27 +1283,26 @@
   bool IsArrow : 1;
 
   /// \brief True if this member expression used a nested-name-specifier to
-  /// refer to the member, e.g., "x->Base::f". When true, a NameQualifier
+  /// refer to the member, e.g., "x->Base::f", or found its member via a using
+  /// declaration.  When true, a MemberNameQualifier
   /// structure is allocated immediately after the MemberExpr.
-  bool HasQualifier : 1;
+  bool HasQualifierOrFoundDecl : 1;
 
   /// \brief True if this member expression specified a template argument list
   /// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList
   /// structure (and its TemplateArguments) are allocated immediately after
   /// the MemberExpr or, if the member expression also has a qualifier, after
-  /// the NameQualifier structure.
+  /// the MemberNameQualifier structure.
   bool HasExplicitTemplateArgumentList : 1;
 
   /// \brief Retrieve the qualifier that preceded the member name, if any.
-  NameQualifier *getMemberQualifier() {
-    if (!HasQualifier)
-      return 0;
-
-    return reinterpret_cast<NameQualifier *> (this + 1);
+  MemberNameQualifier *getMemberQualifier() {
+    assert(HasQualifierOrFoundDecl);
+    return reinterpret_cast<MemberNameQualifier *> (this + 1);
   }
 
   /// \brief Retrieve the qualifier that preceded the member name, if any.
-  const NameQualifier *getMemberQualifier() const {
+  const MemberNameQualifier *getMemberQualifier() const {
     return const_cast<MemberExpr *>(this)->getMemberQualifier();
   }
 
@@ -1308,7 +1312,7 @@
     if (!HasExplicitTemplateArgumentList)
       return 0;
 
-    if (!HasQualifier)
+    if (!HasQualifierOrFoundDecl)
       return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
 
     return reinterpret_cast<ExplicitTemplateArgumentList *>(
@@ -1321,26 +1325,22 @@
     return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList();
   }
 
-  MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
-             SourceRange qualrange, ValueDecl *memberdecl, SourceLocation l,
-             const TemplateArgumentListInfo *targs, QualType ty);
-
 public:
   MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
              SourceLocation l, QualType ty)
     : Expr(MemberExprClass, ty,
            base->isTypeDependent(), base->isValueDependent()),
       Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
-      HasQualifier(false), HasExplicitTemplateArgumentList(false) {}
+      HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}
 
   /// \brief Build an empty member reference expression.
   explicit MemberExpr(EmptyShell Empty)
-    : Expr(MemberExprClass, Empty), HasQualifier(false),
+    : Expr(MemberExprClass, Empty), HasQualifierOrFoundDecl(false),
       HasExplicitTemplateArgumentList(false) { }
 
   static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,
                             NestedNameSpecifier *qual, SourceRange qualrange,
-                            ValueDecl *memberdecl,
+                            ValueDecl *memberdecl, NamedDecl *founddecl,
                             SourceLocation l,
                             const TemplateArgumentListInfo *targs,
                             QualType ty);
@@ -1355,16 +1355,23 @@
   ValueDecl *getMemberDecl() const { return MemberDecl; }
   void setMemberDecl(ValueDecl *D) { MemberDecl = D; }
 
+  /// \brief Retrieves the declaration found by lookup.
+  NamedDecl *getFoundDecl() const {
+    if (!HasQualifierOrFoundDecl)
+      return getMemberDecl();
+    return getMemberQualifier()->FoundDecl;
+  }
+
   /// \brief Determines whether this member expression actually had
   /// a C++ nested-name-specifier prior to the name of the member, e.g.,
   /// x->Base::foo.
-  bool hasQualifier() const { return HasQualifier; }
+  bool hasQualifier() const { return getQualifier() != 0; }
 
   /// \brief If the member name was qualified, retrieves the source range of
   /// the nested-name-specifier that precedes the member name. Otherwise,
   /// returns an empty source range.
   SourceRange getQualifierRange() const {
-    if (!HasQualifier)
+    if (!HasQualifierOrFoundDecl)
       return SourceRange();
 
     return getMemberQualifier()->Range;
@@ -1374,7 +1381,7 @@
   /// nested-name-specifier that precedes the member name. Otherwise, returns
   /// NULL.
   NestedNameSpecifier *getQualifier() const {
-    if (!HasQualifier)
+    if (!HasQualifierOrFoundDecl)
       return 0;
 
     return getMemberQualifier()->NNS;

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Mar 30 16:47:33 2010
@@ -499,44 +499,45 @@
   return FnType->getResultType();
 }
 
-MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual,
-                       SourceRange qualrange, ValueDecl *memberdecl,
-                       SourceLocation l, const TemplateArgumentListInfo *targs,
-                       QualType ty)
-  : Expr(MemberExprClass, ty,
-         base->isTypeDependent() || (qual && qual->isDependent()),
-         base->isValueDependent() || (qual && qual->isDependent())),
-    Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow),
-    HasQualifier(qual != 0), HasExplicitTemplateArgumentList(targs) {
-  // Initialize the qualifier, if any.
-  if (HasQualifier) {
-    NameQualifier *NQ = getMemberQualifier();
-    NQ->NNS = qual;
-    NQ->Range = qualrange;
-  }
-
-  // Initialize the explicit template argument list, if any.
-  if (targs)
-    getExplicitTemplateArgumentList()->initializeFrom(*targs);
-}
-
 MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,
                                NestedNameSpecifier *qual,
                                SourceRange qualrange,
                                ValueDecl *memberdecl,
+                               NamedDecl *founddecl,
                                SourceLocation l,
                                const TemplateArgumentListInfo *targs,
                                QualType ty) {
   std::size_t Size = sizeof(MemberExpr);
-  if (qual != 0)
-    Size += sizeof(NameQualifier);
+
+  bool hasQualOrFound = (qual != 0 || founddecl != memberdecl);
+  if (hasQualOrFound)
+    Size += sizeof(MemberNameQualifier);
 
   if (targs)
     Size += ExplicitTemplateArgumentList::sizeFor(*targs);
 
   void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>());
-  return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l,
-                              targs, ty);
+  MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, l, ty);
+
+  if (hasQualOrFound) {
+    if (qual && qual->isDependent()) {
+      E->setValueDependent(true);
+      E->setTypeDependent(true);
+    }
+    E->HasQualifierOrFoundDecl = true;
+
+    MemberNameQualifier *NQ = E->getMemberQualifier();
+    NQ->NNS = qual;
+    NQ->Range = qualrange;
+    NQ->FoundDecl = founddecl;
+  }
+
+  if (targs) {
+    E->HasExplicitTemplateArgumentList = true;
+    E->getExplicitTemplateArgumentList()->initializeFrom(*targs);
+  }
+
+  return E;
 }
 
 const char *CastExpr::getCastKindName() const {

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Mar 30 16:47:33 2010
@@ -1119,6 +1119,7 @@
                                   CXXRecordDecl *ActingContext);
   bool PerformObjectArgumentInitialization(Expr *&From, 
                                            NestedNameSpecifier *Qualifier,
+                                           NamedDecl *FoundDecl,
                                            CXXMethodDecl *Method);
 
   ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From);
@@ -1126,6 +1127,7 @@
 
   bool PerformObjectMemberConversion(Expr *&From, 
                                      NestedNameSpecifier *Qualifier,
+                                     NamedDecl *FoundDecl,
                                      NamedDecl *Member);
 
   // Members have to be NamespaceDecl* or TranslationUnitDecl*.
@@ -1246,11 +1248,15 @@
                                    const PartialDiagnostic &PDiag);
 
   FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
-                                                   bool Complain);
+                                                   bool Complain,
+                                                   DeclAccessPair &Found);
   FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From);
 
-  Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);
+  Expr *FixOverloadedFunctionReference(Expr *E,
+                                       NamedDecl *FoundDecl,
+                                       FunctionDecl *Fn);
   OwningExprResult FixOverloadedFunctionReference(OwningExprResult, 
+                                                  NamedDecl *FoundDecl,
                                                   FunctionDecl *Fn);
 
   void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
@@ -2395,7 +2401,9 @@
   Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
                                   QualType EncodedType,
                                   SourceLocation RParenLoc);
-  CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp, CXXMethodDecl *Method);
+  CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp,
+                                            NamedDecl *FoundDecl,
+                                            CXXMethodDecl *Method);
 
   virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
                                                SourceLocation EncodeLoc,
@@ -2640,6 +2648,8 @@
                                          Expr *ObjectExpr,
                                          Expr *ArgExpr,
                                          DeclAccessPair FoundDecl);
+  AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr,
+                                          DeclAccessPair FoundDecl);
   AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,
                                     QualType Base, QualType Derived,
                                     const CXXBasePath &Path,

Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Tue Mar 30 16:47:33 2010
@@ -907,6 +907,31 @@
   return CheckAccess(*this, OpLoc, Entity);
 }
 
+Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
+                                                    DeclAccessPair Found) {
+  if (!getLangOptions().AccessControl ||
+      Found.getAccess() == AS_public)
+    return AR_accessible;
+
+  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer();
+  NestedNameSpecifier *Qualifier = Ovl->getQualifier();
+  assert(Qualifier && "address of overloaded member without qualifier");
+
+  CXXScopeSpec SS;
+  SS.setScopeRep(Qualifier);
+  SS.setRange(Ovl->getQualifierRange());
+  DeclContext *DC = computeDeclContext(SS);
+  assert(DC && DC->isRecord() && "scope did not resolve to record");
+  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(DC);
+
+  AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, Found);
+  Entity.setDiag(diag::err_access)
+    << Ovl->getSourceRange();
+
+  return CheckAccess(*this, Ovl->getNameLoc(), Entity);
+}
+
+
 /// Checks access for a hierarchy conversion.
 ///
 /// \param IsBaseToDerived whether this is a base-to-derived conversion (true)

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Tue Mar 30 16:47:33 2010
@@ -808,8 +808,10 @@
     return TC_NotApplicable;
 
   bool WasOverloadedFunction = false;
+  DeclAccessPair FoundOverload;
   if (FunctionDecl *Fn
-          = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false)) {
+        = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
+                                                  FoundOverload)) {
     CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
     SrcType = Self.Context.getMemberPointerType(Fn->getType(),
                     Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
@@ -870,13 +872,14 @@
     // allowing complaints if something goes wrong.
     FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr, 
                                                                DestType, 
-                                                               true);
+                                                               true,
+                                                               FoundOverload);
     if (!Fn) {
       msg = 0;
       return TC_Failed;
     }
 
-    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, Fn);
+    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
     if (!SrcExpr) {
       msg = 0;
       return TC_Failed;

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar 30 16:47:33 2010
@@ -4409,16 +4409,18 @@
   // to resolve the overloaded function. If all goes well, T2 is the
   // type of the resulting function.
   if (Context.getCanonicalType(T2) == Context.OverloadTy) {
+    DeclAccessPair Found;
     FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Init, DeclType,
-                                                          ICS != 0);
+                                                          ICS != 0, Found);
     if (Fn) {
       // Since we're performing this reference-initialization for
       // real, update the initializer with the resulting function.
       if (!ICS) {
         if (DiagnoseUseOfDecl(Fn, DeclLoc))
-          return true; 
+          return true;
 
-        Init = FixOverloadedFunctionReference(Init, Fn);
+        CheckAddressOfMemberAccess(Init, Found);
+        Init = FixOverloadedFunctionReference(Init, Found, Fn);
       }
 
       T2 = Fn->getType();

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Mar 30 16:47:33 2010
@@ -635,7 +635,7 @@
       MemberType = Context.getQualifiedType(MemberType, NewQuals);
 
     MarkDeclarationReferenced(Loc, *FI);
-    PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI);
+    PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI);
     // FIXME: Might this end up being a qualified name?
     Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
                                       OpLoc, MemberType);
@@ -1355,10 +1355,27 @@
   return Owned((Expr*) 0);
 }
 
-/// \brief Cast member's object to its own class if necessary.
+/// \brief Cast a base object to a member's actual type.
+///
+/// Logically this happens in three phases:
+///
+/// * First we cast from the base type to the naming class.
+///   The naming class is the class into which we were looking
+///   when we found the member;  it's the qualifier type if a
+///   qualifier was provided, and otherwise it's the base type.
+///
+/// * Next we cast from the naming class to the declaring class.
+///   If the member we found was brought into a class's scope by
+///   a using declaration, this is that class;  otherwise it's
+///   the class declaring the member.
+///
+/// * Finally we cast from the declaring class to the "true"
+///   declaring class of the member.  This conversion does not
+///   obey access control.
 bool
 Sema::PerformObjectMemberConversion(Expr *&From,
                                     NestedNameSpecifier *Qualifier,
+                                    NamedDecl *FoundDecl,
                                     NamedDecl *Member) {
   CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());
   if (!RD)
@@ -1406,6 +1423,9 @@
   if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
     return false;
 
+  SourceRange FromRange = From->getSourceRange();
+  SourceLocation FromLoc = FromRange.getBegin();
+
   // C++ [class.member.lookup]p8:
   //   [...] Ambiguities can often be resolved by qualifying a name with its
   //   class name.
@@ -1424,51 +1444,89 @@
   //     x = 17; // error: ambiguous base subobjects
   //     Derived1::x = 17; // okay, pick the Base subobject of Derived1
   //   }
-  QualType IntermediateRecordType;
-  QualType IntermediateType;
   if (Qualifier) {
-    if (const RecordType *IntermediateRecord
-                           = Qualifier->getAsType()->getAs<RecordType>()) {
-      IntermediateRecordType = QualType(IntermediateRecord, 0);
-      IntermediateType = IntermediateRecordType;
+    QualType QType = QualType(Qualifier->getAsType(), 0);
+    assert(!QType.isNull() && "lookup done with dependent qualifier?");
+    assert(QType->isRecordType() && "lookup done with non-record type");
+
+    QualType QRecordType = QualType(QType->getAs<RecordType>(), 0);
+
+    // In C++98, the qualifier type doesn't actually have to be a base
+    // type of the object type, in which case we just ignore it.
+    // Otherwise build the appropriate casts.
+    if (IsDerivedFrom(FromRecordType, QRecordType)) {
+      if (CheckDerivedToBaseConversion(FromRecordType, QRecordType,
+                                       FromLoc, FromRange))
+        return true;
+
       if (PointerConversions)
-        IntermediateType = Context.getPointerType(IntermediateType);
+        QType = Context.getPointerType(QType);
+      ImpCastExprToType(From, QType, CastExpr::CK_DerivedToBase,
+                        /*isLvalue*/ !PointerConversions);
+
+      FromType = QType;
+      FromRecordType = QRecordType;
+
+      // If the qualifier type was the same as the destination type,
+      // we're done.
+      if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))
+        return false;
     }
   }
 
-  if (!IntermediateType.isNull() &&
-      IsDerivedFrom(FromRecordType, IntermediateRecordType) &&
-      IsDerivedFrom(IntermediateRecordType, DestRecordType)) {
-    if (CheckDerivedToBaseConversion(FromRecordType, IntermediateRecordType,
-                                     From->getSourceRange().getBegin(),
-                                     From->getSourceRange()) ||
-        CheckDerivedToBaseConversion(IntermediateRecordType, DestRecordType,
-                                     From->getSourceRange().getBegin(),
-                                     From->getSourceRange()))
-      return true;
+  bool IgnoreAccess = false;
 
-    ImpCastExprToType(From, IntermediateType, CastExpr::CK_DerivedToBase,
-                      /*isLvalue=*/!PointerConversions);
-    ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase,
-                      /*isLvalue=*/!PointerConversions);
-    return false;
+  // If we actually found the member through a using declaration, cast
+  // down to the using declaration's type.
+  //
+  // Pointer equality is fine here because only one declaration of a
+  // class ever has member declarations.
+  if (FoundDecl->getDeclContext() != Member->getDeclContext()) {
+    assert(isa<UsingShadowDecl>(FoundDecl));
+    QualType URecordType = Context.getTypeDeclType(
+                           cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
+
+    // We only need to do this if the naming-class to declaring-class
+    // conversion is non-trivial.
+    if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) {
+      assert(IsDerivedFrom(FromRecordType, URecordType));
+      if (CheckDerivedToBaseConversion(FromRecordType, URecordType,
+                                       FromLoc, FromRange))
+        return true;
+      
+      QualType UType = URecordType;
+      if (PointerConversions)
+        UType = Context.getPointerType(UType);
+      ImpCastExprToType(From, UType, CastExpr::CK_DerivedToBase,
+                        /*isLvalue*/ !PointerConversions);
+      FromType = UType;
+      FromRecordType = URecordType;
+    }
+
+    // We don't do access control for the conversion from the
+    // declaring class to the true declaring class.
+    IgnoreAccess = true;
   }
 
   if (CheckDerivedToBaseConversion(FromRecordType,
                                    DestRecordType,
-                                   From->getSourceRange().getBegin(),
-                                   From->getSourceRange()))
+                                   FromLoc,
+                                   FromRange,
+                                   IgnoreAccess))
     return true;
 
+  // FIXME: isLvalue should be !PointerConversions here, but codegen
+  // does very silly things.
   ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase,
-                    /*isLvalue=*/true);
+                    /*isLvalue=*/ true);
   return false;
 }
 
 /// \brief Build a MemberExpr AST node.
 static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
                                    const CXXScopeSpec &SS, ValueDecl *Member,
-                                   SourceLocation Loc, QualType Ty,
+                                   NamedDecl *FoundDecl, SourceLocation Loc,
+                                   QualType Ty,
                           const TemplateArgumentListInfo *TemplateArgs = 0) {
   NestedNameSpecifier *Qualifier = 0;
   SourceRange QualifierRange;
@@ -1478,7 +1536,7 @@
   }
 
   return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
-                            Member, Loc, TemplateArgs, Ty);
+                            Member, FoundDecl, Loc, TemplateArgs, Ty);
 }
 
 /// Builds an implicit member access expression.  The current context
@@ -2692,6 +2750,7 @@
   }
 
   assert(R.isSingleResult());
+  NamedDecl *FoundDecl = *R.begin();
   NamedDecl *MemberDecl = R.getFoundDecl();
 
   // FIXME: diagnose the presence of template arguments now.
@@ -2754,30 +2813,30 @@
     }
 
     MarkDeclarationReferenced(MemberLoc, FD);
-    if (PerformObjectMemberConversion(BaseExpr, Qualifier, FD))
+    if (PerformObjectMemberConversion(BaseExpr, Qualifier, FoundDecl, FD))
       return ExprError();
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
-                                 FD, MemberLoc, MemberType));
+                                 FD, FoundDecl, MemberLoc, MemberType));
   }
 
   if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
     MarkDeclarationReferenced(MemberLoc, Var);
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
-                                 Var, MemberLoc,
+                                 Var, FoundDecl, MemberLoc,
                                  Var->getType().getNonReferenceType()));
   }
 
   if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
     MarkDeclarationReferenced(MemberLoc, MemberDecl);
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
-                                 MemberFn, MemberLoc,
+                                 MemberFn, FoundDecl, MemberLoc,
                                  MemberFn->getType()));
   }
 
   if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
     MarkDeclarationReferenced(MemberLoc, MemberDecl);
     return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
-                                 Enum, MemberLoc, Enum->getType()));
+                                 Enum, FoundDecl, MemberLoc, Enum->getType()));
   }
 
   Owned(BaseExpr);
@@ -6752,7 +6811,8 @@
         Res = BuildAnonymousStructUnionMemberReference(
             OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();
       } else {
-        PerformObjectMemberConversion(Res, /*Qualifier=*/0, MemberDecl);
+        PerformObjectMemberConversion(Res, /*Qualifier=*/0,
+                                      *R.begin(), MemberDecl);
         // MemberDecl->getType() doesn't get the right qualifiers, but it
         // doesn't matter here.
         Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Mar 30 16:47:33 2010
@@ -1650,14 +1650,16 @@
 
   case ICK_Function_To_Pointer:
     if (Context.getCanonicalType(FromType) == Context.OverloadTy) {
-      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true);
+      DeclAccessPair Found;
+      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType,
+                                                            true, Found);
       if (!Fn)
         return true;
 
       if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))
         return true;
 
-      From = FixOverloadedFunctionReference(From, Fn);
+      From = FixOverloadedFunctionReference(From, Found, Fn);
       FromType = From->getType();
         
       // If there's already an address-of operator in the expression, we have
@@ -2847,8 +2849,10 @@
 }
 
 CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, 
+                                                NamedDecl *FoundDecl,
                                                 CXXMethodDecl *Method) {
-  if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, Method))
+  if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0,
+                                          FoundDecl, Method))
     assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?");
 
   MemberExpr *ME = 
@@ -2892,7 +2896,8 @@
     assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");
 
     // Create an implicit call expr that calls it.
-    CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method);
+    // FIXME: pass the FoundDecl for the user-defined conversion here
+    CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method, Method);
     return MaybeBindToTemporary(CE);
   }
   }

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Mar 30 16:47:33 2010
@@ -2036,13 +2036,13 @@
 }
 
 void InitializationSequence::AddAddressOverloadResolutionStep(
-                                                      FunctionDecl *Function) {
+                                                      FunctionDecl *Function,
+                                                      DeclAccessPair Found) {
   Step S;
   S.Kind = SK_ResolveAddressOfOverloadedFunction;
   S.Type = Function->getType();
-  // Access is currently ignored for these.
   S.Function.Function = Function;
-  S.Function.FoundDecl = DeclAccessPair::make(Function, AS_none);
+  S.Function.FoundDecl = Found;
   Steps.push_back(S);
 }
 
@@ -2375,15 +2375,17 @@
   // to resolve the overloaded function. If all goes well, T2 is the
   // type of the resulting function.
   if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+    DeclAccessPair Found;
     FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer, 
                                                             T1,
-                                                            false);
+                                                            false,
+                                                            Found);
     if (!Fn) {
       Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
       return;
     }
     
-    Sequence.AddAddressOverloadResolutionStep(Fn);
+    Sequence.AddAddressOverloadResolutionStep(Fn, Found);
     cv2T2 = Fn->getType();
     T2 = cv2T2.getUnqualifiedType();
   }
@@ -3348,8 +3350,9 @@
     case SK_ResolveAddressOfOverloadedFunction:
       // Overload resolution determined which function invoke; update the 
       // initializer to reflect that choice.
-      // Access control was done in overload resolution.
+      S.CheckAddressOfMemberAccess(CurInitExpr, Step->Function.FoundDecl);
       CurInit = S.FixOverloadedFunctionReference(move(CurInit),
+                                                 Step->Function.FoundDecl,
                                                  Step->Function.Function);
       break;
         
@@ -3457,7 +3460,7 @@
         // derived-to-base conversion? I believe the answer is "no", because
         // we don't want to turn off access control here for c-style casts.
         if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0,
-                                                  Conversion))
+                                                  FoundFn, Conversion))
           return S.ExprError();
 
         // Do a little dance to make sure that CurInit has the proper
@@ -3465,7 +3468,8 @@
         CurInit.release();
         
         // Build the actual call to the conversion function.
-        CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, Conversion));
+        CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn,
+                                                   Conversion));
         if (CurInit.isInvalid() || !CurInit.get())
           return S.ExprError();
         
@@ -3649,11 +3653,14 @@
       << (Failure == FK_ArrayNeedsInitListOrStringLiteral);
     break;
       
-  case FK_AddressOfOverloadFailed:
+  case FK_AddressOfOverloadFailed: {
+    DeclAccessPair Found;
     S.ResolveAddressOfOverloadedFunction(Args[0], 
                                          DestType.getNonReferenceType(),
-                                         true);
+                                         true,
+                                         Found);
     break;
+  }
       
   case FK_ReferenceInitOverloadFailed:
   case FK_UserConversionOverloadFailed:

Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Tue Mar 30 16:47:33 2010
@@ -611,7 +611,8 @@
   ///
   /// \param Function the function to which the overloaded function reference
   /// resolves.
-  void AddAddressOverloadResolutionStep(FunctionDecl *Function);
+  void AddAddressOverloadResolutionStep(FunctionDecl *Function,
+                                        DeclAccessPair Found);
   
   /// \brief Add a new step in the initialization that performs a derived-to-
   /// base cast.

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Mar 30 16:47:33 2010
@@ -567,6 +567,8 @@
   // array-to-pointer conversion, or function-to-pointer conversion
   // (C++ 4p1).
 
+  DeclAccessPair AccessPair;
+
   // Lvalue-to-rvalue conversion (C++ 4.1):
   //   An lvalue (3.10) of a non-function, non-array type T can be
   //   converted to an rvalue.
@@ -612,7 +614,8 @@
     // function. (C++ 4.3p1).
     FromType = Context.getPointerType(FromType);
   } else if (FunctionDecl *Fn
-               = ResolveAddressOfOverloadedFunction(From, ToType, false)) {
+               = ResolveAddressOfOverloadedFunction(From, ToType, false,
+                                                    AccessPair)) {
     // Address of overloaded function (C++ [over.over]).
     SCS.First = ICK_Function_To_Pointer;
 
@@ -2278,6 +2281,7 @@
 bool
 Sema::PerformObjectArgumentInitialization(Expr *&From, 
                                           NestedNameSpecifier *Qualifier, 
+                                          NamedDecl *FoundDecl,
                                           CXXMethodDecl *Method) {
   QualType FromRecordType, DestType;
   QualType ImplicitParamRecordType  =
@@ -2302,7 +2306,7 @@
        << ImplicitParamRecordType << FromRecordType << From->getSourceRange();
 
   if (ICS.Standard.Second == ICK_Derived_To_Base)
-    return PerformObjectMemberConversion(From, Qualifier, Method);
+    return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);
 
   if (!Context.hasSameType(From->getType(), DestType))
     ImpCastExprToType(From, DestType, CastExpr::CK_NoOp,
@@ -4942,7 +4946,8 @@
 /// routine will emit diagnostics if there is an error.
 FunctionDecl *
 Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
-                                         bool Complain) {
+                                         bool Complain,
+                                         DeclAccessPair &FoundResult) {
   QualType FunctionType = ToType;
   bool IsMember = false;
   if (const PointerType *ToTypePtr = ToType->getAs<PointerType>())
@@ -5059,9 +5064,10 @@
     return 0;
   else if (Matches.size() == 1) {
     FunctionDecl *Result = Matches[0].second;
+    FoundResult = Matches[0].first;
     MarkDeclarationReferenced(From->getLocStart(), Result);
     if (Complain)
-      CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
+      CheckAddressOfMemberAccess(OvlExpr, Matches[0].first);
     return Result;
   }
 
@@ -5093,10 +5099,9 @@
                                << (unsigned) oc_function_template);
     assert(Result != MatchesCopy.end() && "no most-specialized template");
     MarkDeclarationReferenced(From->getLocStart(), *Result);
-    if (Complain) {
-      DeclAccessPair FoundDecl = Matches[Result - MatchesCopy.begin()].first;
-      CheckUnresolvedAccess(*this, OvlExpr, FoundDecl);
-    }
+    FoundResult = Matches[Result - MatchesCopy.begin()].first;
+    if (Complain)
+      CheckUnresolvedAccess(*this, OvlExpr, FoundResult);
     return cast<FunctionDecl>(*Result);
   }
 
@@ -5115,6 +5120,7 @@
   // selected function.
   if (Matches.size() == 1) {
     MarkDeclarationReferenced(From->getLocStart(), Matches[0].second);
+    FoundResult = Matches[0].first;
     if (Complain)
       CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first);
     return cast<FunctionDecl>(Matches[0].second);
@@ -5395,7 +5401,7 @@
   case OR_Success: {
     FunctionDecl *FDecl = Best->Function;
     CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
-    Fn = FixOverloadedFunctionReference(Fn, FDecl);
+    Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
     return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc);
   }
 
@@ -5522,7 +5528,8 @@
       if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
         CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl);
 
-        if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, Method))
+        if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0,
+                                                Best->FoundDecl, Method))
           return ExprError();
       } else {
         // Convert the arguments.
@@ -5716,7 +5723,7 @@
             return ExprError();
 
           if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, 
-                                                  Method))
+                                                  Best->FoundDecl, Method))
             return ExprError();
 
           Args[1] = RHS = Arg1.takeAs<Expr>();
@@ -5883,7 +5890,7 @@
         // Convert the arguments.
         CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
         if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, 
-                                                Method))
+                                                Best->FoundDecl, Method))
           return ExprError();
 
         // Convert the arguments.
@@ -5988,10 +5995,12 @@
   
   MemberExpr *MemExpr;
   CXXMethodDecl *Method = 0;
+  NamedDecl *FoundDecl = 0;
   NestedNameSpecifier *Qualifier = 0;
   if (isa<MemberExpr>(NakedMemExpr)) {
     MemExpr = cast<MemberExpr>(NakedMemExpr);
     Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
+    FoundDecl = MemExpr->getFoundDecl();
     Qualifier = MemExpr->getQualifier();
   } else {
     UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
@@ -6041,6 +6050,7 @@
     switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) {
     case OR_Success:
       Method = cast<CXXMethodDecl>(Best->Function);
+      FoundDecl = Best->FoundDecl;
       CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
       break;
 
@@ -6068,7 +6078,7 @@
       return ExprError();
     }
 
-    MemExprE = FixOverloadedFunctionReference(MemExprE, Method);
+    MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
 
     // If overload resolution picked a static member, build a
     // non-member call based on that function.
@@ -6093,9 +6103,12 @@
     return ExprError();
   
   // Convert the object argument (for a non-static member function call).
+  // We only need to do this if there was actually an overload; otherwise
+  // it was done at lookup.
   Expr *ObjectArg = MemExpr->getBase();
   if (!Method->isStatic() &&
-      PerformObjectArgumentInitialization(ObjectArg, Qualifier, Method))
+      PerformObjectArgumentInitialization(ObjectArg, Qualifier,
+                                          FoundDecl, Method))
     return ExprError();
   MemExpr->setBase(ObjectArg);
 
@@ -6255,7 +6268,8 @@
     
     // Create an implicit member expr to refer to the conversion operator.
     // and then call it.
-    CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Conv);
+    CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Best->FoundDecl,
+                                                   Conv);
       
     return ActOnCallExpr(S, ExprArg(*this, CE), LParenLoc,
                          MultiExprArg(*this, (ExprTy**)Args, NumArgs),
@@ -6315,7 +6329,7 @@
 
   // Initialize the implicit object parameter.
   IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, 
-                                                 Method);
+                                                 Best->FoundDecl, Method);
   TheCall->setArg(0, Object);
 
 
@@ -6436,7 +6450,8 @@
 
   // Convert the object parameter.
   CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function);
-  if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, Method))
+  if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0,
+                                          Best->FoundDecl, Method))
     return ExprError();
 
   // No concerns about early exits now.
@@ -6463,9 +6478,11 @@
 /// perhaps a '&' around it). We have resolved the overloaded function
 /// to the function declaration Fn, so patch up the expression E to
 /// refer (possibly indirectly) to Fn. Returns the new expr.
-Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
+Expr *Sema::FixOverloadedFunctionReference(Expr *E, NamedDecl *Found,
+                                           FunctionDecl *Fn) {
   if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
-    Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn);
+    Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(),
+                                                   Found, Fn);
     if (SubExpr == PE->getSubExpr())
       return PE->Retain();
     
@@ -6473,7 +6490,8 @@
   } 
   
   if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
-    Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn);
+    Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(),
+                                                   Found, Fn);
     assert(Context.hasSameType(ICE->getSubExpr()->getType(), 
                                SubExpr->getType()) &&
            "Implicit cast type cannot be determined from overload");
@@ -6497,7 +6515,8 @@
         // Fix the sub expression, which really has to be an
         // UnresolvedLookupExpr holding an overloaded member function
         // or template.
-        Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+        Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
+                                                       Found, Fn);
         if (SubExpr == UnOp->getSubExpr())
           return UnOp->Retain();
 
@@ -6518,7 +6537,8 @@
                                            MemPtrType, UnOp->getOperatorLoc());
       }
     }
-    Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
+    Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(),
+                                                   Found, Fn);
     if (SubExpr == UnOp->getSubExpr())
       return UnOp->Retain();
     
@@ -6580,6 +6600,7 @@
                               MemExpr->getQualifier(), 
                               MemExpr->getQualifierRange(),
                               Fn, 
+                              Found,
                               MemExpr->getMemberLoc(),
                               TemplateArgs,
                               Fn->getType());
@@ -6590,8 +6611,9 @@
 }
 
 Sema::OwningExprResult Sema::FixOverloadedFunctionReference(OwningExprResult E, 
+                                                            NamedDecl *Found,
                                                             FunctionDecl *Fn) {
-  return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Fn));
+  return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn));
 }
 
 } // end namespace clang

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Mar 30 16:47:33 2010
@@ -437,32 +437,35 @@
                               << CondExpr->getSourceRange()))
     return true;
 
-  llvm::SmallVector<CXXConversionDecl *, 4> ViableConversions;
-  llvm::SmallVector<CXXConversionDecl *, 4> ExplicitConversions;
+  UnresolvedSet<4> ViableConversions;
+  UnresolvedSet<4> ExplicitConversions;
   if (const RecordType *RecordTy = CondType->getAs<RecordType>()) {
     const UnresolvedSetImpl *Conversions
       = cast<CXXRecordDecl>(RecordTy->getDecl())
                                              ->getVisibleConversionFunctions();
     for (UnresolvedSetImpl::iterator I = Conversions->begin(),
            E = Conversions->end(); I != E; ++I) {
-      if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(*I))
+      if (CXXConversionDecl *Conversion
+            = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl()))
         if (Conversion->getConversionType().getNonReferenceType()
               ->isIntegralType()) {
           if (Conversion->isExplicit())
-            ExplicitConversions.push_back(Conversion);
+            ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
           else
-          ViableConversions.push_back(Conversion);
+            ViableConversions.addDecl(I.getDecl(), I.getAccess());
         }
     }
 
     switch (ViableConversions.size()) {
     case 0:
       if (ExplicitConversions.size() == 1) {
+        DeclAccessPair Found = ExplicitConversions[0];
+        CXXConversionDecl *Conversion =
+          cast<CXXConversionDecl>(Found->getUnderlyingDecl());
         // The user probably meant to invoke the given explicit
         // conversion; use it.
         QualType ConvTy
-          = ExplicitConversions[0]->getConversionType()
-                        .getNonReferenceType();
+          = Conversion->getConversionType().getNonReferenceType();
         std::string TypeStr;
         ConvTy.getAsStringInternal(TypeStr, S.Context.PrintingPolicy);
 
@@ -473,8 +476,7 @@
           << CodeModificationHint::CreateInsertion(
                             S.PP.getLocForEndOfToken(CondExpr->getLocEnd()),
                                ")");
-        S.Diag(ExplicitConversions[0]->getLocation(),
-             diag::note_switch_conversion)
+        S.Diag(Conversion->getLocation(), diag::note_switch_conversion)
           << ConvTy->isEnumeralType() << ConvTy;
 
         // If we aren't in a SFINAE context, build a call to the 
@@ -482,25 +484,32 @@
         if (S.isSFINAEContext())
           return true;
 
-        CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ExplicitConversions[0]);
+        S.CheckMemberOperatorAccess(CondExpr->getExprLoc(),
+                                    CondExpr, 0, Found);
+        CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found, Conversion);
       }
 
       // We'll complain below about a non-integral condition type.
       break;
 
-    case 1:
+    case 1: {
       // Apply this conversion.
-      CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ViableConversions[0]);
+      DeclAccessPair Found = ViableConversions[0];
+      S.CheckMemberOperatorAccess(CondExpr->getExprLoc(),
+                                  CondExpr, 0, Found);
+      CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found,
+                        cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
       break;
+    }
 
     default:
       S.Diag(SwitchLoc, diag::err_switch_multiple_conversions)
         << CondType << CondExpr->getSourceRange();
       for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
-        QualType ConvTy
-          = ViableConversions[I]->getConversionType().getNonReferenceType();
-        S.Diag(ViableConversions[I]->getLocation(),
-             diag::note_switch_conversion)
+        CXXConversionDecl *Conv
+          = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
+        QualType ConvTy = Conv->getConversionType().getNonReferenceType();
+        S.Diag(Conv->getLocation(), diag::note_switch_conversion)
           << ConvTy->isEnumeralType() << ConvTy;
       }
       return true;

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Mar 30 16:47:33 2010
@@ -2617,6 +2617,8 @@
     return false;
   }
 
+  DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction
+
   // Handle pointer-to-function, reference-to-function, and
   // pointer-to-member-function all in (roughly) the same way.
   if (// -- For a non-type template-parameter of type pointer to
@@ -2656,11 +2658,12 @@
       ArgType = Context.getPointerType(ArgType);
       ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay);
     } else if (FunctionDecl *Fn
-                 = ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) {
+                 = ResolveAddressOfOverloadedFunction(Arg, ParamType, true,
+                                                      FoundResult)) {
       if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
         return true;
 
-      Arg = FixOverloadedFunctionReference(Arg, Fn);
+      Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
       ArgType = Arg->getType();
       if (ArgType->isFunctionType() && ParamType->isPointerType()) {
         ArgType = Context.getPointerType(Arg->getType());

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Mar 30 16:47:33 2010
@@ -2004,7 +2004,7 @@
     // function template specialization wherever deduction cannot occur.
     if (FunctionDecl *Specialization
         = ResolveSingleFunctionTemplateSpecialization(E)) {
-      E = FixOverloadedFunctionReference(E, Specialization);
+      E = FixOverloadedFunctionReference(E, Specialization, Specialization);
       if (!E)
         return QualType();      
     } else {
@@ -2024,7 +2024,7 @@
     // function template specialization wherever deduction cannot occur.
     if (FunctionDecl *Specialization
           = ResolveSingleFunctionTemplateSpecialization(E)) {
-      E = FixOverloadedFunctionReference(E, Specialization);
+      E = FixOverloadedFunctionReference(E, Specialization, Specialization);
       if (!E)
         return QualType();      
     } else {

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Mar 30 16:47:33 2010
@@ -977,6 +977,7 @@
                                      SourceRange QualifierRange,
                                      SourceLocation MemberLoc,
                                      ValueDecl *Member,
+                                     NamedDecl *FoundDecl,
                         const TemplateArgumentListInfo *ExplicitTemplateArgs,
                                      NamedDecl *FirstQualifierInScope) {
     if (!Member->getDeclName()) {
@@ -984,7 +985,8 @@
       assert(!Qualifier && "Can't have an unnamed field with a qualifier!");
 
       Expr *BaseExpr = Base.takeAs<Expr>();
-      if (getSema().PerformObjectMemberConversion(BaseExpr, Qualifier, Member))
+      if (getSema().PerformObjectMemberConversion(BaseExpr, Qualifier,
+                                                  FoundDecl, Member))
         return getSema().ExprError();
 
       MemberExpr *ME =
@@ -1002,9 +1004,11 @@
 
     QualType BaseType = ((Expr*) Base.get())->getType();
 
+    // FIXME: this involves duplicating earlier analysis in a lot of
+    // cases; we should avoid this when possible.
     LookupResult R(getSema(), Member->getDeclName(), MemberLoc,
                    Sema::LookupMemberName);
-    R.addDecl(Member);
+    R.addDecl(FoundDecl);
     R.resolveKind();
 
     return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
@@ -3868,10 +3872,21 @@
   if (!Member)
     return SemaRef.ExprError();
 
+  NamedDecl *FoundDecl = E->getFoundDecl();
+  if (FoundDecl == E->getMemberDecl()) {
+    FoundDecl = Member;
+  } else {
+    FoundDecl = cast_or_null<NamedDecl>(
+                   getDerived().TransformDecl(E->getMemberLoc(), FoundDecl));
+    if (!FoundDecl)
+      return SemaRef.ExprError();
+  }
+
   if (!getDerived().AlwaysRebuild() &&
       Base.get() == E->getBase() &&
       Qualifier == E->getQualifier() &&
       Member == E->getMemberDecl() &&
+      FoundDecl == E->getFoundDecl() &&
       !E->hasExplicitTemplateArgumentList()) {
     
     // Mark it referenced in the new context regardless.
@@ -3908,6 +3923,7 @@
                                         E->getQualifierRange(),
                                         E->getMemberLoc(),
                                         Member,
+                                        FoundDecl,
                                         (E->hasExplicitTemplateArgumentList()
                                            ? &TransArgs : 0),
                                         FirstQualifierInScope);

Modified: cfe/trunk/test/CXX/class.access/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p4.cpp?rev=99936&r1=99935&r2=99936&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/p4.cpp (original)
+++ cfe/trunk/test/CXX/class.access/p4.cpp Tue Mar 30 16:47:33 2010
@@ -309,3 +309,21 @@
     }
   };
 }
+
+namespace test13 {
+  struct A {
+    int x;
+    unsigned foo() const;
+  };
+
+  struct B : protected A {
+    using A::foo;
+    using A::x;
+  };
+
+  void test() {
+    A *d;
+    d->foo();
+    (void) d->x;
+  }
+}





More information about the cfe-commits mailing list