Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,33 @@ static bool IsArtificial(VarDecl const *VD) {
cast<Decl>(VD->getDeclContext())->isImplicit());
}

/// Returns \c true if the specified variable \c VD is an explicit parameter of
/// a synthesized Objective-C property accessor. E.g., a synthesized property
/// setter method will have a single explicit parameter which is the property to
/// set.
static bool IsObjCSynthesizedPropertyExplicitParameter(VarDecl const *VD) {
assert(VD);

if (!llvm::isa<ParmVarDecl>(VD))
return false;

// Not a property method.
const auto *Method =
llvm::dyn_cast_or_null<ObjCMethodDecl>(VD->getDeclContext());
if (!Method)
return false;

// Not a synthesized property accessor.
if (!Method->isImplicit() || !Method->isPropertyAccessor())
return false;

// Not an explicit parameter.
if (VD->isImplicit())
return false;

return true;
}

CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
Expand Down Expand Up @@ -5158,7 +5185,12 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
}
SmallVector<uint64_t, 13> Expr;
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (VarIsArtificial)

// While synthesized Objective-C property setters are "artificial" (i.e., they
// are not spelled out in source), we want to pretend they are just like a
// regular non-compiler generated method. Hence, don't mark explicitly passed
// parameters of such methods as artificial.
if (VarIsArtificial && !IsObjCSynthesizedPropertyExplicitParameter(VD))
Flags |= llvm::DINode::FlagArtificial;

auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
Expand Down
63 changes: 63 additions & 0 deletions clang/test/DebugInfo/ObjC/property-synthesized-accessors.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Test that synthesized accessors get treated like regular method declarations/definitions.
// I.e.:
// 1. explicitly passed parameter are not marked artificial.
// 2. Each property accessor has a method declaration and definition.

// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -dwarf-version=5 -debug-info-kind=limited %s -o - | FileCheck %s --implicit-check-not "DIFlagArtificial"

@interface Foo
@property int p1;
@end

@implementation Foo
@end

int main(void) {
Foo *f;
f.p1 = 2;
return f.p1;
}

// CHECK: ![[P1_TYPE:[0-9]+]] = !DIBasicType(name: "int"
// CHECK: ![[GETTER_DECL:[0-9]+]] = !DISubprogram(name: "-[Foo p1]"
// CHECK-SAME: type: ![[GETTER_TYPE:[0-9]+]]
// CHECK-SAME: flags: DIFlagArtificial | DIFlagPrototyped
// CHECK-SAME: spFlags: DISPFlagLocalToUnit)

// CHECK: ![[GETTER_TYPE]] = !DISubroutineType(types: ![[GETTER_PARAMS:[0-9]+]])
// CHECK: ![[GETTER_PARAMS]] = !{![[P1_TYPE]], ![[ID_TYPE:[0-9]+]], ![[SEL_TYPE:[0-9]+]]}
// CHECK: ![[ID_TYPE]] = !DIDerivedType(tag: DW_TAG_pointer_type
// CHECK-SAME: flags: DIFlagArtificial | DIFlagObjectPointer)
// CHECK: ![[SEL_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "SEL"
// CHECK-SAME: flags: DIFlagArtificial)

// CHECK: ![[SETTER_DECL:[0-9]+]] = !DISubprogram(name: "-[Foo setP1:]"
// CHECK-SAME: type: ![[SETTER_TYPE:[0-9]+]]
// CHECK-SAME: flags: DIFlagArtificial | DIFlagPrototyped
// CHECK-SAME: spFlags: DISPFlagLocalToUnit)
// CHECK: ![[SETTER_TYPE]] = !DISubroutineType(types: ![[SETTER_PARAMS:[0-9]+]])
// CHECK: ![[SETTER_PARAMS]] = !{null, ![[ID_TYPE]], ![[SEL_TYPE]], ![[P1_TYPE]]}

// CHECK: ![[GETTER_DEF:[0-9]+]] = distinct !DISubprogram(name: "-[Foo p1]"
// CHECK-SAME: type: ![[GETTER_TYPE]]
// CHECK-SAME: flags: DIFlagArtificial | DIFlagPrototyped
// CHECK-SAME: spFlags: DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK-SAME: declaration: ![[GETTER_DECL]]

// CHECK: !DILocalVariable(name: "self", arg: 1, scope: ![[GETTER_DEF]]
// CHECK-SAME: flags: DIFlagArtificial | DIFlagObjectPointer)
//
// CHECK: !DILocalVariable(name: "_cmd", arg: 2, scope: ![[GETTER_DEF]],
// CHECK-SAME: flags: DIFlagArtificial)

// CHECK: ![[SETTER_DEF:[0-9]+]] = distinct !DISubprogram(name: "-[Foo setP1:]",
// CHECK-SAME: type: ![[SETTER_TYPE]]
// CHECK-SAME: flags: DIFlagArtificial | DIFlagPrototyped
// CHECK-SAME: spFlags: DISPFlagLocalToUnit | DISPFlagDefinition
// CHECK-SAME: declaration: ![[SETTER_DECL]]

// CHECK: !DILocalVariable(name: "self", arg: 1, scope: ![[SETTER_DEF]]
// CHECK-SAME: flags: DIFlagArtificial | DIFlagObjectPointer
// CHECK: !DILocalVariable(name: "_cmd", arg: 2, scope: ![[SETTER_DEF]]
// CHECK-SAME: flags: DIFlagArtificial
// CHECK: !DILocalVariable(name: "p1", arg: 3, scope: ![[SETTER_DEF]]