diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp | 346 |
1 files changed, 191 insertions, 155 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp index 26867c2..26b88a2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprMember.cpp @@ -56,7 +56,7 @@ enum IMAKind { /// The reference may be an implicit instance member access. IMA_Mixed, - /// The reference may be to an instance member, but it is invalid if + /// The reference may be to an instance member, but it might be invalid if /// so, because the context is not an instance method. IMA_Mixed_StaticContext, @@ -74,6 +74,11 @@ enum IMAKind { /// context is not an instance method. IMA_Unresolved_StaticContext, + // The reference refers to a field which is not a member of the containing + // class, which is allowed because we're in C++11 mode and the context is + // unevaluated. + IMA_Field_Uneval_Context, + /// All possible referrents are instance members and the current /// context is not an instance method. IMA_Error_StaticContext, @@ -86,7 +91,7 @@ enum IMAKind { /// The given lookup names class member(s) and is not being used for /// an address-of-member expression. Classify the type of access /// according to whether it's possible that this reference names an -/// instance member. This is best-effort; it is okay to +/// instance member. This is best-effort in dependent contexts; it is okay to /// conservatively answer "yes", in which case some errors will simply /// not be caught until template-instantiation. static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, @@ -112,14 +117,14 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // Collect all the declaring classes of instance members we find. bool hasNonInstance = false; - bool hasField = false; + bool isField = false; llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes; for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *D = *I; if (D->isCXXInstanceMember()) { if (dyn_cast<FieldDecl>(D)) - hasField = true; + isField = true; CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); Classes.insert(R->getCanonicalDecl()); @@ -133,27 +138,28 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, if (Classes.empty()) return IMA_Static; + bool IsCXX11UnevaluatedField = false; + if (SemaRef.getLangOpts().CPlusPlus0x && isField) { + // C++11 [expr.prim.general]p12: + // An id-expression that denotes a non-static data member or non-static + // member function of a class can only be used: + // (...) + // - if that id-expression denotes a non-static data member and it + // appears in an unevaluated operand. + const Sema::ExpressionEvaluationContextRecord& record + = SemaRef.ExprEvalContexts.back(); + if (record.Context == Sema::Unevaluated) + IsCXX11UnevaluatedField = true; + } + // If the current context is not an instance method, it can't be // an implicit member reference. if (isStaticContext) { if (hasNonInstance) - return IMA_Mixed_StaticContext; - - if (SemaRef.getLangOptions().CPlusPlus0x && hasField) { - // C++0x [expr.prim.general]p10: - // An id-expression that denotes a non-static data member or non-static - // member function of a class can only be used: - // (...) - // - if that id-expression denotes a non-static data member and it - // appears in an unevaluated operand. - const Sema::ExpressionEvaluationContextRecord& record - = SemaRef.ExprEvalContexts.back(); - bool isUnevaluatedExpression = (record.Context == Sema::Unevaluated); - if (isUnevaluatedExpression) - return IMA_Mixed_StaticContext; - } - - return IMA_Error_StaticContext; + return IMA_Mixed_StaticContext; + + return IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context + : IMA_Error_StaticContext; } CXXRecordDecl *contextClass; @@ -169,76 +175,93 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // ...if C is not X or a base class of X, the class member access expression // is ill-formed. if (R.getNamingClass() && - contextClass != R.getNamingClass()->getCanonicalDecl() && + contextClass->getCanonicalDecl() != + R.getNamingClass()->getCanonicalDecl() && contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) - return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + return hasNonInstance ? IMA_Mixed_Unrelated : + IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : + IMA_Error_Unrelated; // If we can prove that the current context is unrelated to all the // declaring classes, it can't be an implicit member reference (in // which case it's an error if any of those members are selected). if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) - return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + return hasNonInstance ? IMA_Mixed_Unrelated : + IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : + IMA_Error_Unrelated; return (hasNonInstance ? IMA_Mixed : IMA_Instance); } /// Diagnose a reference to a field with no object available. -static void DiagnoseInstanceReference(Sema &SemaRef, +static void diagnoseInstanceReference(Sema &SemaRef, const CXXScopeSpec &SS, - NamedDecl *rep, + NamedDecl *Rep, const DeclarationNameInfo &nameInfo) { SourceLocation Loc = nameInfo.getLoc(); SourceRange Range(Loc); if (SS.isSet()) Range.setBegin(SS.getRange().getBegin()); - - if (isa<FieldDecl>(rep) || isa<IndirectFieldDecl>(rep)) { - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) { - if (MD->isStatic()) { - // "invalid use of member 'x' in static member function" - SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method) + + DeclContext *FunctionLevelDC = SemaRef.getFunctionLevelDeclContext(); + CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FunctionLevelDC); + CXXRecordDecl *ContextClass = Method ? Method->getParent() : 0; + CXXRecordDecl *RepClass = dyn_cast<CXXRecordDecl>(Rep->getDeclContext()); + + bool InStaticMethod = Method && Method->isStatic(); + bool IsField = isa<FieldDecl>(Rep) || isa<IndirectFieldDecl>(Rep); + + if (IsField && InStaticMethod) + // "invalid use of member 'x' in static member function" + SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method) << Range << nameInfo.getName(); - return; - } - } - + else if (ContextClass && RepClass && SS.isEmpty() && !InStaticMethod && + !RepClass->Equals(ContextClass) && RepClass->Encloses(ContextClass)) + // Unqualified lookup in a non-static member function found a member of an + // enclosing class. + SemaRef.Diag(Loc, diag::err_nested_non_static_member_use) + << IsField << RepClass << nameInfo.getName() << ContextClass << Range; + else if (IsField) SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use) - << nameInfo.getName() << Range; - return; - } - - SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range; + << nameInfo.getName() << Range; + else + SemaRef.Diag(Loc, diag::err_member_call_without_object) + << Range; } /// Builds an expression which might be an implicit member expression. ExprResult Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs) { switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) { case IMA_Instance: - return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, true); case IMA_Mixed: case IMA_Mixed_Unrelated: case IMA_Unresolved: - return BuildImplicitMemberExpr(SS, R, TemplateArgs, false); + return BuildImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, false); + case IMA_Field_Uneval_Context: + Diag(R.getNameLoc(), diag::warn_cxx98_compat_non_static_member_use) + << R.getLookupNameInfo().getName(); + // Fall through. case IMA_Static: case IMA_Mixed_StaticContext: case IMA_Unresolved_StaticContext: - if (TemplateArgs) - return BuildTemplateIdExpr(SS, R, false, *TemplateArgs); + if (TemplateArgs || TemplateKWLoc.isValid()) + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, false, TemplateArgs); return BuildDeclarationNameExpr(SS, R, false); case IMA_Error_StaticContext: case IMA_Error_Unrelated: - DiagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), + diagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), R.getLookupNameInfo()); return ExprError(); } llvm_unreachable("unexpected instance member access kind"); - return ExprError(); } /// Check an ext-vector component access expression. @@ -403,6 +426,7 @@ ExprResult Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { @@ -417,7 +441,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, // allows this, while still reporting an error if T is a struct pointer. if (!IsArrow) { const PointerType *PT = BaseType->getAs<PointerType>(); - if (PT && (!getLangOptions().ObjC1 || + if (PT && (!getLangOpts().ObjC1 || PT->getPointeeType()->isRecordType())) { assert(BaseExpr && "cannot happen with implicit member accesses"); Diag(NameInfo.getLoc(), diag::err_typecheck_member_reference_struct_union) @@ -435,6 +459,7 @@ Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType, IsArrow, OpLoc, SS.getWithLocInContext(Context), + TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs)); } @@ -451,7 +476,7 @@ static void DiagnoseQualifiedMemberReference(Sema &SemaRef, // If this is an implicit member access, use a different set of // diagnostics. if (!BaseExpr) - return DiagnoseInstanceReference(SemaRef, SS, rep, nameInfo); + return diagnoseInstanceReference(SemaRef, SS, rep, nameInfo); SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated) << SS.getRange() << rep << BaseType; @@ -509,6 +534,20 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, return true; } +namespace { + +// Callback to only accept typo corrections that are either a ValueDecl or a +// FunctionTemplateDecl. +class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback { + public: + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + NamedDecl *ND = candidate.getCorrectionDecl(); + return ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)); + } +}; + +} + static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, SourceRange BaseRange, const RecordType *RTy, @@ -559,17 +598,16 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // We didn't find anything with the given name, so try to correct // for typos. DeclarationName Name = R.getLookupName(); + RecordMemberExprValidatorCCC Validator; TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), NULL, - &SS, DC, false, - Sema::CTC_MemberLookup); - NamedDecl *ND = Corrected.getCorrectionDecl(); + &SS, Validator, DC); R.clear(); - if (ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) { + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { std::string CorrectedStr( - Corrected.getAsString(SemaRef.getLangOptions())); + Corrected.getAsString(SemaRef.getLangOpts())); std::string CorrectedQuotedStr( - Corrected.getQuoted(SemaRef.getLangOptions())); + Corrected.getQuoted(SemaRef.getLangOpts())); R.setLookupName(Corrected.getCorrection()); R.addDecl(ND); SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) @@ -586,6 +624,7 @@ ExprResult Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { @@ -593,7 +632,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, (SS.isSet() && isDependentScopeSpecifier(SS))) return ActOnDependentMemberExpr(Base, BaseType, IsArrow, OpLoc, - SS, FirstQualifierInScope, + SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs); LookupResult R(*this, NameInfo, LookupMemberName); @@ -631,8 +670,8 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, } return BuildMemberReferenceExpr(Base, BaseType, - OpLoc, IsArrow, SS, FirstQualifierInScope, - R, TemplateArgs); + OpLoc, IsArrow, SS, TemplateKWLoc, + FirstQualifierInScope, R, TemplateArgs); } static ExprResult @@ -697,7 +736,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, // We've found a member of an anonymous struct/union that is // inside a non-anonymous struct/union, so in a well-formed // program our base object expression is "this". - QualType ThisTy = getAndCaptureCurrentThisType(); + QualType ThisTy = getCurrentThisType(); if (ThisTy.isNull()) { Diag(loc, diag::err_invalid_member_use_in_static_method) << indirectField->getDeclName(); @@ -705,6 +744,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, } // Our base object expression is "this". + CheckCXXThisCapture(loc); baseObjectExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true); baseObjectIsPointer = true; @@ -754,22 +794,30 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, } /// \brief Build a MemberExpr AST node. -static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, - const CXXScopeSpec &SS, ValueDecl *Member, +static MemberExpr *BuildMemberExpr(Sema &SemaRef, + ASTContext &C, Expr *Base, bool isArrow, + const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + ValueDecl *Member, DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = 0) { - return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), - Member, FoundDecl, MemberNameInfo, - TemplateArgs, Ty, VK, OK); + assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue"); + MemberExpr *E = + MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), + TemplateKWLoc, Member, FoundDecl, MemberNameInfo, + TemplateArgs, Ty, VK, OK); + SemaRef.MarkMemberReferenced(E); + return E; } ExprResult Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation OpLoc, bool IsArrow, const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, @@ -777,7 +825,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, QualType BaseType = BaseExprType; if (IsArrow) { assert(BaseType->isPointerType()); - BaseType = BaseType->getAs<PointerType>()->getPointeeType(); + BaseType = BaseType->castAs<PointerType>()->getPointeeType(); } R.setBaseObjectType(BaseType); @@ -813,7 +861,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, !SuppressQualifierCheck && CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R)) return ExprError(); - + // Construct an unresolved result if we in fact got an unresolved // result. if (R.isOverloadedResult() || R.isUnresolvableResult()) { @@ -826,7 +874,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, BaseExpr, BaseExprType, IsArrow, OpLoc, SS.getWithLocInContext(Context), - MemberNameInfo, + TemplateKWLoc, MemberNameInfo, TemplateArgs, R.begin(), R.end()); return Owned(MemExpr); @@ -853,6 +901,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); + CheckCXXThisCapture(Loc); BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true); } @@ -870,15 +919,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return ExprError(); } - // Perform a property load on the base regardless of whether we - // actually need it for the declaration. - if (BaseExpr->getObjectKind() == OK_ObjCProperty) { - ExprResult Result = ConvertPropertyForRValue(BaseExpr); - if (Result.isInvalid()) - return ExprError(); - BaseExpr = Result.take(); - } - if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, SS, FD, FoundDecl, MemberNameInfo); @@ -890,9 +930,8 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, BaseExpr, OpLoc); if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, Var); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - Var, FoundDecl, MemberNameInfo, + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, Var, FoundDecl, MemberNameInfo, Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary)); } @@ -908,17 +947,16 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, type = MemberFn->getType(); } - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - MemberFn, FoundDecl, MemberNameInfo, - type, valueKind, OK_Ordinary)); + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, MemberFn, FoundDecl, + MemberNameInfo, type, valueKind, + OK_Ordinary)); } assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { - MarkDeclarationReferenced(MemberLoc, MemberDecl); - return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, - Enum, FoundDecl, MemberNameInfo, + return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS, + TemplateKWLoc, Enum, FoundDecl, MemberNameInfo, Enum->getType(), VK_RValue, OK_Ordinary)); } @@ -979,6 +1017,15 @@ static bool isPointerToRecordType(QualType T) { return false; } +/// Perform conversions on the LHS of a member access expression. +ExprResult +Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) { + if (IsArrow && !Base->getType()->isFunctionType()) + return DefaultFunctionArrayLvalueConversion(Base); + + return CheckPlaceholderExpr(Base); +} + /// Look up the given member of the given non-type-dependent /// expression. This can return in one of two ways: /// * If it returns a sentinel null-but-valid result, the caller will @@ -997,16 +1044,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, assert(BaseExpr.get() && "no base expression"); // Perform default conversions. - BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); + BaseExpr = PerformMemberExprBaseConversion(BaseExpr.take(), IsArrow); if (BaseExpr.isInvalid()) return ExprError(); - if (IsArrow) { - BaseExpr = DefaultLvalueConversion(BaseExpr.take()); - if (BaseExpr.isInvalid()) - return ExprError(); - } - QualType BaseType = BaseExpr.get()->getType(); assert(!BaseType->isDependentType()); @@ -1034,7 +1075,7 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "."); IsArrow = false; - } else if (BaseType == Context.BoundMemberTy) { + } else if (BaseType->isFunctionType()) { goto fail; } else { Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) @@ -1071,15 +1112,17 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // - an interface ObjCInterfaceDecl *IDecl = OTy->getInterface(); if (!IDecl) { - if (getLangOptions().ObjCAutoRefCount && + if (getLangOpts().ObjCAutoRefCount && (OTy->isObjCId() || OTy->isObjCClass())) goto fail; // There's an implicit 'isa' ivar on all objects. // But we only actually find it this way on objects of type 'id', - // apparently. - if (OTy->isObjCId() && Member->isStr("isa")) + // apparently.ghjg + if (OTy->isObjCId() && Member->isStr("isa")) { + Diag(MemberLoc, diag::warn_objc_isa_use); return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc, Context.getObjCClassType())); + } if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, @@ -1087,17 +1130,22 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, goto fail; } - ObjCInterfaceDecl *ClassDeclared; + if (RequireCompleteType(OpLoc, BaseType, + PDiag(diag::err_typecheck_incomplete_tag) + << BaseExpr.get()->getSourceRange())) + return ExprError(); + + ObjCInterfaceDecl *ClassDeclared = 0; ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); if (!IV) { // Attempt to correct for typos in ivar names. - LookupResult Res(*this, R.getLookupName(), R.getNameLoc(), - LookupMemberName); - TypoCorrection Corrected = CorrectTypo( - R.getLookupNameInfo(), LookupMemberName, NULL, NULL, IDecl, false, - IsArrow ? CTC_ObjCIvarLookup : CTC_ObjCPropertyLookup); - if ((IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>())) { + DeclFilterCCC<ObjCIvarDecl> Validator; + Validator.IsObjCIvarLookup = IsArrow; + if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), + LookupMemberName, NULL, NULL, + Validator, IDecl)) { + IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>(); Diag(R.getNameLoc(), diag::err_typecheck_member_reference_ivar_suggest) << IDecl->getDeclName() << MemberName << IV->getDeclName() @@ -1105,6 +1153,13 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, IV->getNameAsString()); Diag(IV->getLocation(), diag::note_previous_decl) << IV->getDeclName(); + + // Figure out the class that declares the ivar. + assert(!ClassDeclared); + Decl *D = cast<Decl>(IV->getDeclContext()); + if (ObjCCategoryDecl *CAT = dyn_cast<ObjCCategoryDecl>(D)) + D = CAT->getClassInterface(); + ClassDeclared = cast<ObjCInterfaceDecl>(D); } else { if (IsArrow && IDecl->FindPropertyDeclaration(Member)) { Diag(MemberLoc, @@ -1113,8 +1168,6 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, << FixItHint::CreateReplacement(OpLoc, "."); return ExprError(); } - Res.clear(); - Res.setLookupName(Member); Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) << IDecl->getDeclName() << MemberName @@ -1122,6 +1175,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, return ExprError(); } } + + assert(ClassDeclared); // If the decl being referenced had an error, return an error for this // sub-expr without emitting another error, in order to avoid cascading @@ -1151,18 +1206,19 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl)) ClassOfMethodDecl = CatImplClass->getClassInterface(); } - - if (IV->getAccessControl() == ObjCIvarDecl::Private) { - if (ClassDeclared != IDecl || - ClassOfMethodDecl != ClassDeclared) - Diag(MemberLoc, diag::error_private_ivar_access) + if (!getLangOpts().DebuggerSupport) { + if (IV->getAccessControl() == ObjCIvarDecl::Private) { + if (!declaresSameEntity(ClassDeclared, IDecl) || + !declaresSameEntity(ClassOfMethodDecl, ClassDeclared)) + Diag(MemberLoc, diag::error_private_ivar_access) + << IV->getDeclName(); + } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) + // @protected + Diag(MemberLoc, diag::error_protected_ivar_access) << IV->getDeclName(); - } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) - // @protected - Diag(MemberLoc, diag::error_protected_ivar_access) - << IV->getDeclName(); + } } - if (getLangOptions().ObjCAutoRefCount) { + if (getLangOpts().ObjCAutoRefCount) { Expr *BaseExp = BaseExpr.get()->IgnoreParenImpCasts(); if (UnaryOperator *UO = dyn_cast<UnaryOperator>(BaseExp)) if (UO->getOpcode() == UO_Deref) @@ -1209,11 +1265,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); - QualType T = PD->getType(); - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) - T = getMessageSendResultType(BaseType, Getter, false, false); - - return Owned(new (Context) ObjCPropertyRefExpr(PD, T, + return Owned(new (Context) ObjCPropertyRefExpr(PD, + Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, MemberLoc, @@ -1231,16 +1284,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0, SetterSel, Context)) SMD = dyn_cast<ObjCMethodDecl>(SDecl); - QualType PType = getMessageSendResultType(BaseType, OMD, false, - false); - ExprValueKind VK = VK_LValue; - if (!getLangOptions().CPlusPlus && PType.isCForbiddenLValueType()) - VK = VK_RValue; - ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); - - return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType, - VK, OK, + return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr.take())); } } @@ -1295,23 +1342,9 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, return ExprError(); if (Getter || Setter) { - QualType PType; - - ExprValueKind VK = VK_LValue; - if (Getter) { - PType = getMessageSendResultType(QualType(OT, 0), Getter, true, - false); - if (!getLangOptions().CPlusPlus && PType.isCForbiddenLValueType()) - VK = VK_RValue; - } else { - // Get the expression type from Setter's incoming parameter. - PType = (*(Setter->param_end() -1))->getType(); - } - ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); - - // FIXME: we must check that the setter has property type. return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, - PType, VK, OK, + Context.PseudoObjectTy, + VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr.take())); } @@ -1384,7 +1417,7 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (tryToRecoverWithCall(BaseExpr, PDiag(diag::err_member_reference_needs_call), /*complain*/ false, - IsArrow ? &isRecordType : &isPointerToRecordType)) { + IsArrow ? &isPointerToRecordType : &isRecordType)) { if (BaseExpr.isInvalid()) return ExprError(); BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); @@ -1415,6 +1448,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, UnqualifiedId &Id, Decl *ObjCImpDecl, bool HasTrailingLParen) { @@ -1422,7 +1456,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, return ExprError(); // Warn about the explicit constructor calls Microsoft extension. - if (getLangOptions().MicrosoftExt && + if (getLangOpts().MicrosoftExt && Id.getKind() == UnqualifiedId::IK_ConstructorName) Diag(Id.getSourceRange().getBegin(), diag::ext_ms_explicit_constructor_call); @@ -1451,7 +1485,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, isDependentScopeSpecifier(SS)) { Result = ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, - SS, FirstQualifierInScope, + SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs); } else { LookupResult R(*this, NameInfo, LookupMemberName); @@ -1480,8 +1514,8 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, } Result = BuildMemberReferenceExpr(Base, Base->getType(), - OpLoc, IsArrow, SS, FirstQualifierInScope, - R, TemplateArgs); + OpLoc, IsArrow, SS, TemplateKWLoc, + FirstQualifierInScope, R, TemplateArgs); } return move(Result); @@ -1536,13 +1570,13 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, MemberType = S.Context.getQualifiedType(MemberType, Combined); } - S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field); ExprResult Base = S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), FoundDecl, Field); if (Base.isInvalid()) return ExprError(); - return S.Owned(BuildMemberExpr(S.Context, Base.take(), IsArrow, SS, + return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, SS, + /*TemplateKWLoc=*/SourceLocation(), Field, FoundDecl, MemberNameInfo, MemberType, VK, OK)); } @@ -1553,6 +1587,7 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, /// is from an appropriate type. ExprResult Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, bool IsKnownInstance) { @@ -1569,7 +1604,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, // If this is known to be an instance access, go ahead and build an // implicit 'this' expression now. // 'this' expression now. - QualType ThisTy = getAndCaptureCurrentThisType(); + QualType ThisTy = getCurrentThisType(); assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'"); Expr *baseExpr = 0; // null signifies implicit access @@ -1577,13 +1612,14 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation Loc = R.getNameLoc(); if (SS.getRange().isValid()) Loc = SS.getRange().getBegin(); + CheckCXXThisCapture(Loc); baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true); } return BuildMemberReferenceExpr(baseExpr, ThisTy, /*OpLoc*/ SourceLocation(), /*IsArrow*/ true, - SS, + SS, TemplateKWLoc, /*FirstQualifierInScope*/ 0, R, TemplateArgs); } |