Index: clang/include/clang/AST/DeclObjC.h =================================================================== --- clang/include/clang/AST/DeclObjC.h +++ clang/include/clang/AST/DeclObjC.h @@ -273,6 +273,10 @@ ObjCMethodDeclBits.HasRedeclaration = HRD; } + /// Each Objective-C method decl may have exactly one redecl. This + /// returns it or this if there is none. + const ObjCMethodDecl *getRedeclaration() const; + /// Returns the location where the declarator ends. It will be /// the location of ';' for a method declaration and the location of '{' /// for a method definition. @@ -2779,6 +2783,13 @@ /// Null for \@dynamic. Required for \@synthesize. ObjCIvarDecl *PropertyIvarDecl; + /// A redeclaration of the getter with this implementation's + /// interface as a decl context. + ObjCMethodDecl *GetterMethodDecl = nullptr; + /// A redeclaration of the setter with this implementation's + /// interface as a decl context. + ObjCMethodDecl *SetterMethodDecl = nullptr; + /// Null for \@dynamic. Non-null if property must be copy-constructed in /// getter. Expr *GetterCXXConstructor = nullptr; @@ -2845,6 +2856,12 @@ return IvarLoc.isValid() && IvarLoc != getLocation(); } + ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } + void setGetterMethodDecl(ObjCMethodDecl *MD) { GetterMethodDecl = MD; } + + ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } + void setSetterMethodDecl(ObjCMethodDecl *MD) { SetterMethodDecl = MD; } + Expr *getGetterCXXConstructor() const { return GetterCXXConstructor; } Index: clang/lib/AST/DeclObjC.cpp =================================================================== --- clang/lib/AST/DeclObjC.cpp +++ clang/lib/AST/DeclObjC.cpp @@ -899,6 +899,16 @@ setParamsAndSelLocs(C, Params, SelLocs); } +const ObjCMethodDecl *ObjCMethodDecl::getRedeclaration() const { + for (auto I : this->redecls()) { + auto *T = cast(I); + if (T != this) + return T; + } + return this; +} + + /// A definition will return its interface declaration. /// An interface declaration will return its definition. /// Otherwise it will return itself. @@ -925,8 +935,28 @@ } else if (auto *ImplD = dyn_cast(CtxD)) { if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) - if (!IFD->isInvalidDecl()) + if (!IFD->isInvalidDecl()) { Redecl = IFD->getMethod(getSelector(), isInstanceMethod()); + // FIXME: In the following case the redecl of the p + // getter/setter is in the @implementation A + // DeclContext, so search A's categories for the + // declaration. + // + // @interface A + // @end + // + // @interface A() + // @property int p; + // @end + // + // @implementation A + // @synthesize p = _p; + // @end + if (!Redecl) + for (auto *CategoryD : IFD->known_categories()) + if ((Redecl = CategoryD->getMethod(getSelector(), isInstanceMethod()))) + break; + } } else if (auto *CImplD = dyn_cast(CtxD)) { if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl()) @@ -1285,10 +1315,8 @@ SmallVectorImpl &Overridden) const { const ObjCMethodDecl *Method = this; - if (Method->isRedeclaration()) { - Method = cast(Method->getDeclContext())-> - getMethod(Method->getSelector(), Method->isInstanceMethod()); - } + if (Method->isRedeclaration()) + Method = Method->getRedeclaration(); if (Method->isOverriding()) { collectOverriddenMethodsSlow(Method, Overridden); Index: clang/lib/CodeGen/CGDebugInfo.h =================================================================== --- clang/lib/CodeGen/CGDebugInfo.h +++ clang/lib/CodeGen/CGDebugInfo.h @@ -601,6 +601,17 @@ /// declaration for the given method definition. llvm::DISubprogram *getFunctionDeclaration(const Decl *D); + /// \return debug info descriptor to the describe method declaration + /// for the given method definition. + /// \param FnType For Objective-C methods, their type. + /// \param LineNo The declaration's line number. + /// \param Flags The DIFlags for the method declaration. + /// \param SPFlags The subprogram-spcific flags for the method declaration. + llvm::DISubprogram * + getObjCMethodDeclaration(const Decl *D, llvm::DISubroutineType *FnType, + unsigned LineNo, llvm::DINode::DIFlags Flags, + llvm::DISubprogram::DISPFlags SPFlags); + /// \return debug info descriptor to describe in-class static data /// member declaration for the given out-of-class definition. If D /// is an out-of-class definition of a static data member of a Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -2566,8 +2566,8 @@ SourceLocation Loc = PD->getLocation(); llvm::DIFile *PUnit = getOrCreateFile(Loc); unsigned PLine = getLineNumber(Loc); - ObjCMethodDecl *Getter = PD->getGetterMethodDecl(); - ObjCMethodDecl *Setter = PD->getSetterMethodDecl(); + ObjCMethodDecl *Getter = PImpD->getGetterMethodDecl(); + ObjCMethodDecl *Setter = PImpD->getSetterMethodDecl(); PropertyNode = DBuilder.createObjCProperty( PD->getName(), PUnit, PLine, hasDefaultGetterName(PD, Getter) @@ -3447,6 +3447,39 @@ return nullptr; } +llvm::DISubprogram *CGDebugInfo::getObjCMethodDeclaration( + const Decl *D, llvm::DISubroutineType *FnType, unsigned LineNo, + llvm::DINode::DIFlags Flags, llvm::DISubprogram::DISPFlags SPFlags) { + if (!D || DebugKind <= codegenoptions::DebugLineTablesOnly) + return nullptr; + + if (CGM.getCodeGenOpts().DwarfVersion < 5) + return nullptr; + + // Starting with DWARF V5 method declarations are emitted as children of + // the interface type. + if (const auto *OMD = dyn_cast_or_null(D)) { + auto *ID = dyn_cast_or_null(D->getDeclContext()); + if (!ID) + ID = OMD->getClassInterface(); + if (ID) { + QualType QTy(ID->getTypeForDecl(), 0); + auto It = TypeCache.find(QTy.getAsOpaquePtr()); + if (It != TypeCache.end()) { + auto *InterfaceType = cast(It->second); + llvm::DISubprogram *FD = DBuilder.createFunction( + InterfaceType, getObjCMethodName(OMD), StringRef(), + InterfaceType->getFile(), LineNo, FnType, LineNo, Flags, + SPFlags); + DBuilder.finalizeSubprogram(FD); + ObjCMethodCache[ID].push_back(FD); + return FD; + } + } + } + return nullptr; +} + // getOrCreateFunctionType - Construct type. If it is a c++ method, include // implicit parameter "this". llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, @@ -3589,6 +3622,12 @@ unsigned LineNo = getLineNumber(Loc); unsigned ScopeLine = getLineNumber(ScopeLoc); + llvm::DISubroutineType *DIFnType = getOrCreateFunctionType(D, FnType, Unit); + llvm::DISubprogram *Decl = nullptr; + if (D) + Decl = isa(D) + ? getObjCMethodDeclaration(D, DIFnType, LineNo, Flags, SPFlags) + : getFunctionDeclaration(D); // FIXME: The function declaration we're constructing here is mostly reusing // declarations from CXXMethodDecl and not constructing new ones for arbitrary @@ -3596,9 +3635,8 @@ // all subprograms instead of the actual context since subprogram definitions // are emitted as CU level entities by the backend. llvm::DISubprogram *SP = DBuilder.createFunction( - FDContext, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, FlagsForDef, - SPFlagsForDef, TParamsArray.get(), getFunctionDeclaration(D)); + FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine, + FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl); Fn->setSubprogram(SP); // We might get here with a VarDecl in the case we're generating // code for the initialization of globals. Do not record these decls @@ -3615,26 +3653,6 @@ if (FD->hasBody() && !FD->param_empty()) SPDefCache[FD].reset(SP); - if (CGM.getCodeGenOpts().DwarfVersion >= 5) { - // Starting with DWARF V5 method declarations are emitted as children of - // the interface type. - if (const auto *OMD = dyn_cast_or_null(D)) { - const ObjCInterfaceDecl *ID = OMD->getClassInterface(); - QualType QTy(ID->getTypeForDecl(), 0); - auto It = TypeCache.find(QTy.getAsOpaquePtr()); - if (It != TypeCache.end()) { - llvm::DICompositeType *InterfaceDecl = - cast(It->second); - llvm::DISubprogram *FD = DBuilder.createFunction( - InterfaceDecl, Name, LinkageName, Unit, LineNo, - getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags, - TParamsArray.get()); - DBuilder.finalizeSubprogram(FD); - ObjCMethodCache[ID].push_back(FD); - } - } - } - // Push the function onto the lexical block stack. LexicalBlockStack.emplace_back(SP); Index: clang/lib/CodeGen/CGObjC.cpp =================================================================== --- clang/lib/CodeGen/CGObjC.cpp +++ clang/lib/CodeGen/CGObjC.cpp @@ -954,8 +954,7 @@ const ObjCPropertyImplDecl *PID) { llvm::Constant *AtomicHelperFn = CodeGenFunction(CGM).GenerateObjCAtomicGetterCopyHelperFunction(PID); - const ObjCPropertyDecl *PD = PID->getPropertyDecl(); - ObjCMethodDecl *OMD = PD->getGetterMethodDecl(); + ObjCMethodDecl *OMD = PID->getGetterMethodDecl(); assert(OMD && "Invalid call to generate getter (empty method)"); StartObjCMethod(OMD, IMP->getClassInterface()); @@ -1041,7 +1040,7 @@ const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); QualType propType = prop->getType(); - ObjCMethodDecl *getterMethod = prop->getGetterMethodDecl(); + ObjCMethodDecl *getterMethod = propImpl->getGetterMethodDecl(); ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); @@ -1311,9 +1310,8 @@ CodeGenFunction::generateObjCSetterBody(const ObjCImplementationDecl *classImpl, const ObjCPropertyImplDecl *propImpl, llvm::Constant *AtomicHelperFn) { - const ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); ObjCIvarDecl *ivar = propImpl->getPropertyIvarDecl(); - ObjCMethodDecl *setterMethod = prop->getSetterMethodDecl(); + ObjCMethodDecl *setterMethod = propImpl->getSetterMethodDecl(); // Just use the setter expression if Sema gave us one and it's // non-trivial. @@ -1490,8 +1488,7 @@ const ObjCPropertyImplDecl *PID) { llvm::Constant *AtomicHelperFn = CodeGenFunction(CGM).GenerateObjCAtomicSetterCopyHelperFunction(PID); - const ObjCPropertyDecl *PD = PID->getPropertyDecl(); - ObjCMethodDecl *OMD = PD->getSetterMethodDecl(); + ObjCMethodDecl *OMD = PID->getSetterMethodDecl(); assert(OMD && "Invalid call to generate setter (empty method)"); StartObjCMethod(OMD, IMP->getClassInterface()); Index: clang/lib/CodeGen/CGObjCGNU.cpp =================================================================== --- clang/lib/CodeGen/CGObjCGNU.cpp +++ clang/lib/CodeGen/CGObjCGNU.cpp @@ -1879,13 +1879,12 @@ for (auto *propImpl : OID->property_impls()) if (propImpl->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { - ObjCPropertyDecl *prop = propImpl->getPropertyDecl(); auto addIfExists = [&](const ObjCMethodDecl* OMD) { if (OMD) InstanceMethods.push_back(OMD); }; - addIfExists(prop->getGetterMethodDecl()); - addIfExists(prop->getSetterMethodDecl()); + addIfExists(propImpl->getGetterMethodDecl()); + addIfExists(propImpl->getSetterMethodDecl()); } if (InstanceMethods.size() == 0) @@ -3493,13 +3492,12 @@ for (auto *propertyImpl : OID->property_impls()) if (propertyImpl->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { - ObjCPropertyDecl *property = propertyImpl->getPropertyDecl(); auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) { if (accessor) InstanceMethods.push_back(accessor); }; - addPropertyMethod(property->getGetterMethodDecl()); - addPropertyMethod(property->getSetterMethodDecl()); + addPropertyMethod(propertyImpl->getGetterMethodDecl()); + addPropertyMethod(propertyImpl->getSetterMethodDecl()); } llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl); Index: clang/lib/CodeGen/CGObjCMac.cpp =================================================================== --- clang/lib/CodeGen/CGObjCMac.cpp +++ clang/lib/CodeGen/CGObjCMac.cpp @@ -3561,12 +3561,10 @@ for (const auto *PID : ID->property_impls()) { if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { - ObjCPropertyDecl *PD = PID->getPropertyDecl(); - - if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) + if (ObjCMethodDecl *MD = PID->getGetterMethodDecl()) if (GetMethodDefinition(MD)) Methods[InstanceMethods].push_back(MD); - if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) + if (ObjCMethodDecl *MD = PID->getSetterMethodDecl()) if (GetMethodDefinition(MD)) Methods[InstanceMethods].push_back(MD); } @@ -6236,12 +6234,10 @@ for (const auto *PID : ID->property_impls()) { if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){ - ObjCPropertyDecl *PD = PID->getPropertyDecl(); - - if (auto MD = PD->getGetterMethodDecl()) + if (auto MD = PID->getGetterMethodDecl()) if (GetMethodDefinition(MD)) methods.push_back(MD); - if (auto MD = PD->getSetterMethodDecl()) + if (auto MD = PID->getSetterMethodDecl()) if (GetMethodDefinition(MD)) methods.push_back(MD); } Index: clang/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenFunction.cpp +++ clang/lib/CodeGen/CodeGenFunction.cpp @@ -635,8 +635,7 @@ return CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM); } -void CodeGenFunction::StartFunction(GlobalDecl GD, - QualType RetTy, +void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, Index: clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp =================================================================== --- clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -953,7 +953,7 @@ "id objc_getProperty(id, SEL, long, bool);\n"; } RewriteObjCMethodDecl(OID->getContainingInterface(), - PD->getGetterMethodDecl(), Getr); + PID->getGetterMethodDecl(), Getr); Getr += "{ "; // Synthesize an explicit cast to gain access to the ivar. // See objc-act.c:objc_synthesize_new_getter() for details. @@ -961,7 +961,7 @@ // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) Getr += "typedef "; const FunctionType *FPRetType = nullptr; - RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr, + RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr, FPRetType); Getr += " _TYPE"; if (FPRetType) { @@ -1013,7 +1013,7 @@ } RewriteObjCMethodDecl(OID->getContainingInterface(), - PD->getSetterMethodDecl(), Setr); + PID->getSetterMethodDecl(), Setr); Setr += "{ "; // Synthesize an explicit cast to initialize the ivar. // See objc-act.c:objc_synthesize_new_setter() for details. @@ -7032,12 +7032,12 @@ ObjCPropertyDecl *PD = Prop->getPropertyDecl(); if (!PD) continue; - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) + if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl()) if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/)) InstanceMethods.push_back(Getter); if (PD->isReadOnly()) continue; - if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) + if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl()) if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/)) InstanceMethods.push_back(Setter); } @@ -7282,11 +7282,11 @@ ObjCPropertyDecl *PD = Prop->getPropertyDecl(); if (!PD) continue; - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) + if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl()) InstanceMethods.push_back(Getter); if (PD->isReadOnly()) continue; - if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) + if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl()) InstanceMethods.push_back(Setter); } Index: clang/lib/Frontend/Rewrite/RewriteObjC.cpp =================================================================== --- clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -787,7 +787,7 @@ if (!OID) return; unsigned Attributes = PD->getPropertyAttributes(); - if (!PD->getGetterMethodDecl()->isDefined()) { + if (!PID->getGetterMethodDecl()->isDefined()) { bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) && (Attributes & (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_copy)); @@ -799,7 +799,7 @@ "id objc_getProperty(id, SEL, long, bool);\n"; } RewriteObjCMethodDecl(OID->getContainingInterface(), - PD->getGetterMethodDecl(), Getr); + PID->getGetterMethodDecl(), Getr); Getr += "{ "; // Synthesize an explicit cast to gain access to the ivar. // See objc-act.c:objc_synthesize_new_getter() for details. @@ -807,7 +807,7 @@ // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) Getr += "typedef "; const FunctionType *FPRetType = nullptr; - RewriteTypeIntoString(PD->getGetterMethodDecl()->getReturnType(), Getr, + RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr, FPRetType); Getr += " _TYPE"; if (FPRetType) { @@ -843,7 +843,7 @@ InsertText(onePastSemiLoc, Getr); } - if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined()) + if (PD->isReadOnly() || PID->getSetterMethodDecl()->isDefined()) return; // Generate the 'setter' function. @@ -858,7 +858,7 @@ } RewriteObjCMethodDecl(OID->getContainingInterface(), - PD->getSetterMethodDecl(), Setr); + PID->getSetterMethodDecl(), Setr); Setr += "{ "; // Synthesize an explicit cast to initialize the ivar. // See objc-act.c:objc_synthesize_new_setter() for details. @@ -5354,12 +5354,12 @@ ObjCPropertyDecl *PD = Prop->getPropertyDecl(); if (!PD) continue; - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) + if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl()) if (!Getter->isDefined()) InstanceMethods.push_back(Getter); if (PD->isReadOnly()) continue; - if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) + if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl()) if (!Setter->isDefined()) InstanceMethods.push_back(Setter); } @@ -5632,11 +5632,11 @@ ObjCPropertyDecl *PD = Prop->getPropertyDecl(); if (!PD) continue; - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) + if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl()) InstanceMethods.push_back(Getter); if (PD->isReadOnly()) continue; - if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) + if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl()) InstanceMethods.push_back(Setter); } RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), Index: clang/lib/Index/IndexDecl.cpp =================================================================== --- clang/lib/Index/IndexDecl.cpp +++ clang/lib/Index/IndexDecl.cpp @@ -513,7 +513,6 @@ } bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { - ObjCPropertyDecl *PD = D->getPropertyDecl(); auto *Container = cast(D->getDeclContext()); SourceLocation Loc = D->getLocation(); SymbolRoleSet Roles = 0; @@ -533,12 +532,12 @@ assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); SymbolRoleSet AccessorMethodRoles = SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit); - if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { + if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) { if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container)) IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); } - if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { + if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) { if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container)) IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); Index: clang/lib/Sema/SemaObjCProperty.cpp =================================================================== --- clang/lib/Sema/SemaObjCProperty.cpp +++ clang/lib/Sema/SemaObjCProperty.cpp @@ -1404,6 +1404,24 @@ if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { getterMethod->createImplicitParams(Context, IDecl); + ObjCMethodDecl *GetterImplDecl = ObjCMethodDecl::Create( + Context, AtLoc, PropertyLoc, getterMethod->getSelector(), + getterMethod->getReturnType(), getterMethod->getReturnTypeSourceInfo(), + PIDecl->getDeclContext(), getterMethod->isInstanceMethod(), + getterMethod->isVariadic(), getterMethod->isPropertyAccessor(), + getterMethod->isImplicit(), getterMethod->isDefined(), + getterMethod->getImplementationControl(), + getterMethod->hasRelatedResultType()); + + + GetterImplDecl->setAsRedeclaration(getterMethod->getRedeclaration()); + GetterImplDecl->getMethodFamily(); + if (getterMethod->hasAttrs()) + GetterImplDecl->setAttrs(getterMethod->getAttrs()); + GetterImplDecl->setSelfDecl(getterMethod->getSelfDecl()); + GetterImplDecl->setCmdDecl(getterMethod->getCmdDecl()); + PIDecl->setGetterMethodDecl(GetterImplDecl); + if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && Ivar->getType()->isRecordType()) { // For Objective-C++, need to synthesize the AST for the IVAR object to be @@ -1458,6 +1476,28 @@ } if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { setterMethod->createImplicitParams(Context, IDecl); + + // Redeclare the setter within the implementation as DeclContext. + ObjCMethodDecl *SetterImplDecl = ObjCMethodDecl::Create( + Context, AtLoc, PropertyLoc, setterMethod->getSelector(), + setterMethod->getReturnType(), setterMethod->getReturnTypeSourceInfo(), + PIDecl->getDeclContext(), setterMethod->isInstanceMethod(), + setterMethod->isVariadic(), setterMethod->isPropertyAccessor(), + setterMethod->isImplicit(), setterMethod->isDefined(), + setterMethod->getImplementationControl(), + setterMethod->hasRelatedResultType()); + SetterImplDecl->setAsRedeclaration(setterMethod->getRedeclaration()); + SetterImplDecl->getMethodFamily(); + if (setterMethod->hasAttrs()) + SetterImplDecl->setAttrs(setterMethod->getAttrs()); + SetterImplDecl->setSelfDecl(setterMethod->getSelfDecl()); + SetterImplDecl->setCmdDecl(setterMethod->getCmdDecl()); + SmallVector SelLocs; + setterMethod->getSelectorLocs(SelLocs); + SetterImplDecl->setMethodParams(Context, setterMethod->parameters(), + SelLocs); + PIDecl->setSetterMethodDecl(SetterImplDecl); + if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && Ivar->getType()->isRecordType()) { // FIXME. Eventually we want to do this for Objective-C as well. Index: clang/lib/Serialization/ASTReaderDecl.cpp =================================================================== --- clang/lib/Serialization/ASTReaderDecl.cpp +++ clang/lib/Serialization/ASTReaderDecl.cpp @@ -1310,6 +1310,8 @@ D->setPropertyDecl(ReadDeclAs()); D->PropertyIvarDecl = ReadDeclAs(); D->IvarLoc = ReadSourceLocation(); + D->setGetterMethodDecl(ReadDeclAs()); + D->setSetterMethodDecl(ReadDeclAs()); D->setGetterCXXConstructor(Record.readExpr()); D->setSetterCXXAssignment(Record.readExpr()); } Index: clang/lib/Serialization/ASTWriterDecl.cpp =================================================================== --- clang/lib/Serialization/ASTWriterDecl.cpp +++ clang/lib/Serialization/ASTWriterDecl.cpp @@ -881,6 +881,8 @@ Record.AddDeclRef(D->getPropertyDecl()); Record.AddDeclRef(D->getPropertyIvarDecl()); Record.AddSourceLocation(D->getPropertyIvarDeclLoc()); + Record.AddDeclRef(D->getGetterMethodDecl()); + Record.AddDeclRef(D->getSetterMethodDecl()); Record.AddStmt(D->getGetterCXXConstructor()); Record.AddStmt(D->getSetterCXXAssignment()); Code = serialization::DECL_OBJC_PROPERTY_IMPL; Index: clang/test/CodeGenObjC/debug-info-objc-property-dwarf5.m =================================================================== --- /dev/null +++ clang/test/CodeGenObjC/debug-info-objc-property-dwarf5.m @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -dwarf-version=5 %s -o - | FileCheck %s + +@protocol NSObject +@end + +@interface NSObject {} +@end + +struct Bar {}; + +@protocol BarProto +@property struct Bar *bar; +@end + +@interface Foo +@end + +@implementation Foo {} +@synthesize bar = _bar; +- (void)f {} +@end + +// CHECK: ![[FOO:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" + +// CHECK: ![[DECL:[0-9]+]] = !DISubprogram(name: "-[Foo setBar:]", +// CHECK-SAME: scope: ![[FOO]] + +// CHECK: distinct !DISubprogram(name: "-[Foo setBar:]", +// CHECK-SAME: declaration: ![[DECL:[0-9]+]] Index: clang/test/CodeGenObjC/debug-info-synthesis.m =================================================================== --- clang/test/CodeGenObjC/debug-info-synthesis.m +++ clang/test/CodeGenObjC/debug-info-synthesis.m @@ -30,8 +30,8 @@ } } -// CHECK: ![[FILE:.*]] = !DIFile(filename: "{{[^"]+}}foo.h" +// CHECK: ![[FILE:.*]] = !DIFile(filename: "foo.m" // CHECK: !DISubprogram(name: "-[Foo setDict:]" // CHECK-SAME: file: ![[FILE]], -// CHECK-SAME: line: 8, +// CHECK-SAME: line: 7, // CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition Index: clang/test/CodeGenObjC/debug-property-synth.m =================================================================== --- clang/test/CodeGenObjC/debug-property-synth.m +++ clang/test/CodeGenObjC/debug-property-synth.m @@ -7,6 +7,10 @@ @interface I { int _p1; } +@property int p1; +@end + +@implementation I // Test that the linetable entries for the synthesized getter and // setter are correct. // @@ -22,10 +26,6 @@ // CHECK: ![[DBG1]] = !DILocation(line: [[@LINE+3]], // CHECK: !DISubprogram(name: "-[I setP1:]",{{.*}} line: [[@LINE+2]],{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition // CHECK: ![[DBG2]] = !DILocation(line: [[@LINE+1]], -@property int p1; -@end - -@implementation I @synthesize p1 = _p1; @end Index: clang/test/CodeGenObjC/debuginfo-properties.m =================================================================== --- clang/test/CodeGenObjC/debuginfo-properties.m +++ clang/test/CodeGenObjC/debuginfo-properties.m @@ -11,19 +11,6 @@ @protocol HasASelection @property (nonatomic, retain) Selection* selection; -// CHECK: !DISubprogram(name: "-[MyClass selection]" -// CHECK-SAME: line: [[@LINE-2]] -// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK: !DISubprogram(name: "-[MyClass setSelection:]" -// CHECK-SAME: line: [[@LINE-5]] -// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK: !DISubprogram(name: "-[OtherClass selection]" -// CHECK-SAME: line: [[@LINE-8]] -// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK: !DISubprogram(name: "-[OtherClass setSelection:]" -// CHECK-SAME: line: [[@LINE-11]] -// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition - @end @interface MyClass : NSObject { @@ -33,6 +20,12 @@ @implementation MyClass @synthesize selection = _selection; +// CHECK: !DISubprogram(name: "-[MyClass selection]" +// CHECK-SAME: line: [[@LINE-2]] +// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK: !DISubprogram(name: "-[MyClass setSelection:]" +// CHECK-SAME: line: [[@LINE-5]] +// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition @end @interface OtherClass : NSObject { @@ -41,4 +34,10 @@ @end @implementation OtherClass @synthesize selection = _selection; +// CHECK: !DISubprogram(name: "-[OtherClass selection]" +// CHECK-SAME: line: [[@LINE-2]] +// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK: !DISubprogram(name: "-[OtherClass setSelection:]" +// CHECK-SAME: line: [[@LINE-5]] +// CHECK-SAME: DISPFlagLocalToUnit | DISPFlagDefinition @end Index: clang/test/CodeGenObjC/instance-method-metadata.m =================================================================== --- clang/test/CodeGenObjC/instance-method-metadata.m +++ clang/test/CodeGenObjC/instance-method-metadata.m @@ -1,6 +1,5 @@ // REQUIRES: x86-registered-target -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S -o %t %s -// RUN: FileCheck < %t %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -S %s -o - | FileCheck %s // rdar://9072317