Skip to content

Commit bc00209

Browse files
committed
Merge remote-tracking branch 'origin/main' into vplan-introduce-region-as-transform
2 parents f605097 + 75270e3 commit bc00209

38 files changed

+852
-362
lines changed

clang/bindings/python/clang/cindex.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2713,6 +2713,21 @@ def visitor(base, children):
27132713
conf.lib.clang_visitCXXBaseClasses(self, fields_visit_callback(visitor), bases)
27142714
return iter(bases)
27152715

2716+
def get_methods(self):
2717+
"""Return an iterator for accessing the methods of this type."""
2718+
2719+
def visitor(method, children):
2720+
assert method != conf.lib.clang_getNullCursor()
2721+
2722+
# Create reference to TU so it isn't GC'd before Cursor.
2723+
method._tu = self._tu
2724+
methods.append(method)
2725+
return 1 # continue
2726+
2727+
methods: list[Cursor] = []
2728+
conf.lib.clang_visitCXXMethods(self, fields_visit_callback(visitor), methods)
2729+
return iter(methods)
2730+
27162731
def get_exception_specification_kind(self):
27172732
"""
27182733
Return the kind of the exception specification; a value from
@@ -4020,6 +4035,7 @@ def set_property(self, property, value):
40204035
),
40214036
("clang_visitChildren", [Cursor, cursor_visit_callback, py_object], c_uint),
40224037
("clang_visitCXXBaseClasses", [Type, fields_visit_callback, py_object], c_uint),
4038+
("clang_visitCXXMethods", [Type, fields_visit_callback, py_object], c_uint),
40234039
("clang_Cursor_getNumArguments", [Cursor], c_int),
40244040
("clang_Cursor_getArgument", [Cursor, c_uint], Cursor),
40254041
("clang_Cursor_getNumTemplateArguments", [Cursor], c_int),

clang/bindings/python/tests/cindex/test_type.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,3 +559,21 @@ class Template : public A, public B, virtual C {
559559
self.assertEqual(bases[1].get_base_offsetof(cursor_type_decl), 96)
560560
self.assertTrue(bases[2].is_virtual_base())
561561
self.assertEqual(bases[2].get_base_offsetof(cursor_type_decl), 128)
562+
563+
def test_class_methods(self):
564+
source = """
565+
template <typename T>
566+
class Template { void Foo(); };
567+
typedef Template<int> instance;
568+
instance bar;
569+
"""
570+
tu = get_tu(source, lang="cpp", flags=["--target=x86_64-linux-gnu"])
571+
cursor = get_cursor(tu, "instance")
572+
cursor_type = cursor.underlying_typedef_type
573+
self.assertEqual(cursor.kind, CursorKind.TYPEDEF_DECL)
574+
methods = list(cursor_type.get_methods())
575+
self.assertEqual(len(methods), 4)
576+
self.assertEqual(methods[0].kind, CursorKind.CXX_METHOD)
577+
self.assertEqual(methods[1].kind, CursorKind.CONSTRUCTOR)
578+
self.assertEqual(methods[2].kind, CursorKind.CONSTRUCTOR)
579+
self.assertEqual(methods[3].kind, CursorKind.CONSTRUCTOR)

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ clang-format
349349

350350
libclang
351351
--------
352+
- Added ``clang_visitCXXMethods``, which allows visiting the methods
353+
of a class.
352354

353355
- Fixed a buffer overflow in ``CXString`` implementation. The fix may result in
354356
increased memory allocation.
@@ -388,6 +390,8 @@ Sanitizers
388390

389391
Python Binding Changes
390392
----------------------
393+
- Added ``Type.get_methods``, a binding for ``clang_visitCXXMethods``, which
394+
allows visiting the methods of a class.
391395

392396
OpenMP Support
393397
--------------

clang/include/clang-c/Index.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6628,6 +6628,28 @@ CINDEX_LINKAGE unsigned clang_visitCXXBaseClasses(CXType T,
66286628
CXFieldVisitor visitor,
66296629
CXClientData client_data);
66306630

6631+
/**
6632+
* Visit the class methods of a type.
6633+
*
6634+
* This function visits all the methods of the given cursor,
6635+
* invoking the given \p visitor function with the cursors of each
6636+
* visited method. The traversal may be ended prematurely, if
6637+
* the visitor returns \c CXFieldVisit_Break.
6638+
*
6639+
* \param T The record type whose field may be visited.
6640+
*
6641+
* \param visitor The visitor function that will be invoked for each
6642+
* field of \p T.
6643+
*
6644+
* \param client_data Pointer data supplied by the client, which will
6645+
* be passed to the visitor each time it is invoked.
6646+
*
6647+
* \returns A non-zero value if the traversal was terminated
6648+
* prematurely by the visitor returning \c CXFieldVisit_Break.
6649+
*/
6650+
CINDEX_LINKAGE unsigned clang_visitCXXMethods(CXType T, CXFieldVisitor visitor,
6651+
CXClientData client_data);
6652+
66316653
/**
66326654
* Describes the kind of binary operators.
66336655
*/

clang/tools/libclang/CIndexCXX.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,32 @@ unsigned clang_visitCXXBaseClasses(CXType PT, CXFieldVisitor visitor,
5454
return true;
5555
}
5656

57+
unsigned clang_visitCXXMethods(CXType PT, CXFieldVisitor visitor,
58+
CXClientData client_data) {
59+
CXCursor PC = clang_getTypeDeclaration(PT);
60+
if (clang_isInvalid(PC.kind))
61+
return false;
62+
const auto *RD =
63+
dyn_cast_if_present<CXXRecordDecl>(cxcursor::getCursorDecl(PC));
64+
if (!RD || RD->isInvalidDecl())
65+
return false;
66+
RD = RD->getDefinition();
67+
if (!RD || RD->isInvalidDecl())
68+
return false;
69+
70+
for (const auto *Method : RD->methods()) {
71+
// Callback to the client.
72+
switch (
73+
visitor(cxcursor::MakeCXCursor(Method, getCursorTU(PC)), client_data)) {
74+
case CXVisit_Break:
75+
return true;
76+
case CXVisit_Continue:
77+
break;
78+
}
79+
}
80+
return true;
81+
}
82+
5783
enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
5884
AccessSpecifier spec = AS_none;
5985

clang/tools/libclang/libclang.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ LLVM_20 {
435435
clang_getTypePrettyPrinted;
436436
clang_isBeforeInTranslationUnit;
437437
clang_visitCXXBaseClasses;
438+
clang_visitCXXMethods;
438439
};
439440

440441
# Example of how to add a new symbol version entry. If you do add a new symbol

lld/ELF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ struct Config {
229229
StringRef zCetReport = "none";
230230
StringRef zPauthReport = "none";
231231
StringRef zGcsReport = "none";
232+
StringRef zExecuteOnlyReport = "none";
232233
bool ltoBBAddrMap;
233234
llvm::StringRef ltoBasicBlockSections;
234235
std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;

lld/ELF/Driver.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,11 @@ static void checkOptions(Ctx &ctx) {
406406
ErrAlways(ctx) << "-z gcs only supported on AArch64";
407407
}
408408

409+
if (ctx.arg.emachine != EM_AARCH64 && ctx.arg.emachine != EM_ARM &&
410+
ctx.arg.zExecuteOnlyReport != "none")
411+
ErrAlways(ctx)
412+
<< "-z execute-only-report only supported on AArch64 and ARM";
413+
409414
if (ctx.arg.emachine != EM_PPC64) {
410415
if (ctx.arg.tocOptimize)
411416
ErrAlways(ctx) << "--toc-optimize is only supported on PowerPC64 targets";
@@ -1620,10 +1625,12 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
16201625
ErrAlways(ctx) << errPrefix << pat.takeError() << ": " << kv.first;
16211626
}
16221627

1623-
auto reports = {std::make_pair("bti-report", &ctx.arg.zBtiReport),
1624-
std::make_pair("cet-report", &ctx.arg.zCetReport),
1625-
std::make_pair("gcs-report", &ctx.arg.zGcsReport),
1626-
std::make_pair("pauth-report", &ctx.arg.zPauthReport)};
1628+
auto reports = {
1629+
std::make_pair("bti-report", &ctx.arg.zBtiReport),
1630+
std::make_pair("cet-report", &ctx.arg.zCetReport),
1631+
std::make_pair("execute-only-report", &ctx.arg.zExecuteOnlyReport),
1632+
std::make_pair("gcs-report", &ctx.arg.zGcsReport),
1633+
std::make_pair("pauth-report", &ctx.arg.zPauthReport)};
16271634
for (opt::Arg *arg : args.filtered(OPT_z)) {
16281635
std::pair<StringRef, StringRef> option =
16291636
StringRef(arg->getValue()).split('=');

lld/ELF/Writer.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ template <class ELFT> class Writer {
6464
void sortOrphanSections();
6565
void finalizeSections();
6666
void checkExecuteOnly();
67+
void checkExecuteOnlyReport();
6768
void setReservedSymbolSections();
6869

6970
SmallVector<std::unique_ptr<PhdrEntry>, 0> createPhdrs(Partition &part);
@@ -323,6 +324,7 @@ template <class ELFT> void Writer<ELFT>::run() {
323324
// finalizeSections does that.
324325
finalizeSections();
325326
checkExecuteOnly();
327+
checkExecuteOnlyReport();
326328

327329
// If --compressed-debug-sections is specified, compress .debug_* sections.
328330
// Do it right now because it changes the size of output sections.
@@ -2176,6 +2178,41 @@ template <class ELFT> void Writer<ELFT>::checkExecuteOnly() {
21762178
"data and code";
21772179
}
21782180

2181+
// Check which input sections of RX output sections don't have the
2182+
// SHF_AARCH64_PURECODE or SHF_ARM_PURECODE flag set.
2183+
template <class ELFT> void Writer<ELFT>::checkExecuteOnlyReport() {
2184+
if (ctx.arg.zExecuteOnlyReport == "none")
2185+
return;
2186+
2187+
auto reportUnless = [&](bool cond) -> ELFSyncStream {
2188+
if (cond)
2189+
return {ctx, DiagLevel::None};
2190+
if (ctx.arg.zExecuteOnlyReport == "error")
2191+
return {ctx, DiagLevel::Err};
2192+
if (ctx.arg.zExecuteOnlyReport == "warning")
2193+
return {ctx, DiagLevel::Warn};
2194+
return {ctx, DiagLevel::None};
2195+
};
2196+
2197+
uint64_t purecodeFlag =
2198+
ctx.arg.emachine == EM_AARCH64 ? SHF_AARCH64_PURECODE : SHF_ARM_PURECODE;
2199+
StringRef purecodeFlagName = ctx.arg.emachine == EM_AARCH64
2200+
? "SHF_AARCH64_PURECODE"
2201+
: "SHF_ARM_PURECODE";
2202+
SmallVector<InputSection *, 0> storage;
2203+
for (OutputSection *osec : ctx.outputSections) {
2204+
if (osec->getPhdrFlags() != (PF_R | PF_X))
2205+
continue;
2206+
for (InputSection *sec : getInputSections(*osec, storage)) {
2207+
if (isa<SyntheticSection>(sec))
2208+
continue;
2209+
reportUnless(sec->flags & purecodeFlag)
2210+
<< "-z execute-only-report: " << sec << " does not have "
2211+
<< purecodeFlagName << " flag set";
2212+
}
2213+
}
2214+
}
2215+
21792216
// The linker is expected to define SECNAME_start and SECNAME_end
21802217
// symbols for a few sections. This function defines them.
21812218
template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// REQUIRES: aarch64
2+
3+
// RUN: rm -rf %t && mkdir %t && cd %t
4+
// RUN: llvm-mc --triple=aarch64 --filetype=obj %s -o a.o
5+
6+
// RUN: ld.lld --defsym absolute=0xf0000000 -z execute-only-report=none --fatal-warnings a.o
7+
8+
// RUN: ld.lld --defsym absolute=0xf0000000 -z execute-only-report=warning a.o 2>&1 | \
9+
// RUN: FileCheck --check-prefix=WARNING %s
10+
// RUN: ld.lld --defsym absolute=0xf0000000 --execute-only -z execute-only-report=warning a.o 2>&1 | \
11+
// RUN: FileCheck --check-prefix=WARNING %s
12+
13+
// WARNING-NOT: warning: -z execute-only-report: a.o:(.text) does not have SHF_AARCH64_PURECODE flag set
14+
// WARNING-NOT: warning: -z execute-only-report: a.o:(.text.foo) does not have SHF_AARCH64_PURECODE flag set
15+
// WARNING: warning: -z execute-only-report: a.o:(.text.bar) does not have SHF_AARCH64_PURECODE flag set
16+
// WARNING-NOT: warning: -z execute-only-report: <internal>:({{.*}}) does not have SHF_AARCH64_PURECODE flag set
17+
18+
// RUN: not ld.lld --defsym absolute=0xf0000000 -z execute-only-report=error a.o 2>&1 | \
19+
// RUN: FileCheck --check-prefix=ERROR %s
20+
// RUN: not ld.lld --defsym absolute=0xf0000000 --execute-only -z execute-only-report=error a.o 2>&1 | \
21+
// RUN: FileCheck --check-prefix=ERROR %s
22+
23+
// ERROR-NOT: error: -z execute-only-report: a.o:(.text) does not have SHF_AARCH64_PURECODE flag set
24+
// ERROR-NOT: error: -z execute-only-report: a.o:(.text.foo) does not have SHF_AARCH64_PURECODE flag set
25+
// ERROR: error: -z execute-only-report: a.o:(.text.bar) does not have SHF_AARCH64_PURECODE flag set
26+
// ERROR-NOT: error: -z execute-only-report: <internal>:({{.*}}) does not have SHF_AARCH64_PURECODE flag set
27+
28+
.section .text,"axy",@progbits,unique,0
29+
.globl _start
30+
_start:
31+
bl foo
32+
bl bar
33+
bl absolute
34+
ret
35+
36+
.section .text.foo,"axy",@progbits,unique,0
37+
.globl foo
38+
foo:
39+
ret
40+
41+
.section .text.bar,"ax",@progbits,unique,0
42+
.globl bar
43+
bar:
44+
ret
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// REQUIRES: arm
2+
3+
// RUN: rm -rf %t && mkdir %t && cd %t
4+
// RUN: llvm-mc --triple=armv7 --filetype=obj %s -o a.o
5+
6+
// RUN: ld.lld --defsym absolute=0xf0000000 -z execute-only-report=none --fatal-warnings a.o
7+
8+
// RUN: ld.lld --defsym absolute=0xf0000000 -z execute-only-report=warning a.o 2>&1 | \
9+
// RUN: FileCheck --check-prefix=WARNING %s
10+
11+
// WARNING-NOT: warning: -z execute-only-report: a.o:(.text) does not have SHF_ARM_PURECODE flag set
12+
// WARNING-NOT: warning: -z execute-only-report: a.o:(.text.foo) does not have SHF_ARM_PURECODE flag set
13+
// WARNING: warning: -z execute-only-report: a.o:(.text.bar) does not have SHF_ARM_PURECODE flag set
14+
// WARNING-NOT: warning: -z execute-only-report: <internal>:({{.*}}) does not have SHF_ARM_PURECODE flag set
15+
16+
// RUN: not ld.lld --defsym absolute=0xf0000000 -z execute-only-report=error a.o 2>&1 | \
17+
// RUN: FileCheck --check-prefix=ERROR %s
18+
19+
// ERROR-NOT: error: -z execute-only-report: a.o:(.text) does not have SHF_ARM_PURECODE flag set
20+
// ERROR-NOT: error: -z execute-only-report: a.o:(.text.foo) does not have SHF_ARM_PURECODE flag set
21+
// ERROR: error: -z execute-only-report: a.o:(.text.bar) does not have SHF_ARM_PURECODE flag set
22+
// ERROR-NOT: error: -z execute-only-report: <internal>:({{.*}}) does not have SHF_ARM_PURECODE flag set
23+
24+
.section .text,"axy",%progbits,unique,0
25+
.globl _start
26+
_start:
27+
bl foo
28+
bl bar
29+
bl absolute
30+
bx lr
31+
32+
.section .text.foo,"axy",%progbits,unique,0
33+
.globl foo
34+
foo:
35+
bx lr
36+
37+
.section .text.bar,"ax",%progbits,unique,0
38+
.globl bar
39+
bar:
40+
bx lr

lld/test/ELF/target-specific-options.s

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,15 @@
1313
# RUN: not ld.lld %t --toc-optimize -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR-TOC
1414
# ERR-TOC: error: --toc-optimize is only supported on PowerPC64 targets
1515

16+
# RUN: not ld.lld %t -z execute-only-report=warning -o /dev/null 2>&1 | \
17+
# RUN: FileCheck %s --check-prefix=ERR-EXECUTE-ONLY
18+
# RUN: not ld.lld %t -z execute-only-report=error -o /dev/null 2>&1 | \
19+
# RUN: FileCheck %s --check-prefix=ERR-EXECUTE-ONLY
20+
# ERR-EXECUTE-ONLY: error: -z execute-only-report only supported on AArch64 and ARM
21+
22+
# RUN: not ld.lld %t -z execute-only-report=foo -o /dev/null 2>&1 | \
23+
# RUN: FileCheck %s --check-prefix=ERR-EXECUTE-ONLY-INVALID
24+
# ERR-EXECUTE-ONLY-INVALID: error: unknown -z execute-only-report= value: foo
25+
1626
.globl _start
1727
_start:

llvm/include/llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -646,14 +646,13 @@ void SampleProfileLoaderBaseImpl<BT>::findEquivalenceClasses(FunctionT &F) {
646646
BasicBlockT *BB1 = &BB;
647647

648648
// Compute BB1's equivalence class once.
649-
if (EquivalenceClass.count(BB1)) {
649+
// By default, blocks are in their own equivalence class.
650+
auto [It, Inserted] = EquivalenceClass.try_emplace(BB1, BB1);
651+
if (!Inserted) {
650652
LLVM_DEBUG(printBlockEquivalence(dbgs(), BB1));
651653
continue;
652654
}
653655

654-
// By default, blocks are in their own equivalence class.
655-
EquivalenceClass[BB1] = BB1;
656-
657656
// Traverse all the blocks dominated by BB1. We are looking for
658657
// every basic block BB2 such that:
659658
//

0 commit comments

Comments
 (0)