aprantl updated this revision to Diff 218000.
aprantl added a comment.
Herald added a subscriber: arphaman.

Here is a work-in-progress alternative patch that attacks the problem by 
changing the AST generation to have an ObjCMethodDecl for the property 
accessors inside the implementation as suggested by @rjmccall.

The patch passes all clang-codegen-* tests, with a few problems in c-index-test 
outstanding that I'll work through.

Let me know if you have any feedback on this approach! I'd be curious if there 
is a more elegant way of doing this: The code that I needed to add to 
`ObjCMethodDecl::getNextRedeclarationImpl()` is a bit odd (see the example in 
the FIXME comment there). It's also weird that Objective-C methods can have 
exactly one redeclaration which forces me to set up a chain of redeclarations 
in Sema::ActOnPropertyImplDecl() instead of having several implementations 
point to the same abstract property declaration, but that seems to work.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66121/new/

https://reviews.llvm.org/D66121

Files:
  clang/include/clang/AST/DeclObjC.h
  clang/lib/AST/DeclObjC.cpp
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/CodeGen/CGDebugInfo.h
  clang/lib/CodeGen/CGObjC.cpp
  clang/lib/CodeGen/CGObjCGNU.cpp
  clang/lib/CodeGen/CGObjCMac.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
  clang/lib/Frontend/Rewrite/RewriteObjC.cpp
  clang/lib/Index/IndexDecl.cpp
  clang/lib/Sema/SemaObjCProperty.cpp
  clang/lib/Serialization/ASTReaderDecl.cpp
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/test/CodeGenObjC/debug-info-objc-property-dwarf5.m
  clang/test/CodeGenObjC/debug-info-synthesis.m
  clang/test/CodeGenObjC/debug-property-synth.m
  clang/test/CodeGenObjC/debuginfo-properties.m
  clang/test/CodeGenObjC/instance-method-metadata.m

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
 
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 <NSObject>
 @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 <HasASelection> {
@@ -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 <HasASelection> {
@@ -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/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/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-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 <NSObject> {}
+@end
+
+struct Bar {};
+
+@protocol BarProto
+@property struct Bar *bar;
+@end
+
+@interface Foo <BarProto>
+@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/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/lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderDecl.cpp
+++ clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1310,6 +1310,8 @@
   D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>());
   D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>();
   D->IvarLoc = ReadSourceLocation();
+  D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
+  D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
   D->setGetterCXXConstructor(Record.readExpr());
   D->setSetterCXXAssignment(Record.readExpr());
 }
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<SourceLocation, 1> 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/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<ObjCImplDecl>(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/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/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/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/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/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/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/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<ObjCMethodDecl>(D)) {
+    auto *ID = dyn_cast_or_null<ObjCInterfaceDecl>(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<llvm::DICompositeType>(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<ObjCMethodDecl>(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<ObjCMethodDecl>(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<llvm::DICompositeType>(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/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<ObjCMethodDecl>(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<ObjCImplementationDecl>(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<ObjCCategoryImplDecl>(CtxD)) {
       if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
@@ -1285,10 +1315,8 @@
                     SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const {
   const ObjCMethodDecl *Method = this;
 
-  if (Method->isRedeclaration()) {
-    Method = cast<ObjCContainerDecl>(Method->getDeclContext())->
-                   getMethod(Method->getSelector(), Method->isInstanceMethod());
-  }
+  if (Method->isRedeclaration())
+    Method = Method->getRedeclaration();
 
   if (Method->isOverriding()) {
     collectOverriddenMethodsSlow(Method, Overridden);
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;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to