From: Douglas Gregor Date: Wed, 3 Mar 2010 23:26:56 +0000 (+0000) Subject: Revert r97674; it's causing failures X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a7cb22d27f4440d264f2a1407c43b8d7259d23b0;p=clang Revert r97674; it's causing failures git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97677 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index a94d07a6ac..efd04e8edd 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1097,16 +1097,12 @@ public: ImplicitConversionSequence TryObjectArgumentInitialization(QualType FromType, CXXMethodDecl *Method, CXXRecordDecl *ActingContext); - bool PerformObjectArgumentInitialization(Expr *&From, - NestedNameSpecifier *Qualifier, - CXXMethodDecl *Method); + bool PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method); ImplicitConversionSequence TryContextuallyConvertToBool(Expr *From); bool PerformContextuallyConvertToBool(Expr *&From); - bool PerformObjectMemberConversion(Expr *&From, - NestedNameSpecifier *Qualifier, - NamedDecl *Member); + bool PerformObjectMemberConversion(Expr *&From, NamedDecl *Member); // Members have to be NamespaceDecl* or TranslationUnitDecl*. // TODO: make this is a typesafe union. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d8648f2b69..d9464ad8c0 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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, *FI); // FIXME: Might this end up being a qualified name? Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); @@ -1357,111 +1357,29 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, /// \brief Cast member's object to its own class if necessary. bool -Sema::PerformObjectMemberConversion(Expr *&From, - NestedNameSpecifier *Qualifier, - NamedDecl *Member) { - CXXRecordDecl *RD = dyn_cast(Member->getDeclContext()); - if (!RD) - return false; - - QualType DestRecordType; - QualType DestType; - QualType FromRecordType; - QualType FromType = From->getType(); - bool PointerConversions = false; - if (isa(Member)) { - DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD)); - - if (FromType->getAs()) { - DestType = Context.getPointerType(DestRecordType); - FromRecordType = FromType->getPointeeType(); - PointerConversions = true; - } else { - DestType = DestRecordType; - FromRecordType = FromType; - } - } else if (CXXMethodDecl *Method = dyn_cast(Member)) { - if (Method->isStatic()) - return false; - - DestType = Method->getThisType(Context); - DestRecordType = DestType->getPointeeType(); - - if (FromType->getAs()) { - FromRecordType = FromType->getPointeeType(); - PointerConversions = true; - } else { - FromRecordType = FromType; - DestType = DestRecordType; - } - } else { - // No conversion necessary. - return false; - } - - if (DestType->isDependentType() || FromType->isDependentType()) - return false; - - // If the unqualified types are the same, no conversion is necessary. - if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) - return false; - - // C++ [class.member.lookup]p8: - // [...] Ambiguities can often be resolved by qualifying a name with its - // class name. - // - // If the member was a qualified name and the qualified referred to a - // specific base subobject type, we'll cast to that intermediate type - // first and then to the object in which the member is declared. That allows - // one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as: - // - // class Base { public: int x; }; - // class Derived1 : public Base { }; - // class Derived2 : public Base { }; - // class VeryDerived : public Derived1, public Derived2 { void f(); }; - // - // void VeryDerived::f() { - // 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()) { - IntermediateRecordType = QualType(IntermediateRecord, 0); - IntermediateType = IntermediateRecordType; - if (PointerConversions) - IntermediateType = Context.getPointerType(IntermediateType); +Sema::PerformObjectMemberConversion(Expr *&From, NamedDecl *Member) { + if (FieldDecl *FD = dyn_cast(Member)) + if (CXXRecordDecl *RD = + dyn_cast(FD->getDeclContext())) { + QualType DestType = + Context.getCanonicalType(Context.getTypeDeclType(RD)); + if (DestType->isDependentType() || From->getType()->isDependentType()) + return false; + QualType FromRecordType = From->getType(); + QualType DestRecordType = DestType; + if (FromRecordType->getAs()) { + DestType = Context.getPointerType(DestType); + FromRecordType = FromRecordType->getPointeeType(); + } + if (!Context.hasSameUnqualifiedType(FromRecordType, DestRecordType) && + CheckDerivedToBaseConversion(FromRecordType, + DestRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange())) + return true; + ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/true); } - } - - 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; - - ImpCastExprToType(From, IntermediateType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/!PointerConversions); - ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/!PointerConversions); - return false; - } - - if (CheckDerivedToBaseConversion(FromRecordType, - DestRecordType, - From->getSourceRange().getBegin(), - From->getSourceRange())) - return true; - - ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, - /*isLvalue=*/true); return false; } @@ -2748,7 +2666,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, } MarkDeclarationReferenced(MemberLoc, FD); - if (PerformObjectMemberConversion(BaseExpr, Qualifier, FD)) + if (PerformObjectMemberConversion(BaseExpr, FD)) return ExprError(); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, FD, MemberLoc, MemberType)); @@ -6733,7 +6651,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, Res = BuildAnonymousStructUnionMemberReference( OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs(); } else { - PerformObjectMemberConversion(Res, /*Qualifier=*/0, MemberDecl); + PerformObjectMemberConversion(Res, 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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 309da292e1..5f4601961c 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2881,7 +2881,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, CXXMethodDecl *Method) { - if (PerformObjectArgumentInitialization(Exp, /*Qualifier=*/0, Method)) + if (PerformObjectArgumentInitialization(Exp, Method)) assert(0 && "Calling BuildCXXMemberCallExpr with invalid call?"); MemberExpr *ME = diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index bf9f73c961..0f8107ac5e 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3365,8 +3365,7 @@ InitializationSequence::Perform(Sema &S, // FIXME: Should we move this initialization into a separate // 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)) + if (S.PerformObjectArgumentInitialization(CurInitExpr, Conversion)) return S.ExprError(); // Do a little dance to make sure that CurInit has the proper diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 5ff4adcc0d..ed0d137d80 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2304,9 +2304,7 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType, /// the implicit object parameter for the given Method with the given /// expression. bool -Sema::PerformObjectArgumentInitialization(Expr *&From, - NestedNameSpecifier *Qualifier, - CXXMethodDecl *Method) { +Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) { QualType FromRecordType, DestType; QualType ImplicitParamRecordType = Method->getThisType(Context)->getAs()->getPointeeType(); @@ -2329,12 +2327,15 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, diag::err_implicit_object_parameter_init) << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); - if (ICS.Standard.Second == ICK_Derived_To_Base) - return PerformObjectMemberConversion(From, Qualifier, Method); + if (ICS.Standard.Second == ICK_Derived_To_Base && + CheckDerivedToBaseConversion(FromRecordType, + ImplicitParamRecordType, + From->getSourceRange().getBegin(), + From->getSourceRange())) + return true; - if (!Context.hasSameType(From->getType(), DestType)) - ImpCastExprToType(From, DestType, CastExpr::CK_NoOp, - /*isLvalue=*/!From->getType()->getAs()); + ImpCastExprToType(From, DestType, CastExpr::CK_DerivedToBase, + /*isLvalue=*/true); return false; } @@ -5544,7 +5545,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, if (CXXMethodDecl *Method = dyn_cast(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess()); - if (PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, Method)) + if (PerformObjectArgumentInitialization(Input, Method)) return ExprError(); } else { // Convert the arguments. @@ -5737,8 +5738,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Arg1.isInvalid()) return ExprError(); - if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, - Method)) + if (PerformObjectArgumentInitialization(Args[0], Method)) return ExprError(); Args[1] = RHS = Arg1.takeAs(); @@ -5904,8 +5904,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Convert the arguments. CXXMethodDecl *Method = cast(FnDecl); - if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, - Method)) + if (PerformObjectArgumentInitialization(Args[0], Method)) return ExprError(); // Convert the arguments. @@ -6010,15 +6009,12 @@ 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 @@ -6117,7 +6113,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, Qualifier, Method)) + PerformObjectArgumentInitialization(ObjectArg, Method)) return ExprError(); MemExpr->setBase(ObjectArg); @@ -6337,8 +6333,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, bool IsError = false; // Initialize the implicit object parameter. - IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, - Method); + IsError |= PerformObjectArgumentInitialization(Object, Method); TheCall->setArg(0, Object); @@ -6463,7 +6458,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { // Convert the object parameter. CXXMethodDecl *Method = cast(Best->Function); - if (PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, Method)) + if (PerformObjectArgumentInitialization(Base, Method)) return ExprError(); // No concerns about early exits now. diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 24ea62cde1..2f3c482321 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -969,7 +969,7 @@ public: assert(!Qualifier && "Can't have an unnamed field with a qualifier!"); Expr *BaseExpr = Base.takeAs(); - if (getSema().PerformObjectMemberConversion(BaseExpr, Qualifier, Member)) + if (getSema().PerformObjectMemberConversion(BaseExpr, Member)) return getSema().ExprError(); MemberExpr *ME = diff --git a/test/CXX/class.derived/class.member.lookup/p8.cpp b/test/CXX/class.derived/class.member.lookup/p8.cpp deleted file mode 100644 index 4d4acc3460..0000000000 --- a/test/CXX/class.derived/class.member.lookup/p8.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s - -// FIXME: Access control checks - -namespace PR5820 { - // also - struct Base { - void Foo(); - int Member; - }; - - struct D1 : public Base {}; - struct D2 : public Base {}; - - struct Derived : public D1, public D2 { - void Inner(); - }; - - void Test() { - Derived d; - d.D1::Foo(); - d.D1::Member = 17; - } - - void Derived::Inner() { - D1::Foo(); - D1::Member = 42; - this->D1::Foo(); - this->D1::Member = 42; - } -} - -template -struct BaseT { - void Foo(); // expected-note{{found by ambiguous name lookup}} - int Member; -}; - -template struct Derived1T : BaseT { }; -template struct Derived2T : BaseT { }; - -template -struct DerivedT : public Derived1T, public Derived2T { - void Inner(); -}; - -template -void DerivedT::Inner() { - Derived1T::Foo(); - Derived2T::Member = 42; - this->Derived1T::Foo(); - this->Derived2T::Member = 42; - this->Foo(); // expected-error{{non-static member 'Foo' found in multiple base-class subobjects of type 'BaseT'}} -} - -template -void Test(DerivedT d) { - d.template Derived1T::Foo(); - d.template Derived2T::Member = 17; - d.Inner(); // expected-note{{in instantiation}} -} - -template void Test(DerivedT);