diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 51 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 16 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 25 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 130 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 27 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaInit.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 68 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 41 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 20 | 
14 files changed, 293 insertions, 129 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 935a2080dcc..a9b5f36a983 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -499,44 +499,45 @@ QualType CallExpr::getCallReturnType() const {    return FnType->getResultType();  } -MemberExpr::MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, -                       SourceRange qualrange, ValueDecl *memberdecl, -                       SourceLocation l, const TemplateArgumentListInfo *targs, -                       QualType ty) -  : Expr(MemberExprClass, ty, -         base->isTypeDependent() || (qual && qual->isDependent()), -         base->isValueDependent() || (qual && qual->isDependent())), -    Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), -    HasQualifier(qual != 0), HasExplicitTemplateArgumentList(targs) { -  // Initialize the qualifier, if any. -  if (HasQualifier) { -    NameQualifier *NQ = getMemberQualifier(); -    NQ->NNS = qual; -    NQ->Range = qualrange; -  } - -  // Initialize the explicit template argument list, if any. -  if (targs) -    getExplicitTemplateArgumentList()->initializeFrom(*targs); -} -  MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, bool isarrow,                                 NestedNameSpecifier *qual,                                 SourceRange qualrange,                                 ValueDecl *memberdecl, +                               NamedDecl *founddecl,                                 SourceLocation l,                                 const TemplateArgumentListInfo *targs,                                 QualType ty) {    std::size_t Size = sizeof(MemberExpr); -  if (qual != 0) -    Size += sizeof(NameQualifier); + +  bool hasQualOrFound = (qual != 0 || founddecl != memberdecl); +  if (hasQualOrFound) +    Size += sizeof(MemberNameQualifier);    if (targs)      Size += ExplicitTemplateArgumentList::sizeFor(*targs);    void *Mem = C.Allocate(Size, llvm::alignof<MemberExpr>()); -  return new (Mem) MemberExpr(base, isarrow, qual, qualrange, memberdecl, l, -                              targs, ty); +  MemberExpr *E = new (Mem) MemberExpr(base, isarrow, memberdecl, l, ty); + +  if (hasQualOrFound) { +    if (qual && qual->isDependent()) { +      E->setValueDependent(true); +      E->setTypeDependent(true); +    } +    E->HasQualifierOrFoundDecl = true; + +    MemberNameQualifier *NQ = E->getMemberQualifier(); +    NQ->NNS = qual; +    NQ->Range = qualrange; +    NQ->FoundDecl = founddecl; +  } + +  if (targs) { +    E->HasExplicitTemplateArgumentList = true; +    E->getExplicitTemplateArgumentList()->initializeFrom(*targs); +  } + +  return E;  }  const char *CastExpr::getCastKindName() const { diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 859e4975764..d3e55f381e1 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1119,6 +1119,7 @@ public:                                    CXXRecordDecl *ActingContext);    bool PerformObjectArgumentInitialization(Expr *&From,                                              NestedNameSpecifier *Qualifier, +                                           NamedDecl *FoundDecl,                                             CXXMethodDecl *Method);    ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From); @@ -1126,6 +1127,7 @@ public:    bool PerformObjectMemberConversion(Expr *&From,                                        NestedNameSpecifier *Qualifier, +                                     NamedDecl *FoundDecl,                                       NamedDecl *Member);    // Members have to be NamespaceDecl* or TranslationUnitDecl*. @@ -1246,11 +1248,15 @@ public:                                     const PartialDiagnostic &PDiag);    FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, -                                                   bool Complain); +                                                   bool Complain, +                                                   DeclAccessPair &Found);    FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From); -  Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); +  Expr *FixOverloadedFunctionReference(Expr *E, +                                       NamedDecl *FoundDecl, +                                       FunctionDecl *Fn);    OwningExprResult FixOverloadedFunctionReference(OwningExprResult,  +                                                  NamedDecl *FoundDecl,                                                    FunctionDecl *Fn);    void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, @@ -2395,7 +2401,9 @@ public:    Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,                                    QualType EncodedType,                                    SourceLocation RParenLoc); -  CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp, CXXMethodDecl *Method); +  CXXMemberCallExpr *BuildCXXMemberCallExpr(Expr *Exp, +                                            NamedDecl *FoundDecl, +                                            CXXMethodDecl *Method);    virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,                                                 SourceLocation EncodeLoc, @@ -2640,6 +2648,8 @@ public:                                           Expr *ObjectExpr,                                           Expr *ArgExpr,                                           DeclAccessPair FoundDecl); +  AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr, +                                          DeclAccessPair FoundDecl);    AccessResult CheckBaseClassAccess(SourceLocation AccessLoc,                                      QualType Base, QualType Derived,                                      const CXXBasePath &Path, diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index e7ea2041370..e356c52a684 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -907,6 +907,31 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,    return CheckAccess(*this, OpLoc, Entity);  } +Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, +                                                    DeclAccessPair Found) { +  if (!getLangOptions().AccessControl || +      Found.getAccess() == AS_public) +    return AR_accessible; + +  OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).getPointer(); +  NestedNameSpecifier *Qualifier = Ovl->getQualifier(); +  assert(Qualifier && "address of overloaded member without qualifier"); + +  CXXScopeSpec SS; +  SS.setScopeRep(Qualifier); +  SS.setRange(Ovl->getQualifierRange()); +  DeclContext *DC = computeDeclContext(SS); +  assert(DC && DC->isRecord() && "scope did not resolve to record"); +  CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(DC); + +  AccessedEntity Entity(Context, AccessedEntity::Member, NamingClass, Found); +  Entity.setDiag(diag::err_access) +    << Ovl->getSourceRange(); + +  return CheckAccess(*this, Ovl->getNameLoc(), Entity); +} + +  /// Checks access for a hierarchy conversion.  ///  /// \param IsBaseToDerived whether this is a base-to-derived conversion (true) diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 2b93d38e2ab..11c8e6ddab5 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -808,8 +808,10 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,      return TC_NotApplicable;    bool WasOverloadedFunction = false; +  DeclAccessPair FoundOverload;    if (FunctionDecl *Fn -          = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false)) { +        = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false, +                                                  FoundOverload)) {      CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);      SrcType = Self.Context.getMemberPointerType(Fn->getType(),                      Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); @@ -870,13 +872,14 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,      // allowing complaints if something goes wrong.      FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr,                                                                  DestType,  -                                                               true); +                                                               true, +                                                               FoundOverload);      if (!Fn) {        msg = 0;        return TC_Failed;      } -    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, Fn); +    SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);      if (!SrcExpr) {        msg = 0;        return TC_Failed; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 49352b5f4eb..dfaa85559bb 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4409,16 +4409,18 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,    // to resolve the overloaded function. If all goes well, T2 is the    // type of the resulting function.    if (Context.getCanonicalType(T2) == Context.OverloadTy) { +    DeclAccessPair Found;      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Init, DeclType, -                                                          ICS != 0); +                                                          ICS != 0, Found);      if (Fn) {        // Since we're performing this reference-initialization for        // real, update the initializer with the resulting function.        if (!ICS) {          if (DiagnoseUseOfDecl(Fn, DeclLoc)) -          return true;  +          return true; -        Init = FixOverloadedFunctionReference(Init, Fn); +        CheckAddressOfMemberAccess(Init, Found); +        Init = FixOverloadedFunctionReference(Init, Found, Fn);        }        T2 = Fn->getType(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0c9b3bd44bf..406b8201a3f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -635,7 +635,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,        MemberType = Context.getQualifiedType(MemberType, NewQuals);      MarkDeclarationReferenced(Loc, *FI); -    PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI); +    PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI);      // FIXME: Might this end up being a qualified name?      Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,                                        OpLoc, MemberType); @@ -1355,10 +1355,27 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,    return Owned((Expr*) 0);  } -/// \brief Cast member's object to its own class if necessary. +/// \brief Cast a base object to a member's actual type. +/// +/// Logically this happens in three phases: +/// +/// * First we cast from the base type to the naming class. +///   The naming class is the class into which we were looking +///   when we found the member;  it's the qualifier type if a +///   qualifier was provided, and otherwise it's the base type. +/// +/// * Next we cast from the naming class to the declaring class. +///   If the member we found was brought into a class's scope by +///   a using declaration, this is that class;  otherwise it's +///   the class declaring the member. +/// +/// * Finally we cast from the declaring class to the "true" +///   declaring class of the member.  This conversion does not +///   obey access control.  bool  Sema::PerformObjectMemberConversion(Expr *&From,                                      NestedNameSpecifier *Qualifier, +                                    NamedDecl *FoundDecl,                                      NamedDecl *Member) {    CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext());    if (!RD) @@ -1406,6 +1423,9 @@ Sema::PerformObjectMemberConversion(Expr *&From,    if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType))      return false; +  SourceRange FromRange = From->getSourceRange(); +  SourceLocation FromLoc = FromRange.getBegin(); +    // C++ [class.member.lookup]p8:    //   [...] Ambiguities can often be resolved by qualifying a name with its    //   class name. @@ -1424,51 +1444,89 @@ Sema::PerformObjectMemberConversion(Expr *&From,    //     x = 17; // error: ambiguous base subobjects    //     Derived1::x = 17; // okay, pick the Base subobject of Derived1    //   } -  QualType IntermediateRecordType; -  QualType IntermediateType;    if (Qualifier) { -    if (const RecordType *IntermediateRecord -                           = Qualifier->getAsType()->getAs<RecordType>()) { -      IntermediateRecordType = QualType(IntermediateRecord, 0); -      IntermediateType = IntermediateRecordType; +    QualType QType = QualType(Qualifier->getAsType(), 0); +    assert(!QType.isNull() && "lookup done with dependent qualifier?"); +    assert(QType->isRecordType() && "lookup done with non-record type"); + +    QualType QRecordType = QualType(QType->getAs<RecordType>(), 0); + +    // In C++98, the qualifier type doesn't actually have to be a base +    // type of the object type, in which case we just ignore it. +    // Otherwise build the appropriate casts. +    if (IsDerivedFrom(FromRecordType, QRecordType)) { +      if (CheckDerivedToBaseConversion(FromRecordType, QRecordType, +                                       FromLoc, FromRange)) +        return true; +        if (PointerConversions) -        IntermediateType = Context.getPointerType(IntermediateType); +        QType = Context.getPointerType(QType); +      ImpCastExprToType(From, QType, CastExpr::CK_DerivedToBase, +                        /*isLvalue*/ !PointerConversions); + +      FromType = QType; +      FromRecordType = QRecordType; + +      // If the qualifier type was the same as the destination type, +      // we're done. +      if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) +        return false;      }    } -  if (!IntermediateType.isNull() && -      IsDerivedFrom(FromRecordType, IntermediateRecordType) && -      IsDerivedFrom(IntermediateRecordType, DestRecordType)) { -    if (CheckDerivedToBaseConversion(FromRecordType, IntermediateRecordType, -                                     From->getSourceRange().getBegin(), -                                     From->getSourceRange()) || -        CheckDerivedToBaseConversion(IntermediateRecordType, DestRecordType, -                                     From->getSourceRange().getBegin(), -                                     From->getSourceRange())) -      return true; +  bool IgnoreAccess = false; -    ImpCastExprToType(From, IntermediateType, CastExpr::CK_DerivedToBase, -                      /*isLvalue=*/!PointerConversions); -    ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, -                      /*isLvalue=*/!PointerConversions); -    return false; +  // If we actually found the member through a using declaration, cast +  // down to the using declaration's type. +  // +  // Pointer equality is fine here because only one declaration of a +  // class ever has member declarations. +  if (FoundDecl->getDeclContext() != Member->getDeclContext()) { +    assert(isa<UsingShadowDecl>(FoundDecl)); +    QualType URecordType = Context.getTypeDeclType( +                           cast<CXXRecordDecl>(FoundDecl->getDeclContext())); + +    // We only need to do this if the naming-class to declaring-class +    // conversion is non-trivial. +    if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) { +      assert(IsDerivedFrom(FromRecordType, URecordType)); +      if (CheckDerivedToBaseConversion(FromRecordType, URecordType, +                                       FromLoc, FromRange)) +        return true; +       +      QualType UType = URecordType; +      if (PointerConversions) +        UType = Context.getPointerType(UType); +      ImpCastExprToType(From, UType, CastExpr::CK_DerivedToBase, +                        /*isLvalue*/ !PointerConversions); +      FromType = UType; +      FromRecordType = URecordType; +    } + +    // We don't do access control for the conversion from the +    // declaring class to the true declaring class. +    IgnoreAccess = true;    }    if (CheckDerivedToBaseConversion(FromRecordType,                                     DestRecordType, -                                   From->getSourceRange().getBegin(), -                                   From->getSourceRange())) +                                   FromLoc, +                                   FromRange, +                                   IgnoreAccess))      return true; +  // FIXME: isLvalue should be !PointerConversions here, but codegen +  // does very silly things.    ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, -                    /*isLvalue=*/true); +                    /*isLvalue=*/ true);    return false;  }  /// \brief Build a MemberExpr AST node.  static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,                                     const CXXScopeSpec &SS, ValueDecl *Member, -                                   SourceLocation Loc, QualType Ty, +                                   NamedDecl *FoundDecl, SourceLocation Loc, +                                   QualType Ty,                            const TemplateArgumentListInfo *TemplateArgs = 0) {    NestedNameSpecifier *Qualifier = 0;    SourceRange QualifierRange; @@ -1478,7 +1536,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,    }    return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange, -                            Member, Loc, TemplateArgs, Ty); +                            Member, FoundDecl, Loc, TemplateArgs, Ty);  }  /// Builds an implicit member access expression.  The current context @@ -2692,6 +2750,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,    }    assert(R.isSingleResult()); +  NamedDecl *FoundDecl = *R.begin();    NamedDecl *MemberDecl = R.getFoundDecl();    // FIXME: diagnose the presence of template arguments now. @@ -2754,30 +2813,30 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType,      }      MarkDeclarationReferenced(MemberLoc, FD); -    if (PerformObjectMemberConversion(BaseExpr, Qualifier, FD)) +    if (PerformObjectMemberConversion(BaseExpr, Qualifier, FoundDecl, FD))        return ExprError();      return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, -                                 FD, MemberLoc, MemberType)); +                                 FD, FoundDecl, MemberLoc, MemberType));    }    if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {      MarkDeclarationReferenced(MemberLoc, Var);      return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, -                                 Var, MemberLoc, +                                 Var, FoundDecl, MemberLoc,                                   Var->getType().getNonReferenceType()));    }    if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {      MarkDeclarationReferenced(MemberLoc, MemberDecl);      return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, -                                 MemberFn, MemberLoc, +                                 MemberFn, FoundDecl, MemberLoc,                                   MemberFn->getType()));    }    if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {      MarkDeclarationReferenced(MemberLoc, MemberDecl);      return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, -                                 Enum, MemberLoc, Enum->getType())); +                                 Enum, FoundDecl, MemberLoc, Enum->getType()));    }    Owned(BaseExpr); @@ -6752,7 +6811,8 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,          Res = BuildAnonymousStructUnionMemberReference(              OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs<Expr>();        } else { -        PerformObjectMemberConversion(Res, /*Qualifier=*/0, MemberDecl); +        PerformObjectMemberConversion(Res, /*Qualifier=*/0, +                                      *R.begin(), MemberDecl);          // MemberDecl->getType() doesn't get the right qualifiers, but it          // doesn't matter here.          Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c31d93416d7..9baa6ac079b 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1650,14 +1650,16 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,    case ICK_Function_To_Pointer:      if (Context.getCanonicalType(FromType) == Context.OverloadTy) { -      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true); +      DeclAccessPair Found; +      FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, +                                                            true, Found);        if (!Fn)          return true;        if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))          return true; -      From = FixOverloadedFunctionReference(From, Fn); +      From = FixOverloadedFunctionReference(From, Found, Fn);        FromType = From->getType();        // If there's already an address-of operator in the expression, we have @@ -2847,8 +2849,10 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,  }  CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,  +                                                NamedDecl *FoundDecl,                                                  CXXMethodDecl *Method) { -  if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, Method)) +  if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, +                                          FoundDecl, Method))      assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?");    MemberExpr *ME =  @@ -2892,7 +2896,8 @@ Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,      assert(!From->getType()->isPointerType() && "Arg can't have pointer type!");      // Create an implicit call expr that calls it. -    CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method); +    // FIXME: pass the FoundDecl for the user-defined conversion here +    CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method, Method);      return MaybeBindToTemporary(CE);    }    } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 0b2e1db6a00..4612bda7b24 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2036,13 +2036,13 @@ bool InitializationSequence::isAmbiguous() const {  }  void InitializationSequence::AddAddressOverloadResolutionStep( -                                                      FunctionDecl *Function) { +                                                      FunctionDecl *Function, +                                                      DeclAccessPair Found) {    Step S;    S.Kind = SK_ResolveAddressOfOverloadedFunction;    S.Type = Function->getType(); -  // Access is currently ignored for these.    S.Function.Function = Function; -  S.Function.FoundDecl = DeclAccessPair::make(Function, AS_none); +  S.Function.FoundDecl = Found;    Steps.push_back(S);  } @@ -2375,15 +2375,17 @@ static void TryReferenceInitialization(Sema &S,    // to resolve the overloaded function. If all goes well, T2 is the    // type of the resulting function.    if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { +    DeclAccessPair Found;      FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer,                                                               T1, -                                                            false); +                                                            false, +                                                            Found);      if (!Fn) {        Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);        return;      } -    Sequence.AddAddressOverloadResolutionStep(Fn); +    Sequence.AddAddressOverloadResolutionStep(Fn, Found);      cv2T2 = Fn->getType();      T2 = cv2T2.getUnqualifiedType();    } @@ -3348,8 +3350,9 @@ InitializationSequence::Perform(Sema &S,      case SK_ResolveAddressOfOverloadedFunction:        // Overload resolution determined which function invoke; update the         // initializer to reflect that choice. -      // Access control was done in overload resolution. +      S.CheckAddressOfMemberAccess(CurInitExpr, Step->Function.FoundDecl);        CurInit = S.FixOverloadedFunctionReference(move(CurInit), +                                                 Step->Function.FoundDecl,                                                   Step->Function.Function);        break; @@ -3457,7 +3460,7 @@ InitializationSequence::Perform(Sema &S,          // derived-to-base conversion? I believe the answer is "no", because          // we don't want to turn off access control here for c-style casts.          if (S.PerformObjectArgumentInitialization(CurInitExpr, /*Qualifier=*/0, -                                                  Conversion)) +                                                  FoundFn, Conversion))            return S.ExprError();          // Do a little dance to make sure that CurInit has the proper @@ -3465,7 +3468,8 @@ InitializationSequence::Perform(Sema &S,          CurInit.release();          // Build the actual call to the conversion function. -        CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, Conversion)); +        CurInit = S.Owned(S.BuildCXXMemberCallExpr(CurInitExpr, FoundFn, +                                                   Conversion));          if (CurInit.isInvalid() || !CurInit.get())            return S.ExprError(); @@ -3649,11 +3653,14 @@ bool InitializationSequence::Diagnose(Sema &S,        << (Failure == FK_ArrayNeedsInitListOrStringLiteral);      break; -  case FK_AddressOfOverloadFailed: +  case FK_AddressOfOverloadFailed: { +    DeclAccessPair Found;      S.ResolveAddressOfOverloadedFunction(Args[0],                                            DestType.getNonReferenceType(), -                                         true); +                                         true, +                                         Found);      break; +  }    case FK_ReferenceInitOverloadFailed:    case FK_UserConversionOverloadFailed: diff --git a/clang/lib/Sema/SemaInit.h b/clang/lib/Sema/SemaInit.h index d57679ab757..7c6327f8c7f 100644 --- a/clang/lib/Sema/SemaInit.h +++ b/clang/lib/Sema/SemaInit.h @@ -611,7 +611,8 @@ public:    ///    /// \param Function the function to which the overloaded function reference    /// resolves. -  void AddAddressOverloadResolutionStep(FunctionDecl *Function); +  void AddAddressOverloadResolutionStep(FunctionDecl *Function, +                                        DeclAccessPair Found);    /// \brief Add a new step in the initialization that performs a derived-to-    /// base cast. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 58d7d675085..8d3313982c8 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -567,6 +567,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,    // array-to-pointer conversion, or function-to-pointer conversion    // (C++ 4p1). +  DeclAccessPair AccessPair; +    // Lvalue-to-rvalue conversion (C++ 4.1):    //   An lvalue (3.10) of a non-function, non-array type T can be    //   converted to an rvalue. @@ -612,7 +614,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,      // function. (C++ 4.3p1).      FromType = Context.getPointerType(FromType);    } else if (FunctionDecl *Fn -               = ResolveAddressOfOverloadedFunction(From, ToType, false)) { +               = ResolveAddressOfOverloadedFunction(From, ToType, false, +                                                    AccessPair)) {      // Address of overloaded function (C++ [over.over]).      SCS.First = ICK_Function_To_Pointer; @@ -2278,6 +2281,7 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType,  bool  Sema::PerformObjectArgumentInitialization(Expr *&From,                                             NestedNameSpecifier *Qualifier,  +                                          NamedDecl *FoundDecl,                                            CXXMethodDecl *Method) {    QualType FromRecordType, DestType;    QualType ImplicitParamRecordType  = @@ -2302,7 +2306,7 @@ Sema::PerformObjectArgumentInitialization(Expr *&From,         << ImplicitParamRecordType << FromRecordType << From->getSourceRange();    if (ICS.Standard.Second == ICK_Derived_To_Base) -    return PerformObjectMemberConversion(From, Qualifier, Method); +    return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method);    if (!Context.hasSameType(From->getType(), DestType))      ImpCastExprToType(From, DestType, CastExpr::CK_NoOp, @@ -4942,7 +4946,8 @@ static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) {  /// routine will emit diagnostics if there is an error.  FunctionDecl *  Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, -                                         bool Complain) { +                                         bool Complain, +                                         DeclAccessPair &FoundResult) {    QualType FunctionType = ToType;    bool IsMember = false;    if (const PointerType *ToTypePtr = ToType->getAs<PointerType>()) @@ -5059,9 +5064,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,      return 0;    else if (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 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,                                 << (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 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,    // 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 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,    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 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn,        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 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,              return ExprError();            if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0,  -                                                  Method)) +                                                  Best->FoundDecl, Method))              return ExprError();            Args[1] = RHS = Arg1.takeAs<Expr>(); @@ -5883,7 +5890,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,          // 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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,    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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,      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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,        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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,      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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,      // 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 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,    // Initialize the implicit object parameter.    IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0,  -                                                 Method); +                                                 Best->FoundDecl, Method);    TheCall->setArg(0, Object); @@ -6436,7 +6450,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {    // 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 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {  /// 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 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {    }     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 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {          // 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 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {                                             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 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {                                MemExpr->getQualifier(),                                 MemExpr->getQualifierRange(),                                Fn,  +                              Found,                                MemExpr->getMemberLoc(),                                TemplateArgs,                                Fn->getType()); @@ -6590,8 +6611,9 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {  }  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 diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 1e37bb00c47..fd30a5360e5 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -437,32 +437,35 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc,                                << 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 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc,            << 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 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc,          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; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index d1f0815eae5..4507e648684 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2617,6 +2617,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,      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 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,        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()); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 099d30a44fc..ce410a7605c 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2004,7 +2004,7 @@ QualType Sema::BuildTypeofExprType(Expr *E) {      // 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 @@ QualType Sema::BuildDecltypeType(Expr *E) {      // 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 { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index d6f3352266a..c7ea17fde68 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -977,6 +977,7 @@ public:                                       SourceRange QualifierRange,                                       SourceLocation MemberLoc,                                       ValueDecl *Member, +                                     NamedDecl *FoundDecl,                          const TemplateArgumentListInfo *ExplicitTemplateArgs,                                       NamedDecl *FirstQualifierInScope) {      if (!Member->getDeclName()) { @@ -984,7 +985,8 @@ public:        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 @@ public:      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 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {    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 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) {                                          E->getQualifierRange(),                                          E->getMemberLoc(),                                          Member, +                                        FoundDecl,                                          (E->hasExplicitTemplateArgumentList()                                             ? &TransArgs : 0),                                          FirstQualifierInScope);  | 

