ABataev created this revision.

If the first parameter of the function is the ImplicitParamDecl codegen
automatically marks it as an implicit argument with `this` or `self`
pointer. To fix this problem Implicit ThisOrSelfAttr is added. This
attribute is used to mark real `this` or `self` pointers only.


https://reviews.llvm.org/D33735

Files:
  include/clang/Basic/Attr.td
  lib/AST/DeclObjC.cpp
  lib/CodeGen/CGCXXABI.cpp
  lib/CodeGen/CGDebugInfo.cpp
  test/CodeGen/captured-statements.c
  test/CodeGenCXX/captured-statements.cpp
  test/Misc/ast-dump-decl.m
  test/Misc/pragma-attribute-objc-subject-match-rules.m
  test/Misc/pragma-attribute-objc.m

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"
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/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/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/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: 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<ImplicitParamDecl>(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<ImplicitParamDecl>(VD) && ArgNo && *ArgNo == 1 &&
+      VD->hasAttr<ThisOrSelfAttr>())
+    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: 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/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: 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 = [];
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to