llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: QuietMisdreavus (QuietMisdreavus)

<details>
<summary>Changes</summary>

fixes rdar://137214218

When 'typedef struct' decls are encountered, the records are combined if the 
underlying type is either anonymous or has the same name as the typedef. Extend 
this behavior to also combine records when the underlying type has an 
underscored name that is equivalent to the typedef name when the leading 
underscores are removed.

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


2 Files Affected:

- (modified) clang/include/clang/ExtractAPI/ExtractAPIVisitor.h (+25-1) 
- (added) clang/test/ExtractAPI/typedef_underscore.c (+69) 


``````````diff
diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h 
b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
index aa86e4180671144..6442b234cd929f2 100644
--- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
+++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
@@ -1146,11 +1146,30 @@ bool 
ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
 
   StringRef Name = Decl->getName();
 
+  auto nameMatches = [&Name](TagDecl *TagDecl) {
+    StringRef TagName = TagDecl->getName();
+
+    if (TagName == Name)
+      return true;
+
+    // Also check whether the tag decl's name is the same as the typedef name
+    // with prefixed underscores
+    if (TagName.starts_with('_')) {
+      StringRef StrippedName =
+          TagName.drop_while([](char c) { return c == '_'; });
+
+      if (StrippedName == Name)
+        return true;
+    }
+
+    return false;
+  };
+
   // If the underlying type was defined as part of the typedef modify it's
   // fragments directly and pretend the typedef doesn't exist.
   if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) {
     if (TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition() &&
-        Decl->getName() == TagDecl->getName()) {
+        nameMatches(TagDecl)) {
       SmallString<128> TagUSR;
       index::generateUSRForDecl(TagDecl, TagUSR);
       if (auto *Record = API.findRecordForUSR(TagUSR)) {
@@ -1164,6 +1183,11 @@ bool 
ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
             .append(Name, DeclarationFragments::FragmentKind::Identifier)
             .appendSemicolon();
 
+        // Replace the name and subheading in case it's underscored so we can
+        // use the non-underscored version
+        Record->Name = Name;
+        Record->SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl);
+
         return true;
       }
     }
diff --git a/clang/test/ExtractAPI/typedef_underscore.c 
b/clang/test/ExtractAPI/typedef_underscore.c
new file mode 100644
index 000000000000000..a42046907b46de8
--- /dev/null
+++ b/clang/test/ExtractAPI/typedef_underscore.c
@@ -0,0 +1,69 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -extract-api --pretty-sgf 
--emit-sgf-symbol-labels-for-testing \
+// RUN:   --product-name=TypedefChain -triple arm64-apple-macosx -x c-header 
%s -o %t/typedefchain-c.symbols.json -verify
+// RUN: %clang_cc1 -extract-api --pretty-sgf 
--emit-sgf-symbol-labels-for-testing \
+// RUN:   --product-name=TypedefChain -triple arm64-apple-macosx -x c++-header 
%s -o %t/typedefchain-cxx.symbols.json -verify
+
+// RUN: FileCheck %s --input-file %t/typedefchain-c.symbols.json 
--check-prefix MYSTRUCT
+// RUN: FileCheck %s --input-file %t/typedefchain-cxx.symbols.json 
--check-prefix MYSTRUCT
+typedef struct _MyStruct { } MyStruct;
+
+// MYSTRUCT-LABEL: "!testLabel": "c:@S@_MyStruct"
+// MYSTRUCT:      "accessLevel": "public",
+// MYSTRUCT:      "declarationFragments": [
+// MYSTRUCT-NEXT:   {
+// MYSTRUCT-NEXT:     "kind": "keyword",
+// MYSTRUCT-NEXT:     "spelling": "typedef"
+// MYSTRUCT-NEXT:   },
+// MYSTRUCT-NEXT:   {
+// MYSTRUCT-NEXT:     "kind": "text",
+// MYSTRUCT-NEXT:     "spelling": " "
+// MYSTRUCT-NEXT:   },
+// MYSTRUCT-NEXT:   {
+// MYSTRUCT-NEXT:     "kind": "keyword",
+// MYSTRUCT-NEXT:     "spelling": "struct"
+// MYSTRUCT-NEXT:   },
+// MYSTRUCT-NEXT:   {
+// MYSTRUCT-NEXT:     "kind": "text",
+// MYSTRUCT-NEXT:     "spelling": " "
+// MYSTRUCT-NEXT:   },
+// MYSTRUCT-NEXT:   {
+// MYSTRUCT-NEXT:     "kind": "identifier",
+// MYSTRUCT-NEXT:     "spelling": "_MyStruct"
+// MYSTRUCT-NEXT:   },
+// MYSTRUCT-NEXT:   {
+// MYSTRUCT-NEXT:     "kind": "text",
+// MYSTRUCT-NEXT:     "spelling": " { ... } "
+// MYSTRUCT-NEXT:   },
+// MYSTRUCT-NEXT:   {
+// MYSTRUCT-NEXT:     "kind": "identifier",
+// MYSTRUCT-NEXT:     "spelling": "MyStruct"
+// MYSTRUCT-NEXT:   },
+// MYSTRUCT-NEXT:   {
+// MYSTRUCT-NEXT:     "kind": "text",
+// MYSTRUCT-NEXT:     "spelling": ";"
+// MYSTRUCT-NEXT:   }
+// MYSTRUCT-NEXT: ],
+// MYSTRUCT:      "kind": {
+// MYSTRUCT-NEXT:   "displayName": "Structure",
+// MYSTRUCT-NEXT:   "identifier": "c{{(\+\+)?}}.struct"
+// MYSTRUCT:           "names": {
+// MYSTRUCT-NEXT:        "navigator": [
+// MYSTRUCT-NEXT:          {
+// MYSTRUCT-NEXT:            "kind": "identifier",
+// MYSTRUCT-NEXT:            "spelling": "MyStruct"
+// MYSTRUCT-NEXT:          }
+// MYSTRUCT-NEXT:        ],
+// MYSTRUCT-NEXT:        "subHeading": [
+// MYSTRUCT-NEXT:          {
+// MYSTRUCT-NEXT:            "kind": "identifier",
+// MYSTRUCT-NEXT:            "spelling": "MyStruct"
+// MYSTRUCT-NEXT:          }
+// MYSTRUCT-NEXT:        ],
+// MYSTRUCT-NEXT:        "title": "MyStruct"
+// MYSTRUCT-NEXT:      },
+// MYSTRUCT:      "pathComponents": [
+// MYSTRUCT-NEXT:    "MyStruct"
+// MYSTRUCT-NEXT:  ]
+
+// expected-no-diagnostics

``````````

</details>


https://github.com/llvm/llvm-project/pull/125964
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to