Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -2613,6 +2613,15 @@ let Documentation = [Undocumented]; } +def ThisOrSelf : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + // Mark ImplicitParamDecl with this attribute for implicit 'this'/'self' + // pointer for correct debug info emission. + let Spellings = []; + let SemaHandler = 0; + let Documentation = [Undocumented]; +} + def OMPThreadPrivateDecl : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; Index: lib/AST/DeclObjC.cpp =================================================================== --- lib/AST/DeclObjC.cpp +++ lib/AST/DeclObjC.cpp @@ -1073,6 +1073,7 @@ ImplicitParamDecl *self = ImplicitParamDecl::Create(Context, this, SourceLocation(), &Context.Idents.get("self"), selfTy); + self->addAttr(ThisOrSelfAttr::CreateImplicit(Context)); setSelfDecl(self); if (selfIsConsumed) Index: lib/CodeGen/CGCXXABI.cpp =================================================================== --- lib/CodeGen/CGCXXABI.cpp +++ lib/CodeGen/CGCXXABI.cpp @@ -159,10 +159,11 @@ // FIXME: I'm not entirely sure I like using a fake decl just for code // generation. Maybe we can come up with a better way? - ImplicitParamDecl *ThisDecl - = ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(), - &CGM.getContext().Idents.get("this"), - MD->getThisType(CGM.getContext())); + ImplicitParamDecl *ThisDecl = ImplicitParamDecl::Create( + CGM.getContext(), CGM.getContext().getTranslationUnitDecl(), + MD->getLocation(), &CGM.getContext().Idents.get("this"), + MD->getThisType(CGM.getContext())); + ThisDecl->addAttr(ThisOrSelfAttr::CreateImplicit(CGM.getContext())); params.push_back(ThisDecl); CGF.CXXABIThisDecl = ThisDecl; Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -3462,13 +3462,11 @@ unsigned AddressSpace = CGM.getContext().getTargetAddressSpace(VD->getType()); AppendAddressSpaceXDeref(AddressSpace, Expr); - // If this is the first argument and it is implicit then - // give it an object pointer flag. - // FIXME: There has to be a better way to do this, but for static - // functions there won't be an implicit param at arg1 and - // otherwise it is 'self' or 'this'. - if (isa(VD) && ArgNo && *ArgNo == 1) - Flags |= llvm::DINode::FlagObjectPointer; + // If this is the first argument, it is implicit and has ThisOrSelf attribute + // then give it an object pointer flag. + if (isa(VD) && ArgNo && *ArgNo == 1 && + VD->hasAttr()) + Flags |= llvm::DINode::FlagObjectPointer; // Note: Older versions of clang used to emit byval references with an extra // DW_OP_deref, because they referenced the IR arg directly instead of Index: test/CodeGen/captured-statements.c =================================================================== --- test/CodeGen/captured-statements.c +++ test/CodeGen/captured-statements.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o %t +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o %t -debug-info-kind=limited // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-GLOBALS // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2 @@ -98,3 +98,8 @@ // CHECK-GLOBALS: load i32, i32* @global // CHECK-GLOBALS: load i32, i32* @ // CHECK-GLOBALS: load i32, i32* @e + +// CHECK-GLOBALS-NOT: DIFlagObjectPointer +// CHECK-1-NOT: DIFlagObjectPointer +// CHECK-2-NOT: DIFlagObjectPointer +// CHECK-3-NOT: DIFlagObjectPointer Index: test/CodeGenCXX/captured-statements.cpp =================================================================== --- test/CodeGenCXX/captured-statements.cpp +++ test/CodeGenCXX/captured-statements.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm %s -o %t +// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm %s -o %t -debug-info-kind=limited // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2 // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3 @@ -194,3 +194,18 @@ void call_test_captured_linkage() { test_captured_linkage(); } + +// CHECK-1-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) +// CHECK-1-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) +// CHECK-2-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) +// CHECK-2-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) +// CHECK-3-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) +// CHECK-3-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) +// CHECK-4-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) +// CHECK-4-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) +// CHECK-5-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) +// CHECK-5-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) +// CHECK-6-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) +// CHECK-6-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) +// CHECK-7-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) +// CHECK-7-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) Index: test/Misc/ast-dump-decl.m =================================================================== --- test/Misc/ast-dump-decl.m +++ test/Misc/ast-dump-decl.m @@ -39,6 +39,7 @@ } // CHECK: ObjCMethodDecl{{.*}} - TestObjCMethodDecl: 'int' // CHECK-NEXT: ImplicitParamDecl{{.*}} self +// CHECK-NEXT: ThisOrSelfAttr // CHECK-NEXT: ImplicitParamDecl{{.*}} _cmd // CHECK-NEXT: ParmVarDecl{{.*}} i 'int' // CHECK-NEXT: ... Index: test/Misc/pragma-attribute-objc-subject-match-rules.m =================================================================== --- test/Misc/pragma-attribute-objc-subject-match-rules.m +++ test/Misc/pragma-attribute-objc-subject-match-rules.m @@ -60,16 +60,19 @@ @end // CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testInstanceMethod // CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD-NEXT: ThisOrSelfAttr // CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl // CHECK-OBJC_METHOD-NEXT: CompoundStmt // CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" // CHECK-OBJC_METHOD: ObjCMethodDecl{{.*}} testClassMethod // CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD-NEXT: ThisOrSelfAttr // CHECK-OBJC_METHOD-NEXT: ImplicitParamDecl // CHECK-OBJC_METHOD-NEXT: CompoundStmt // CHECK-OBJC_METHOD-NEXT: AnnotateAttr{{.*}} "test" // CHECK-OBJC_METHOD_IS_INSTANCE-LABEL: ObjCMethodDecl{{.*}} testInstanceMethod // CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: ImplicitParamDecl +// CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: ThisOrSelfAttr // CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: ImplicitParamDecl // CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: CompoundStmt // CHECK-OBJC_METHOD_IS_INSTANCE-NEXT: AnnotateAttr{{.*}} "test" Index: test/Misc/pragma-attribute-objc.m =================================================================== --- test/Misc/pragma-attribute-objc.m +++ test/Misc/pragma-attribute-objc.m @@ -63,6 +63,7 @@ - (void)testIm:(int) x { // CHECK-LABEL: ObjCMethodDecl{{.*}}testIm // CHECK-NEXT: ImplicitParamDecl +// CHECK-NEXT: ThisOrSelfAttr // CHECK-NEXT: ImplicitParamDecl // CHECK-NEXT: ParmVarDecl{{.*}} x // CHECK-NEXT: AnnotateAttr{{.*}} "test"