Skip to content

[lld-macho] Make ObjC category checker print the source file name of … #80221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 1, 2024

Conversation

alx32
Copy link
Contributor

@alx32 alx32 commented Feb 1, 2024

When printing category conflicts in the ObjC category checker, also print the source file name of the problematic categories. Currently we only print the object file name. This change is mostly useful only for thinLTO builds, where the object file name will be of form 999.arm64.lto.o and thus does not reveal any information about the original source file.

…conflicting categories

Summary: When printing category conflicts in the ObjC category checker, also print the source file name of the problematic categories. Currently we only print the object file name.
This change is mostly useful only for thinLTO builds, where the object file name will be of form 999.arm64.lto.o and thus does not reveal any information about the original source file.

Test Plan: Added test case + check-lld.

Reviewers:

Subscribers:

Tasks:

Tags:
@llvmbot
Copy link
Member

llvmbot commented Feb 1, 2024

@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-macho

Author: None (alx32)

Changes

Summary: When printing category conflicts in the ObjC category checker, also print the source file name of the problematic categories. Currently we only print the object file name. This change is mostly useful only for thinLTO builds, where the object file name will be of form 999.arm64.lto.o and thus does not reveal any information about the original source file.

Test Plan: Added test case + check-lld.


Full diff: https://github.com/llvm/llvm-project/pull/80221.diff

2 Files Affected:

  • (modified) lld/MachO/ObjC.cpp (+14-2)
  • (modified) lld/test/MachO/objc-category-conflicts.s (+31-2)
diff --git a/lld/MachO/ObjC.cpp b/lld/MachO/ObjC.cpp
index 7e8cec026d2f7..02009d4ed59cf 100644
--- a/lld/MachO/ObjC.cpp
+++ b/lld/MachO/ObjC.cpp
@@ -237,12 +237,24 @@ void ObjcCategoryChecker::parseMethods(const ConcatInputSection *methodsIsec,
     StringRef newCatName =
         getReferentString(*containerIsec->getRelocAt(catLayout.nameOffset));
 
+    auto formatObjAndSrcFileName = [](const InputSection *section) {
+      lld::macho::InputFile *inputFile = section->getFile();
+      std::string result = toString(inputFile);
+
+      auto objFile = dyn_cast_or_null<ObjFile>(inputFile);
+      if (objFile && objFile->compileUnit) {
+        result += " (" + objFile->sourceFile() + ")";
+      }
+
+      return result;
+    };
+
     StringRef containerType = mc.kind == MCK_Category ? "category" : "class";
     warn("method '" + methPrefix + methodName.val() +
          "' has conflicting definitions:\n>>> defined in category " +
-         newCatName + " from " + toString(containerIsec->getFile()) +
+         newCatName + " from " + formatObjAndSrcFileName(containerIsec) +
          "\n>>> defined in " + containerType + " " + containerName + " from " +
-         toString(mc.isec->getFile()));
+         formatObjAndSrcFileName(mc.isec));
   }
 }
 
diff --git a/lld/test/MachO/objc-category-conflicts.s b/lld/test/MachO/objc-category-conflicts.s
index 59a9ed50eb055..4ac8dc72c8668 100644
--- a/lld/test/MachO/objc-category-conflicts.s
+++ b/lld/test/MachO/objc-category-conflicts.s
@@ -3,6 +3,9 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -o %t/cat1.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -o %t/cat2.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -o %t/klass.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -g -o %t/cat1_w_sym.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -g -o %t/cat2_w_sym.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -g -o %t/klass_w_sym.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s --defsym MAKE_LOAD_METHOD=1 -o %t/cat1-with-load.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s --defsym MAKE_LOAD_METHOD=1 -o %t/cat2-with-load.o
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s --defsym MAKE_LOAD_METHOD=1 -o %t/klass-with-load.o
@@ -14,6 +17,14 @@
 # RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1.o \
 # RUN:   %t/cat2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT
 
+# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/klass_w_sym.o %t/cat1_w_sym.o %t/cat2_w_sym.o -o \
+# RUN:   /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS_W_SYM,CATCAT_W_SYM
+# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1_w_sym.o \
+# RUN:   %t/cat2_w_sym.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT_W_SYM
+
+# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \
+# RUN:   /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS,CATCAT
+
 ## Check that we don't emit spurious warnings around the +load method while
 ## still emitting the other warnings. Note that we have made separate
 ## `*-with-load.s` files for ease of comparison with ld64; ld64 will not warn
@@ -45,6 +56,24 @@
 # CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2{{.*}}.o
 # CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
 
+
+# CATCLS_W_SYM:      warning: method '+s1' has conflicting definitions:
+# CATCLS_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}})
+# CATCLS_W_SYM-NEXT: >>> defined in class Foo from {{.*}}klass_w_sym{{.*}}.o ({{.*}}klass.s{{.*}})
+
+# CATCLS_W_SYM:      warning: method '-m1' has conflicting definitions:
+# CATCLS_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}})
+# CATCLS_W_SYM-NEXT: >>> defined in class Foo from {{.*}}klass_w_sym{{.*}}.o ({{.*}}klass.s{{.*}})
+
+# CATCAT_W_SYM:      warning: method '+s2' has conflicting definitions:
+# CATCAT_W_SYM-NEXT: >>> defined in category Cat2 from {{.*}}cat2_w_sym{{.*}}.o ({{.*}}cat2.s{{.*}})
+# CATCAT_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}})
+
+# CATCAT_W_SYM:      warning: method '-m2' has conflicting definitions:
+# CATCAT_W_SYM-NEXT: >>> defined in category Cat2 from {{.*}}cat2_w_sym{{.*}}.o ({{.*}}cat2.s{{.*}})
+# CATCAT_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}})
+
+
 #--- cat1.s
 
 .include "objc-macros.s"
@@ -55,7 +84,7 @@
 ## +(void) s1;
 ## +(void) s2;
 ## @end
-## 
+##
 ## @implementation Foo(Cat1)
 ## -(void) m1 {}
 ## -(void) m2 {}
@@ -114,7 +143,7 @@ __OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1:
 ## -(void) m2;
 ## +(void) s2;
 ## @end
-## 
+##
 ## @implementation Foo(Cat2)
 ## -(void) m2 {}
 ## +(void) s2 {}

@kyulee-com kyulee-com requested review from int3 and kyulee-com February 1, 2024 00:43
@kyulee-com
Copy link
Contributor

This change is mostly useful only for thinLTO builds

I'm curious how it looks like with (full)lto builds where bitcodes are merged.

@alx32
Copy link
Contributor Author

alx32 commented Feb 1, 2024

I'm curious how it looks like with (full)lto builds where bitcodes are merged.

Good catch. In that case the file paths won't be valid. i.e it'll be something like:

defined in category TheCategory from /tmp/lto.tmp (RandomFile.mm)

However, I don't see an easy way to tell at this location if we're within the LTO scenario.

Copy link
Contributor

@thevinster thevinster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a minor nit.

However, I don't see an easy way to tell at this location if we're within the LTO scenario.

That's unfortunate. Spitting out some RandomFile might lead someone on a wild goose chase and I would prefer (if possible) to not even emit the source file in that scenario. In any case, this is already a quality improvement.

@kyulee-com
Copy link
Contributor

lgtm

@kyulee-com kyulee-com merged commit f0c8d88 into llvm:main Feb 1, 2024
carlosgalvezp pushed a commit to carlosgalvezp/llvm-project that referenced this pull request Feb 1, 2024
…category (llvm#80221)

When printing category conflicts in the ObjC category checker, also
print the source file name of the problematic categories. Currently we
only print the object file name. This change is mostly useful only for
thinLTO builds, where the object file name will be of form
999.arm64.lto.o and thus does not reveal any information about the
original source file.

---------

Co-authored-by: Alex Borcan <[email protected]>
agozillon pushed a commit to agozillon/llvm-project that referenced this pull request Feb 5, 2024
…category (llvm#80221)

When printing category conflicts in the ObjC category checker, also
print the source file name of the problematic categories. Currently we
only print the object file name. This change is mostly useful only for
thinLTO builds, where the object file name will be of form
999.arm64.lto.o and thus does not reveal any information about the
original source file.

---------

Co-authored-by: Alex Borcan <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants