Skip to content
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

[libclang] Add API to query more information about base classes. #120300

Merged
merged 1 commit into from
Jan 14, 2025

Conversation

efriedma-quic
Copy link
Collaborator

The first API is clang_visitCXXBaseClasses: this allows visiting the base classes without going through the generic child visitor (which is awkward, and doesn't work for template instantiations).

The second API is clang_getOffsetOfBase; this allows computing the offset of a base in the class layout, the same way clang_Cursor_getOffsetOfField computes the offset of a field.

Also, add a Python binding for the existing function clang_isVirtualBase.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:as-a-library libclang and C++ API labels Dec 17, 2024
@llvmbot
Copy link
Member

llvmbot commented Dec 17, 2024

@llvm/pr-subscribers-clang

Author: Eli Friedman (efriedma-quic)

Changes

The first API is clang_visitCXXBaseClasses: this allows visiting the base classes without going through the generic child visitor (which is awkward, and doesn't work for template instantiations).

The second API is clang_getOffsetOfBase; this allows computing the offset of a base in the class layout, the same way clang_Cursor_getOffsetOfField computes the offset of a field.

Also, add a Python binding for the existing function clang_isVirtualBase.


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

6 Files Affected:

  • (modified) clang/bindings/python/clang/cindex.py (+25)
  • (modified) clang/bindings/python/tests/cindex/test_type.py (+26)
  • (modified) clang/include/clang-c/Index.h (+29)
  • (modified) clang/tools/libclang/CIndexCXX.cpp (+27)
  • (modified) clang/tools/libclang/CXType.cpp (+34)
  • (modified) clang/tools/libclang/libclang.map (+2)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index f8a20a1e224724..6e26eca9ce0a01 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -2123,6 +2123,14 @@ def get_field_offsetof(self):
         """Returns the offsetof the FIELD_DECL pointed by this Cursor."""
         return conf.lib.clang_Cursor_getOffsetOfField(self)  # type: ignore [no-any-return]
 
+    def get_base_offsetof(self, parent):
+        """Returns the offsetof the CXX_BASE_SPECIFIER pointed by this Cursor."""
+        return conf.lib.clang_getOffsetOfBase(parent, self)  # type: ignore [no-any-return]
+
+    def is_virtual_base(self):
+        """Returns whether the CXX_BASE_SPECIFIER pointed by this Cursor is virtual."""
+        return conf.lib.clang_isVirtualBase(self)  # type: ignore [no-any-return]
+
     def is_anonymous(self):
         """
         Check if the record is anonymous.
@@ -2663,6 +2671,21 @@ def visitor(field, children):
         conf.lib.clang_Type_visitFields(self, fields_visit_callback(visitor), fields)
         return iter(fields)
 
+    def get_bases(self):
+        """Return an iterator for accessing the base classes of this type."""
+
+        def visitor(field, children):
+            assert field != conf.lib.clang_getNullCursor()
+
+            # Create reference to TU so it isn't GC'd before Cursor.
+            field._tu = self._tu
+            fields.append(field)
+            return 1  # continue
+
+        fields: list[Cursor] = []
+        conf.lib.clang_visitCXXBaseClasses(self, fields_visit_callback(visitor), fields)
+        return iter(fields)
+
     def get_exception_specification_kind(self):
         """
         Return the kind of the exception specification; a value from
@@ -3844,6 +3867,7 @@ def write_main_file_to_stdout(self):
     ("clang_getNumDiagnosticsInSet", [c_object_p], c_uint),
     ("clang_getNumElements", [Type], c_longlong),
     ("clang_getNumOverloadedDecls", [Cursor], c_uint),
+    ("clang_getOffsetOfBase", [Cursor, Cursor], c_longlong),
     ("clang_getOverloadedDecl", [Cursor, c_uint], Cursor),
     ("clang_getPointeeType", [Type], Type),
     ("clang_getRange", [SourceLocation, SourceLocation], SourceRange),
@@ -3895,6 +3919,7 @@ def write_main_file_to_stdout(self):
         [TranslationUnit, SourceRange, POINTER(POINTER(Token)), POINTER(c_uint)],
     ),
     ("clang_visitChildren", [Cursor, cursor_visit_callback, py_object], c_uint),
+    ("clang_visitCXXBaseClasses", [Type, fields_visit_callback, py_object], c_uint),
     ("clang_Cursor_getNumArguments", [Cursor], c_int),
     ("clang_Cursor_getArgument", [Cursor, c_uint], Cursor),
     ("clang_Cursor_getNumTemplateArguments", [Cursor], c_int),
diff --git a/clang/bindings/python/tests/cindex/test_type.py b/clang/bindings/python/tests/cindex/test_type.py
index ce05fdb1a1ebc0..76497bdcf9f43f 100644
--- a/clang/bindings/python/tests/cindex/test_type.py
+++ b/clang/bindings/python/tests/cindex/test_type.py
@@ -1,4 +1,5 @@
 import os
+import clang.cindex
 
 from clang.cindex import Config, CursorKind, RefQualifierKind, TranslationUnit, TypeKind
 
@@ -514,3 +515,28 @@ class Template {
         # Variable without a template argument.
         cursor = get_cursor(tu, "bar")
         self.assertEqual(cursor.get_num_template_arguments(), -1)
+
+    def test_base_classes(self):
+        source = """
+        class A { int a; };
+        class B { int b; };
+        class C { int c; };
+        template <typename T>
+        class Template : public A, public B, virtual C {
+        };
+        Template<int> instance;
+        int bar;
+        """
+        tu = get_tu(source, lang="cpp")
+        cursor = get_cursor(tu, "instance")
+        cursor_type = cursor.type
+        cursor_type_decl = cursor_type.get_declaration()
+        self.assertEqual(cursor.kind, CursorKind.VAR_DECL)
+        bases = list(cursor_type.get_bases())
+        self.assertEqual(len(bases), 3)
+        self.assertFalse(bases[0].is_virtual_base())
+        self.assertEqual(bases[0].get_base_offsetof(cursor_type_decl), 64)
+        self.assertFalse(bases[1].is_virtual_base())
+        self.assertEqual(bases[1].get_base_offsetof(cursor_type_decl), 96)
+        self.assertTrue(bases[2].is_virtual_base())
+        self.assertEqual(bases[2].get_base_offsetof(cursor_type_decl), 128)
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 0c5ac80772e2b9..6ee4043efc9112 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -3731,6 +3731,12 @@ CINDEX_LINKAGE enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T);
  */
 CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor);
 
+/**
+ * Returns the offset in bits of a CX_CXXBaseSpecifier relative to the parent
+ * class.
+ */
+CINDEX_LINKAGE long long clang_getOffsetOfBase(CXCursor Parent, CXCursor Base);
+
 /**
  * Represents the C++ access control level to a base class for a
  * cursor with kind CX_CXXBaseSpecifier.
@@ -6600,6 +6606,29 @@ typedef enum CXVisitorResult (*CXFieldVisitor)(CXCursor C,
 CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T, CXFieldVisitor visitor,
                                                CXClientData client_data);
 
+/**
+ * Visit the base classes of a type.
+ *
+ * This function visits all the direct base classes of a the given cursor,
+ * invoking the given \p visitor function with the cursors of each
+ * visited base. The traversal may be ended prematurely, if
+ * the visitor returns \c CXFieldVisit_Break.
+ *
+ * \param T the record type whose field may be visited.
+ *
+ * \param visitor the visitor function that will be invoked for each
+ * field of \p T.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the visitor each time it is invoked.
+ *
+ * \returns a non-zero value if the traversal was terminated
+ * prematurely by the visitor returning \c CXFieldVisit_Break.
+ */
+CINDEX_LINKAGE unsigned clang_visitCXXBaseClasses(CXType T,
+                                                  CXFieldVisitor visitor,
+                                                  CXClientData client_data);
+
 /**
  * Describes the kind of binary operators.
  */
