r254750 - Fix debug info for Objective-C properties from class extensions after r251874
Nico Weber via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 4 11:14:14 PST 2015
Author: nico
Date: Fri Dec 4 13:14:14 2015
New Revision: 254750
URL: http://llvm.org/viewvc/llvm-project?rev=254750&view=rev
Log:
Fix debug info for Objective-C properties from class extensions after r251874
After r251874, properties from class extensions no longer show up in
ObjCInterfaceDecl::properties(). Make debug info emission explicitly
look for properties in class extensions before looking at direct properties.
Also add a test that checks for this. There are three interesting cases:
1. A property is only declared in a class extension, and the @implementation
is in a different file. This used to generated a DIObjcProperty before
r251874 and does again with this fix.
2. A property is declared as readonly in the class itself and redeclared as
readwrite in a class extension. clang before r251874 put the DIObjcProperty
on the first declaration. clang after r251874 didn't emit any DIObjcProperty,
and clang with this fix puts it on the readwrite redeclaration (which is
what lookup finds). This seems like a progression.
3. Like 2, but with an @implementation in the same file. In this case,
the property debug info gets generated a second time through the ivar
from the definition. In this case, lookup and declaration code need
to agree on the line number so that the DIObjcProperty isn't emitted
twice. In this case, clang before r251874 emitted one DIObjcProperty
on the first declaration, clang with r251874 emitted one on the second
declaration, and clang with this patch still does the latter.
Added:
cfe/trunk/test/CodeGenObjC/debug-info-property-class-extension.m
Modified:
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=254750&r1=254749&r2=254750&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Dec 4 13:14:14 2015
@@ -1791,7 +1791,7 @@ llvm::DIType *CGDebugInfo::CreateTypeDef
}
// Create entries for all of the properties.
- for (const auto *PD : ID->properties()) {
+ auto AddProperty = [&](const ObjCPropertyDecl *PD) {
SourceLocation Loc = PD->getLocation();
llvm::DIFile *PUnit = getOrCreateFile(Loc);
unsigned PLine = getLineNumber(Loc);
@@ -1805,6 +1805,21 @@ llvm::DIType *CGDebugInfo::CreateTypeDef
: getSelectorName(PD->getSetterName()),
PD->getPropertyAttributes(), getOrCreateType(PD->getType(), PUnit));
EltTys.push_back(PropertyNode);
+ };
+ {
+ llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
+ //for (const ObjCCategoryDecl *ClassExt : ID->known_extensions())
+ // for (auto *PD : ClassExt->properties()) {
+ // PropertySet.insert(PD->getIdentifier());
+ // AddProperty(PD);
+ // }
+ for (const auto *PD : ID->properties()) {
+ // Don't emit duplicate metadata for properties that were already in a
+ // class extension.
+ if (!PropertySet.insert(PD->getIdentifier()).second)
+ continue;
+ AddProperty(PD);
+ }
}
const ASTRecordLayout &RL = CGM.getContext().getASTObjCInterfaceLayout(ID);
Added: cfe/trunk/test/CodeGenObjC/debug-info-property-class-extension.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/debug-info-property-class-extension.m?rev=254750&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/debug-info-property-class-extension.m (added)
+++ cfe/trunk/test/CodeGenObjC/debug-info-property-class-extension.m Fri Dec 4 13:14:14 2015
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -S -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+// Checks debug info for properties from class extensions for a few cases.
+
+
+// Readonly property in interface made readwrite in a category, with @impl
+// The interesting bit is that when the ivar debug info is generated, the corresponding
+// property is looked up and also gets debug info. If the debug info from the interface's
+// declaration and from the ivar doesn't match, this will end up with two DIObjCProperty
+// entries which would be bad.
+ at interface FooROWithImpl
+// CHECK-NOT: !DIObjCProperty(name: "evolvingpropwithimpl"{{.*}}line: [[@LINE+1]]
+ at property (readonly) int evolvingpropwithimpl;
+ at end
+ at interface FooROWithImpl ()
+// CHECK: !DIObjCProperty(name: "evolvingpropwithimpl"{{.*}}line: [[@LINE+1]]
+ at property int evolvingpropwithimpl;
+ at end
+ at implementation FooROWithImpl
+ at synthesize evolvingpropwithimpl = _evolvingpropwithimpl;
+ at end
+
+
+// Simple property from a class extension:
+ at interface Foo
+ at end
+ at interface Foo()
+// CHECK: !DIObjCProperty(name: "myprop"{{.*}}line: [[@LINE+1]]
+ at property int myprop;
+ at end
+// There's intentionally no @implementation for Foo, because that would
+// generate debug info for the property via the backing ivar.
+
+
+// Readonly property in interface made readwrite in a category:
+ at interface FooRO
+// Shouldn't be here but in the class extension below.
+// CHECK-NOT: !DIObjCProperty(name: "evolvingprop"{{.*}}line: [[@LINE+1]]
+ at property (readonly) int evolvingprop;
+ at end
+ at interface FooRO ()
+// CHECK: !DIObjCProperty(name: "evolvingprop"{{.*}}line: [[@LINE+1]]
+ at property int evolvingprop;
+ at end
+
+
+// This references types in this file to force emission of their debug info.
+void foo(Foo *f, FooRO *g, FooROWithImpl* h) { }
More information about the cfe-commits
mailing list