diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 56 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 45 | ||||
-rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 111 | ||||
-rw-r--r-- | clang/lib/Sema/SemaPseudoObject.cpp | 20 |
4 files changed, 165 insertions, 67 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index db594bbd21d..30a1b95d424 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -2828,6 +2828,9 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, "Expected to find the method through lookup as well"); // ImpMethodDecl may be null as in a @dynamic property. if (ImpMethodDecl) { + // Skip property accessor function stubs. + if (ImpMethodDecl->isSynthesizedAccessorStub()) + continue; if (!WarnCategoryMethodImpl) WarnConflictingTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl)); @@ -2854,6 +2857,9 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, "Expected to find the method through lookup as well"); // ImpMethodDecl may be null as in a @dynamic property. if (ImpMethodDecl) { + // Skip property accessor function stubs. + if (ImpMethodDecl->isSynthesizedAccessorStub()) + continue; if (!WarnCategoryMethodImpl) WarnConflictingTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl)); @@ -3903,6 +3909,25 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, || isa<ObjCProtocolDecl>(ClassDecl); bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl); + // Make synthesized accessor stub functions visible. + // ActOnPropertyImplDecl() creates them as not visible in case + // they are overridden by an explicit method that is encountered + // later. + if (auto *OID = dyn_cast<ObjCImplementationDecl>(CurContext)) { + for (auto PropImpl : OID->property_impls()) { + if (auto *Getter = PropImpl->getGetterMethodDecl()) + if (Getter->isSynthesizedAccessorStub()) { + OID->makeDeclVisibleInContext(Getter); + OID->addDecl(Getter); + } + if (auto *Setter = PropImpl->getSetterMethodDecl()) + if (Setter->isSynthesizedAccessorStub()) { + OID->makeDeclVisibleInContext(Setter); + OID->addDecl(Setter); + } + } + } + // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap; llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap; @@ -4001,8 +4026,8 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, continue; for (const auto *Ext : IDecl->visible_extensions()) { - if (ObjCMethodDecl *GetterMethod - = Ext->getInstanceMethod(Property->getGetterName())) + if (ObjCMethodDecl *GetterMethod = + Ext->getInstanceMethod(Property->getGetterName())) GetterMethod->setPropertyAccessor(true); if (!Property->isReadOnly()) if (ObjCMethodDecl *SetterMethod @@ -4551,6 +4576,7 @@ Decl *Sema::ActOnMethodDeclaration( Diag(MethodLoc, diag::err_missing_method_context); return nullptr; } + Decl *ClassDecl = cast<ObjCContainerDecl>(CurContext); QualType resultDeclType; @@ -4574,7 +4600,7 @@ Decl *Sema::ActOnMethodDeclaration( ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create( Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, CurContext, MethodType == tok::minus, isVariadic, - /*isPropertyAccessor=*/false, + /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false, /*isImplicitlyDeclared=*/false, /*isDefined=*/false, MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional : ObjCMethodDecl::Required, @@ -4666,6 +4692,27 @@ Decl *Sema::ActOnMethodDeclaration( ImpDecl->addClassMethod(ObjCMethod); } + // If this method overrides a previous @synthesize declaration, + // register it with the property. Linear search through all + // properties here, because the autosynthesized stub hasn't been + // made visible yet, so it can be overriden by a later + // user-specified implementation. + for (ObjCPropertyImplDecl *PropertyImpl : ImpDecl->property_impls()) { + if (auto *Setter = PropertyImpl->getSetterMethodDecl()) + if (Setter->getSelector() == Sel && + Setter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) { + assert(Setter->isSynthesizedAccessorStub() && "autosynth stub expected"); + PropertyImpl->setSetterMethodDecl(ObjCMethod); + } + if (auto *Getter = PropertyImpl->getGetterMethodDecl()) + if (Getter->getSelector() == Sel && + Getter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) { + assert(Getter->isSynthesizedAccessorStub() && "autosynth stub expected"); + PropertyImpl->setGetterMethodDecl(ObjCMethod); + break; + } + } + // Merge information from the @interface declaration into the // @implementation. if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) { @@ -5063,6 +5110,9 @@ void Sema::DiagnoseUnusedBackingIvarInAccessor(Scope *S, if (!IV) continue; + if (CurMethod->isSynthesizedAccessorStub()) + continue; + UnusedBackingIvarChecker Checker(*this, CurMethod, IV); Checker.TraverseStmt(CurMethod->getBody()); if (Checker.AccessedIvar) diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index e18621e42a6..207812c8848 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -288,6 +288,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, S.NSNumberPointer, ReturnTInfo, S.NSNumberDecl, /*isInstance=*/false, /*isVariadic=*/false, /*isPropertyAccessor=*/false, + /*isSynthesizedAccessorStub=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, /*HasRelatedResultType=*/false); @@ -563,6 +564,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { NSStringPointer, ReturnTInfo, NSStringDecl, /*isInstance=*/false, /*isVariadic=*/false, /*isPropertyAccessor=*/false, + /*isSynthesizedAccessorStub=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, /*HasRelatedResultType=*/false); @@ -671,20 +673,15 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { // Debugger needs to work even if NSValue hasn't been defined. TypeSourceInfo *ReturnTInfo = nullptr; ObjCMethodDecl *M = ObjCMethodDecl::Create( - Context, - SourceLocation(), - SourceLocation(), - ValueWithBytesObjCType, - NSValuePointer, - ReturnTInfo, - NSValueDecl, - /*isInstance=*/false, - /*isVariadic=*/false, - /*isPropertyAccessor=*/false, - /*isImplicitlyDeclared=*/true, - /*isDefined=*/false, - ObjCMethodDecl::Required, - /*HasRelatedResultType=*/false); + Context, SourceLocation(), SourceLocation(), ValueWithBytesObjCType, + NSValuePointer, ReturnTInfo, NSValueDecl, + /*isInstance=*/false, + /*isVariadic=*/false, + /*isPropertyAccessor=*/false, + /*isSynthesizedAccessorStub=*/false, + /*isImplicitlyDeclared=*/true, + /*isDefined=*/false, ObjCMethodDecl::Required, + /*HasRelatedResultType=*/false); SmallVector<ParmVarDecl *, 2> Params; @@ -815,7 +812,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo, Context.getTranslationUnitDecl(), false /*Instance*/, false /*isVariadic*/, - /*isPropertyAccessor=*/false, + /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, false); SmallVector<ParmVarDecl *, 2> Params; @@ -916,16 +913,14 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, NSAPI::NSDict_dictionaryWithObjectsForKeysCount); ObjCMethodDecl *Method = NSDictionaryDecl->lookupClassMethod(Sel); if (!Method && getLangOpts().DebuggerObjCLiteral) { - Method = ObjCMethodDecl::Create(Context, - SourceLocation(), SourceLocation(), Sel, - IdT, - nullptr /*TypeSourceInfo */, - Context.getTranslationUnitDecl(), - false /*Instance*/, false/*isVariadic*/, - /*isPropertyAccessor=*/false, - /*isImplicitlyDeclared=*/true, /*isDefined=*/false, - ObjCMethodDecl::Required, - false); + Method = ObjCMethodDecl::Create( + Context, SourceLocation(), SourceLocation(), Sel, IdT, + nullptr /*TypeSourceInfo */, Context.getTranslationUnitDecl(), + false /*Instance*/, false /*isVariadic*/, + /*isPropertyAccessor=*/false, + /*isSynthesizedAccessorStub=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, false); SmallVector<ParmVarDecl *, 3> Params; ParmVarDecl *objects = ParmVarDecl::Create(Context, Method, SourceLocation(), diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index ac810745d2f..427def1b94e 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -1037,6 +1037,31 @@ static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop, return false; } +/// Create a synthesized property accessor stub inside the \@implementation. +static ObjCMethodDecl * +RedeclarePropertyAccessor(ASTContext &Context, ObjCImplementationDecl *Impl, + ObjCMethodDecl *AccessorDecl, SourceLocation AtLoc, + SourceLocation PropertyLoc) { + ObjCMethodDecl *Decl = AccessorDecl; + ObjCMethodDecl *ImplDecl = ObjCMethodDecl::Create( + Context, AtLoc, PropertyLoc, Decl->getSelector(), Decl->getReturnType(), + Decl->getReturnTypeSourceInfo(), Impl, Decl->isInstanceMethod(), + Decl->isVariadic(), Decl->isPropertyAccessor(), /* isSynthesized*/ true, + Decl->isImplicit(), Decl->isDefined(), Decl->getImplementationControl(), + Decl->hasRelatedResultType()); + ImplDecl->getMethodFamily(); + if (Decl->hasAttrs()) + ImplDecl->setAttrs(Decl->getAttrs()); + ImplDecl->setSelfDecl(Decl->getSelfDecl()); + ImplDecl->setCmdDecl(Decl->getCmdDecl()); + SmallVector<SourceLocation, 1> SelLocs; + Decl->getSelectorLocs(SelLocs); + ImplDecl->setMethodParams(Context, Decl->parameters(), SelLocs); + ImplDecl->setLexicalDeclContext(Impl); + ImplDecl->setDefined(false); + return ImplDecl; +} + /// ActOnPropertyImplDecl - This routine performs semantic checks and /// builds the AST node for a property implementation declaration; declared /// as \@synthesize or \@dynamic. @@ -1404,6 +1429,18 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { getterMethod->createImplicitParams(Context, IDecl); + + // Redeclare the getter within the implementation as DeclContext. + if (Synthesize) { + // If the method hasn't been overridden, create a synthesized implementation. + ObjCMethodDecl *OMD = ClassImpDecl->getMethod( + getterMethod->getSelector(), getterMethod->isInstanceMethod()); + if (!OMD) + OMD = RedeclarePropertyAccessor(Context, IC, getterMethod, AtLoc, + PropertyLoc); + PIDecl->setGetterMethodDecl(OMD); + } + if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && Ivar->getType()->isRecordType()) { // For Objective-C++, need to synthesize the AST for the IVAR object to be @@ -1456,8 +1493,20 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, break; } } + if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { setterMethod->createImplicitParams(Context, IDecl); + + // Redeclare the setter within the implementation as DeclContext. + if (Synthesize) { + ObjCMethodDecl *OMD = ClassImpDecl->getMethod( + setterMethod->getSelector(), setterMethod->isInstanceMethod()); + if (!OMD) + OMD = RedeclarePropertyAccessor(Context, IC, setterMethod, + AtLoc, PropertyLoc); + PIDecl->setSetterMethodDecl(OMD); + } + if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && Ivar->getType()->isRecordType()) { // FIXME. Eventually we want to do this for Objective-C as well. @@ -1852,10 +1901,12 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, if (IMPDecl->FindPropertyImplDecl( Prop->getIdentifier(), Prop->getQueryKind())) continue; - if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { + ObjCMethodDecl *ImpMethod = IMPDecl->getInstanceMethod(Prop->getGetterName()); + if (ImpMethod && !ImpMethod->getBody()) { if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) continue; - if (IMPDecl->getInstanceMethod(Prop->getSetterName())) + ImpMethod = IMPDecl->getInstanceMethod(Prop->getSetterName()); + if (ImpMethod && !ImpMethod->getBody()) continue; } if (ObjCPropertyImplDecl *PID = @@ -2083,7 +2134,6 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) { for (const auto *propertyImpl : impDecl->property_impls()) { const auto *property = propertyImpl->getPropertyDecl(); - // Warn about null_resettable properties with synthesized setters, // because the setter won't properly handle nil. if (propertyImpl->getPropertyImplementation() @@ -2092,16 +2142,16 @@ void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) ObjCPropertyDecl::OBJC_PR_null_resettable) && property->getGetterMethodDecl() && property->getSetterMethodDecl()) { - auto *getterMethod = property->getGetterMethodDecl(); - auto *setterMethod = property->getSetterMethodDecl(); - if (!impDecl->getInstanceMethod(setterMethod->getSelector()) && - !impDecl->getInstanceMethod(getterMethod->getSelector())) { + auto *getterImpl = propertyImpl->getGetterMethodDecl(); + auto *setterImpl = propertyImpl->getSetterMethodDecl(); + if ((!getterImpl || getterImpl->isSynthesizedAccessorStub()) && + (!setterImpl || setterImpl->isSynthesizedAccessorStub())) { SourceLocation loc = propertyImpl->getLocation(); if (loc.isInvalid()) loc = impDecl->getBeginLoc(); Diag(loc, diag::warn_null_resettable_setter) - << setterMethod->getSelector() << property->getDeclName(); + << setterImpl->getSelector() << property->getDeclName(); } } } @@ -2138,6 +2188,10 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, SetterMethod = Property->isClassProperty() ? IMPDecl->getClassMethod(Property->getSetterName()) : IMPDecl->getInstanceMethod(Property->getSetterName()); + if (GetterMethod && GetterMethod->isSynthesizedAccessorStub()) + GetterMethod = nullptr; + if (SetterMethod && SetterMethod->isSynthesizedAccessorStub()) + SetterMethod = nullptr; LookedUpGetterSetter = true; if (GetterMethod) { Diag(GetterMethod->getLocation(), @@ -2161,15 +2215,13 @@ Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, Property->getIdentifier(), Property->getQueryKind())) { if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; - if (!LookedUpGetterSetter) { - GetterMethod = Property->isClassProperty() ? - IMPDecl->getClassMethod(Property->getGetterName()) : - IMPDecl->getInstanceMethod(Property->getGetterName()); - SetterMethod = Property->isClassProperty() ? - IMPDecl->getClassMethod(Property->getSetterName()) : - IMPDecl->getInstanceMethod(Property->getSetterName()); - } - if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { + GetterMethod = PIDecl->getGetterMethodDecl(); + SetterMethod = PIDecl->getSetterMethodDecl(); + if (GetterMethod && GetterMethod->isSynthesizedAccessorStub()) + GetterMethod = nullptr; + if (SetterMethod && SetterMethod->isSynthesizedAccessorStub()) + SetterMethod = nullptr; + if ((bool)GetterMethod ^ (bool)SetterMethod) { SourceLocation MethodLoc = (GetterMethod ? GetterMethod->getLocation() : SetterMethod->getLocation()); @@ -2210,8 +2262,10 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D for (const auto *PID : D->property_impls()) { const ObjCPropertyDecl *PD = PID->getPropertyDecl(); if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() && - !PD->isClassProperty() && - !D->getInstanceMethod(PD->getGetterName())) { + !PD->isClassProperty()) { + ObjCMethodDecl *IM = PID->getGetterMethodDecl(); + if (IM && !IM->isSynthesizedAccessorStub()) + continue; ObjCMethodDecl *method = PD->getGetterMethodDecl(); if (!method) continue; @@ -2396,16 +2450,14 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { } } - GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, - property->getGetterName(), - resultTy, nullptr, CD, - !IsClassProperty, /*isVariadic=*/false, - /*isPropertyAccessor=*/true, - /*isImplicitlyDeclared=*/true, /*isDefined=*/false, - (property->getPropertyImplementation() == - ObjCPropertyDecl::Optional) ? - ObjCMethodDecl::Optional : - ObjCMethodDecl::Required); + GetterMethod = ObjCMethodDecl::Create( + Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD, + !IsClassProperty, /*isVariadic=*/false, + /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) + ? ObjCMethodDecl::Optional + : ObjCMethodDecl::Required); CD->addDecl(GetterMethod); AddPropertyAttrs(*this, GetterMethod, property); @@ -2447,6 +2499,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property) { nullptr, CD, !IsClassProperty, /*isVariadic=*/false, /*isPropertyAccessor=*/true, + /*isSynthesizedAccessorStub=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, (property->getPropertyImplementation() == diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index 06bcd8d00de..602806968ce 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -1190,16 +1190,15 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { true /*instance*/); if (!AtIndexGetter && S.getLangOpts().DebuggerObjCLiteral) { - AtIndexGetter = ObjCMethodDecl::Create(S.Context, SourceLocation(), - SourceLocation(), AtIndexGetterSelector, - S.Context.getObjCIdType() /*ReturnType*/, - nullptr /*TypeSourceInfo */, - S.Context.getTranslationUnitDecl(), - true /*Instance*/, false/*isVariadic*/, - /*isPropertyAccessor=*/false, - /*isImplicitlyDeclared=*/true, /*isDefined=*/false, - ObjCMethodDecl::Required, - false); + AtIndexGetter = ObjCMethodDecl::Create( + S.Context, SourceLocation(), SourceLocation(), AtIndexGetterSelector, + S.Context.getObjCIdType() /*ReturnType*/, nullptr /*TypeSourceInfo */, + S.Context.getTranslationUnitDecl(), true /*Instance*/, + false /*isVariadic*/, + /*isPropertyAccessor=*/false, + /*isSynthesizedAccessorStub=*/false, + /*isImplicitlyDeclared=*/true, /*isDefined=*/false, + ObjCMethodDecl::Required, false); ParmVarDecl *Argument = ParmVarDecl::Create(S.Context, AtIndexGetter, SourceLocation(), SourceLocation(), arrayRef ? &S.Context.Idents.get("index") @@ -1303,6 +1302,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { ReturnType, ReturnTInfo, S.Context.getTranslationUnitDecl(), true /*Instance*/, false /*isVariadic*/, /*isPropertyAccessor=*/false, + /*isSynthesizedAccessorStub=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, false); SmallVector<ParmVarDecl *, 2> Params; |