From f2a42a66e2d9b39bfaf90aae2e14e7a1d1c37025 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 3 Mar 2010 22:53:40 +0000 Subject: Implement disambiguation of base class members via a nested-name-specifier. For example, this allows member access in diamond-shaped hierarchies like: struct Base { void Foo(); int Member; }; struct D1 : public Base {}; struct D2 : public Base {}; struct Derived : public D1, public D2 { } void Test(Derived d) { d.Member = 17; // error: ambiguous cast from Derived to Base d.D1::Member = 17; // error: okay, modify D1's Base's Member } Fixes PR5820 and . Also, eliminate some redundancy between Sema::PerformObjectMemberConversion() and Sema::PerformObjectArgumentInitialization() -- the latter now calls the former. llvm-svn: 97674 --- clang/lib/Sema/SemaOverload.cpp | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'clang/lib/Sema/SemaOverload.cpp') diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index ed0d137d806..5ff4adcc0d5 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2304,7 +2304,9 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType, /// the implicit object parameter for the given Method with the given /// expression. bool -Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) { +Sema::PerformObjectArgumentInitialization(Expr *&From, + NestedNameSpecifier *Qualifier, + CXXMethodDecl *Method) { QualType FromRecordType, DestType; QualType ImplicitParamRecordType = Method->getThisType(Context)->getAs()->getPointeeType(); @@ -2327,15 +2329,12 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) { diag::err_implicit_object_parameter_init) << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); - if (ICS.Standard.Second == ICK_Derived_To_Base && - CheckDerivedToBaseConversion(FromRecordType, - ImplicitParamRecordType, - From->getSourceRange().getBegin(), - From->getSourceRange())) - return true; + if (ICS.Standard.Second == ICK_Derived_To_Base) + return PerformObjectMemberConversion(From, Qualifier, Method); - ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/true); + if (!Context.hasSameType(From->getType(), DestType)) + ImpCastExprToType(From, DestType, CastExpr::CK_NoOp, + /*isLvalue=*/!From->getType()->getAs()); return false; } @@ -5545,7 +5544,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess()); - if (PerformObjectArgumentInitialization(Input, Method)) + if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, Method)) return ExprError(); } else { // Convert the arguments. @@ -5738,7 +5737,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Arg1.isInvalid()) return ExprError(); - if (PerformObjectArgumentInitialization(Args[0], Method)) + if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Method)) return ExprError(); Args[1] = RHS = Arg1.takeAs(); @@ -5904,7 +5904,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Convert the arguments. CXXMethodDecl *Method = cast(FnDecl); - if (PerformObjectArgumentInitialization(Args[0], Method)) + if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Method)) return ExprError(); // Convert the arguments. @@ -6009,12 +6010,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, MemberExpr *MemExpr; CXXMethodDecl *Method = 0; + NestedNameSpecifier *Qualifier = 0; if (isa(NakedMemExpr)) { MemExpr = cast(NakedMemExpr); Method = cast(MemExpr->getMemberDecl()); + Qualifier = MemExpr->getQualifier(); } else { UnresolvedMemberExpr *UnresExpr = cast(NakedMemExpr); - + Qualifier = UnresExpr->getQualifier(); + QualType ObjectType = UnresExpr->getBaseType(); // Add overload candidates @@ -6113,7 +6117,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // Convert the object argument (for a non-static member function call). Expr *ObjectArg = MemExpr->getBase(); if (!Method->isStatic() && - PerformObjectArgumentInitialization(ObjectArg, Method)) + PerformObjectArgumentInitialization(ObjectArg, Qualifier, Method)) return ExprError(); MemExpr->setBase(ObjectArg); @@ -6333,7 +6337,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, bool IsError = false; // Initialize the implicit object parameter. - IsError |= PerformObjectArgumentInitialization(Object, Method); + IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, + Method); TheCall->setArg(0, Object); @@ -6458,7 +6463,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { // Convert the object parameter. CXXMethodDecl *Method = cast(Best->Function); - if (PerformObjectArgumentInitialization(Base, Method)) + if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, Method)) return ExprError(); // No concerns about early exits now. -- cgit v1.2.3