From dd5132ce2569a1ef901c92772eb8581aa1705f25 Mon Sep 17 00:00:00 2001 From: Roman Divacky Date: Sat, 6 Mar 2010 09:23:02 +0000 Subject: Update clang to r97873. --- lib/Sema/SemaExpr.cpp | 134 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 108 insertions(+), 26 deletions(-) (limited to 'lib/Sema/SemaExpr.cpp') diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d9464ad8c009..10001c356d1c 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, *FI); + PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI); // FIXME: Might this end up being a qualified name? Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); @@ -1357,29 +1357,111 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, /// \brief Cast member's object to its own class if necessary. bool -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); +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); + } + } + + 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; } @@ -1609,7 +1691,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, return ExprError(); } - if (VD->getType()->isArrayType()) { + if (VD->getType()->isArrayType() && !VD->hasAttr()) { Diag(Loc, diag::err_ref_array_type); Diag(D->getLocation(), diag::note_declared_at); return ExprError(); @@ -2666,7 +2748,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, } MarkDeclarationReferenced(MemberLoc, FD); - if (PerformObjectMemberConversion(BaseExpr, FD)) + if (PerformObjectMemberConversion(BaseExpr, Qualifier, FD)) return ExprError(); return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, FD, MemberLoc, MemberType)); @@ -6651,7 +6733,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, Res = BuildAnonymousStructUnionMemberReference( OC.LocEnd, MemberDecl, Res, OC.LocEnd).takeAs(); } else { - PerformObjectMemberConversion(Res, MemberDecl); + PerformObjectMemberConversion(Res, /*Qualifier=*/0, MemberDecl); // MemberDecl->getType() doesn't get the right qualifiers, but it // doesn't matter here. Res = new (Context) MemberExpr(Res, false, MemberDecl, OC.LocEnd, -- cgit v1.2.3