diff --git a/clang/tools/libclang/CIndexCXX.cpp b/clang/tools/libclang/CIndexCXX.cpp
index ea6f97d39644e1..16f82c9bdb29a5 100644
--- a/clang/tools/libclang/CIndexCXX.cpp
+++ b/clang/tools/libclang/CIndexCXX.cpp
@@ -27,6 +27,33 @@ unsigned clang_isVirtualBase(CXCursor C) {
   return B->isVirtual();
 }
 
+unsigned clang_visitCXXBaseClasses(CXType PT, CXFieldVisitor visitor,
+                                   CXClientData client_data) {
+  CXCursor PC = clang_getTypeDeclaration(PT);
+  if (clang_isInvalid(PC.kind))
+    return false;
+  const CXXRecordDecl *RD =
+      dyn_cast_or_null<CXXRecordDecl>(cxcursor::getCursorDecl(PC));
+  if (!RD || RD->isInvalidDecl())
+    return false;
+  RD = RD->getDefinition();
+  if (!RD || RD->isInvalidDecl())
+    return false;
+
+  for (auto &Base : RD->bases()) {
+    // Callback to the client.
+    switch (
+        visitor(cxcursor::MakeCursorCXXBaseSpecifier(&Base, getCursorTU(PC)),
+                client_data)) {
+    case CXVisit_Break:
+      return true;
+    case CXVisit_Continue:
+      break;
+    }
+  }
+  return true;
+}
+
 enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
   AccessSpecifier spec = AS_none;
 
diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp
index b4df12405cf356..da04e041bee455 100644
--- a/clang/tools/libclang/CXType.cpp
+++ b/clang/tools/libclang/CXType.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/Frontend/ASTUnit.h"
@@ -1094,6 +1095,39 @@ long long clang_Cursor_getOffsetOfField(CXCursor C) {
   return -1;
 }
 
