Skip to content

Commit 692c9b2

Browse files
authored
[clang] Support member function poiners in Decl::getFunctionType() (#125077)
This seems consistent with the documentation, which claims it: ``` /// Looks through the Decl's underlying type to extract a FunctionType /// when possible. Will return null if the type underlying the Decl does not /// have a FunctionType. const FunctionType *getFunctionType(bool BlocksToo = true) const; ``` Note: This patch rewords this doc comment to clarify it includes various function pointer types. Without this, attaching attributes (which use `HasFunctionProto`) to member function pointers errors with: ``` error: '<attr>' only applies to non-K&R-style functions ``` ...which does not really make sense, since member functions are not K&C functions. With this change the Arm SME TypeAttrs work correctly on member function pointers. Note, however, that not all attributes work correctly when applied to function pointers or member function pointers. For example, `alloc_align` crashes when applied to a function pointer (on truck): https://godbolt.org/z/YvMhnhKfx (as it only expects a `FunctionDecl` not a `ParmVarDecl`). The same crash applies to member function pointers (for the same reason).
1 parent cc72042 commit 692c9b2

File tree

6 files changed

+60
-3
lines changed

6 files changed

+60
-3
lines changed

clang/include/clang/AST/DeclBase.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,8 +1257,11 @@ class alignas(8) Decl {
12571257
int64_t getID() const;
12581258

12591259
/// Looks through the Decl's underlying type to extract a FunctionType
1260-
/// when possible. Will return null if the type underlying the Decl does not
1261-
/// have a FunctionType.
1260+
/// when possible. This includes direct FunctionDecls, along with various
1261+
/// function types and typedefs. This includes function pointers/references,
1262+
/// member function pointers, and optionally if \p BlocksToo is set
1263+
/// Objective-C block pointers. Returns nullptr if the type underlying the
1264+
/// Decl does not have a FunctionType.
12621265
const FunctionType *getFunctionType(bool BlocksToo = true) const;
12631266

12641267
// Looks through the Decl's underlying type to determine if it's a

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ def OpenCLKernelFunction
198198
// inclusive nature of subject testing).
199199
def HasFunctionProto : SubsetSubject<DeclBase,
200200
[{(S->getFunctionType(true) != nullptr &&
201-
isa<FunctionProtoType>(S->getFunctionType())) ||
201+
isa<FunctionProtoType>(S->getFunctionType())) ||
202202
isa<ObjCMethodDecl>(S) ||
203203
isa<BlockDecl>(S)}],
204204
"non-K&R-style functions">;

clang/lib/AST/DeclBase.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,8 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
12031203

12041204
if (Ty->isFunctionPointerType())
12051205
Ty = Ty->castAs<PointerType>()->getPointeeType();
1206+
else if (Ty->isMemberFunctionPointerType())
1207+
Ty = Ty->castAs<MemberPointerType>()->getPointeeType();
12061208
else if (Ty->isFunctionReferenceType())
12071209
Ty = Ty->castAs<ReferenceType>()->getPointeeType();
12081210
else if (BlocksToo && Ty->isBlockPointerType())

clang/test/AST/attr-print-emit.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,8 @@ ANNOTATE_ATTR NONNULL_ATTR void fn_non_null_annotated_attr(int *) __attribute__(
9191

9292
[[gnu::nonnull(1)]] [[gnu::always_inline]] void cxx11_attr(int*) ANNOTATE_ATTR;
9393
// CHECK: {{\[\[}}gnu::nonnull(1)]] {{\[\[}}gnu::always_inline]] void cxx11_attr(int *) __attribute__((annotate("Annotated")));
94+
95+
struct Foo;
96+
97+
// CHECK: void as_member_fn_ptr(int *(Foo::*member)(int) __attribute__((alloc_size(1))));
98+
void as_member_fn_ptr(int* (Foo::*member)(int) __attribute__((alloc_size(1))));
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %clang_cc1 -triple aarch64 -target-feature +sme -target-feature +sme2 -x c++ -std=c++20 -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK
2+
3+
struct TestStruct;
4+
5+
__arm_new("za", "zt0") void test(TestStruct& TS,
6+
void (TestStruct::*streaming_member_ptr)() __arm_streaming,
7+
void (TestStruct::*streaming_compat_member)() __arm_streaming_compatible,
8+
void (TestStruct::*arm_in_member)() __arm_in("za", "zt0"),
9+
void (TestStruct::*arm_inout_member)() __arm_inout("za", "zt0"),
10+
void (TestStruct::*arm_preserves_member)() __arm_preserves("za", "zt0"),
11+
void (TestStruct::*arm_agnostic_member)() __arm_agnostic("sme_za_state")) {
12+
13+
// CHECK: call void %{{.*}} [[STREAMING_MEMBER_CALL_ATTRS:#.+]]
14+
(TS.*streaming_member_ptr)();
15+
16+
// CHECK: call void %{{.*}} [[STREAMING_COMPAT_MEMBER_CALL_ATTRS:#.+]]
17+
(TS.*streaming_compat_member)();
18+
19+
// CHECK: call void %{{.*}} [[ARM_IN_MEMBER_CALL_ATTRS:#.+]]
20+
(TS.*arm_in_member)();
21+
22+
// CHECK: call void %{{.*}} [[ARM_INOUT_MEMBER_CALL_ATTRS:#.+]]
23+
(TS.*arm_inout_member)();
24+
25+
// CHECK: call void %{{.*}} [[ARM_PRESERVES_MEMBER_CALL_ATTRS:#.+]]
26+
(TS.*arm_preserves_member)();
27+
28+
// CHECK: call void %{{.*}} [[ARM_AGNOSTIC_MEMBER_CALL_ATTRS:#.+]]
29+
(TS.*arm_agnostic_member)();
30+
}
31+
32+
// CHECK: attributes [[STREAMING_MEMBER_CALL_ATTRS]] = { "aarch64_pstate_sm_enabled" }
33+
// CHECK: attributes [[STREAMING_COMPAT_MEMBER_CALL_ATTRS]] = { "aarch64_pstate_sm_compatible" }
34+
// CHECK: attributes [[ARM_IN_MEMBER_CALL_ATTRS]] = { "aarch64_in_za" "aarch64_in_zt0" }
35+
// CHECK: attributes [[ARM_INOUT_MEMBER_CALL_ATTRS]] = { "aarch64_inout_za" "aarch64_inout_zt0" }
36+
// CHECK: attributes [[ARM_PRESERVES_MEMBER_CALL_ATTRS]] = { "aarch64_preserves_za" "aarch64_preserves_zt0" }
37+
// CHECK: attributes [[ARM_AGNOSTIC_MEMBER_CALL_ATTRS]] = { "aarch64_za_state_agnostic" }
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
2+
// RUN: %clang_cc1 %s
3+
4+
// FIXME: These should not crash!
5+
// XFAIL: *
6+
7+
void aa_fn_ptr(char* (*member)(char*) __attribute__((alloc_align(1))));
8+
9+
struct Test;
10+
void aa_member_fn_ptr(char* (Test::*member)(char*) __attribute__((alloc_align(1))));

0 commit comments

Comments
 (0)