+long long clang_getOffsetOfBase(CXCursor Parent, CXCursor Base) {
+  if (Base.kind != CXCursor_CXXBaseSpecifier)
+    return -1;
+
+  if (!clang_isDeclaration(Parent.kind))
+    return -1;
+
+  // we need to validate the parent type
+  CXType PT = clang_getCursorType(Parent);
+  long long Error = validateFieldParentType(Parent, PT);
+  if (Error < 0)
+    return Error;
+
+  const CXXRecordDecl *ParentRD =
+      dyn_cast<CXXRecordDecl>(cxcursor::getCursorDecl(Parent));
+  if (!ParentRD)
+    return -1;
+
+  ASTContext &Ctx = cxcursor::getCursorContext(Base);
+  const CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(Base);
+  if (ParentRD->bases_begin() > B || ParentRD->bases_end() <= B)
+    return -1;
+
+  const CXXRecordDecl *BaseRD = B->getType()->getAsCXXRecordDecl();
+  if (!BaseRD)
+    return -1;
+
+  const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(ParentRD);
+  if (B->isVirtual())
+    return Ctx.toBits(Layout.getVBaseClassOffset(BaseRD));
+  return Ctx.toBits(Layout.getBaseClassOffset(BaseRD));
+}
+
 enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) {
   QualType QT = GetQualType(T);
   if (QT.isNull())
diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map
index 25d8ba57d32514..09e6a5f8d3a33b 100644
--- a/clang/tools/libclang/libclang.map
+++ b/clang/tools/libclang/libclang.map
@@ -437,6 +437,8 @@ LLVM_19 {
 LLVM_20 {
   global:
     clang_isBeforeInTranslationUnit;
+    clang_getOffsetOfBase;
+    clang_visitCXXBaseClasses;
 };
 
 # Example of how to add a new symbol version entry.  If you do add a new symbol

@efriedma-quic efriedma-quic changed the title [cindex] Add API to query more information about base classes. [libclang] Add API to query more information about base classes. Dec 18, 2024
Copy link
Contributor

@DeinAlptraum DeinAlptraum left a comment

Choose a reason for hiding this comment

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

I'm only familiar with the Python-side of the bindings, so only reviewed those. Minor comments, otherwise LGTM!

@trelau
Copy link
Contributor

trelau commented Jan 2, 2025

Just referencing #121502 since this PR seem somewhat related (making it easier to iterate over things and pointed out it doesn't work for template instantiations, which might be the underlying problem I encountered).

I'd like to keep using libclang (and its Python bindings), so if there is a new API that could be added to libclang or a modification somewhere that is obvious, let me know and I'll see if I can make an attempt at it.

@trelau
Copy link
Contributor

trelau commented Jan 5, 2025

For what it's worth, to get around my issue in #121502 I followed your same pattern here and added a get_methods() function to Python (and a new libclang function clang_visitCXXMethods) to access the class methods.

Looking at CXXRecordDecl, perhaps the following might all be useful to add to the libclang API (including Python):

  • methods()
  • fields()
  • ctors()?
  • friends()?

For my purposes of parsing C++ headers and generating Python bindings via pybind11, this bases PR plus adding the get_methods() function would make things much easier (ctors and friends seem like more "nice to have" and ctors seem to come through in "methods" anyway and can be determined by the cursor kind property).

Adding get_methods was basically copy/pasting your work (see libclang function here).

I'll open a PR for the get_methods() addition (and maybe I'll try the others if they work as I imagine them to).

@efriedma-quic
Copy link
Collaborator Author

I think the relevant code that prevents visiting template instantiations is CursorVisitor::VisitClassTemplateSpecializationDecl. It intentionally skips implicit template instantiations, I guess because of the origin of the API, which was focused around code written by the user.

  • methods()

It might be a little weird to see uninstantiated methods in some cases... but this probably makes sense.

  • fields()

get_fields() already exists.

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

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

No idea what is going on with the python, but only 1 possible nit in the C++

if (clang_isInvalid(PC.kind))
return false;
const CXXRecordDecl *RD =
dyn_cast_or_null<CXXRecordDecl>(cxcursor::getCursorDecl(PC));
Copy link
Collaborator

Choose a reason for hiding this comment

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

are we supposed to be using the if_present versions or not?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yup, the or_null variants are deprecated in favor of the is_present ones.

if (clang_isInvalid(PC.kind))
return false;
const CXXRecordDecl *RD =
dyn_cast_or_null<CXXRecordDecl>(cxcursor::getCursorDecl(PC));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yup, the or_null variants are deprecated in favor of the is_present ones.

@efriedma-quic efriedma-quic force-pushed the base-class-cindex branch 2 times, most recently from 0d4bcf6 to ff0f4b5 Compare January 10, 2025 23:29
The first API is clang_visitCXXBaseClasses: this allows visiting the
base classes without going through the generic child visitor (which is
awkward, and doesn't work for template instantiations).

The second API is clang_getOffsetOfBase; this allows computing the
offset of a base in the class layout, the same way
clang_Cursor_getOffsetOfField compues the offset of a field.

Also, add a Python binding for the existing function
clang_isVirtualBase.
@efriedma-quic
Copy link
Collaborator Author

Addressed review comments

Copy link
Contributor

@DeinAlptraum DeinAlptraum left a comment

Choose a reason for hiding this comment

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

Re Python: LGTM!

On a sidenote just fyi, there's no need to amend & forcepush when you adress review comments. I know the contributor guide says something about how you should have only a single commit when submitting a patch, but that goes only for the initial thing (I got confused by this at the start). We squash on merge anyways.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

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

LGTM!

@efriedma-quic efriedma-quic merged commit 1682dee into llvm:main Jan 14, 2025
11 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 14, 2025

LLVM Buildbot has detected a new failure on builder clang-armv8-quick running on linaro-clang-armv8-quick while building clang at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/154/builds/10273

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
FAIL: test_base_classes


@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 14, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-libc-amdgpu-runtime running on omp-vega20-1 while building clang at step 7 "Add check check-offload".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/73/builds/11714

Here is the relevant piece of the build log for the reference
Step 7 (Add check check-offload) failure: test (failure)
******************** TEST 'libomptarget :: amdgcn-amd-amdhsa :: offloading/pgo1.c' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/clang -fopenmp    -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src  -nogpulib -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib  -fopenmp-targets=amdgcn-amd-amdhsa /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/offloading/pgo1.c -o /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/offloading/Output/pgo1.c.tmp -Xoffload-linker -lc -Xoffload-linker -lm /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib/libomptarget.devicertl.a -fprofile-instr-generate      -Xclang "-fprofile-instrument=clang"
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/clang -fopenmp -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -nogpulib -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -fopenmp-targets=amdgcn-amd-amdhsa /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/offloading/pgo1.c -o /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/offloading/Output/pgo1.c.tmp -Xoffload-linker -lc -Xoffload-linker -lm /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib/libomptarget.devicertl.a -fprofile-instr-generate -Xclang -fprofile-instrument=clang
# RUN: at line 3
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/offloading/Output/pgo1.c.tmp 2>&1 | /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/offloading/pgo1.c      --check-prefix="CLANG-PGO"
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/offloading/Output/pgo1.c.tmp
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/offloading/pgo1.c --check-prefix=CLANG-PGO
# .---command stderr------------
# | /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/offloading/pgo1.c:32:20: error: CLANG-PGO-NEXT: expected string not found in input
# | // CLANG-PGO-NEXT: [ 0 11 20 ]
# |                    ^
# | <stdin>:3:28: note: scanning from here
# | ======== Counters =========
# |                            ^
# | <stdin>:4:1: note: possible intended match here
# | [ 0 12 20 ]
# | ^
# | 
# | Input file: <stdin>
# | Check file: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/offloading/pgo1.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |            1: ======= GPU Profile ======= 
# |            2: Target: amdgcn-amd-amdhsa 
# |            3: ======== Counters ========= 
# | next:32'0                                X error: no match found
# |            4: [ 0 12 20 ] 
# | next:32'0     ~~~~~~~~~~~~
# | next:32'1     ?            possible intended match
# |            5: [ 10 ] 
# | next:32'0     ~~~~~~~
# |            6: [ 20 ] 
# | next:32'0     ~~~~~~~
# |            7: ========== Data =========== 
# | next:32'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            8: { 9515997471539760012 4749112401 0xffffffffffffffd8 0x0 0x0 0x0 3 [...] 0 } 
# | next:32'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            9: { 3666282617048535130 24 0xffffffffffffffb0 0x0 0x0 0x0 1 [...] 0 } 
# | next:32'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# |            .
# |            .
# |            .
...

@efriedma-quic
Copy link
Collaborator Author

The 32-bit Arm failures are fixed by 7aec7ca . The other failures appear to be unrelated.

@efriedma-quic efriedma-quic deleted the base-class-cindex branch January 14, 2025 23:58
Endilll added a commit that referenced this pull request Mar 1, 2025
Inspired by #120300, add a new
API `clang_visitCXXMethods` to libclang (and the Python bindings) which
allows iterating over the class methods of a type.

---------

Co-authored-by: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Mar 1, 2025
…3539)

Inspired by llvm/llvm-project#120300, add a new
API `clang_visitCXXMethods` to libclang (and the Python bindings) which
allows iterating over the class methods of a type.

---------

Co-authored-by: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com>
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:as-a-library libclang and C++ API clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants