Skip to content

Commit a76561f

Browse files
committed
[clang] Ignore GCC 11 [[malloc(x)]] attribute
Ignore the `[[malloc(x)]]` or `[[malloc(x, 1)]]` function attribute syntax added in [GCC 11][1] and print a warning instead of an error. Unlike `[[malloc]]` with no arguments (which is supported by Clang), GCC uses the one or two argument form to specify a deallocator for GCC's static analyzer. Code currently compiled with `[[malloc(x)]]` or `__attribute((malloc(x)))` fails with the following error: `'malloc' attribute takes no arguments`. [1]: https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;f=gcc/doc/extend.texi;h=dce6c58db87ebf7f4477bd3126228e73e4eeee97#patch6 Fixes: #51607 Partial-Bug: #53152
1 parent 451255b commit a76561f

File tree

7 files changed

+43
-5
lines changed

7 files changed

+43
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,11 @@ Bug Fixes to Compiler Builtins
289289
Bug Fixes to Attribute Support
290290
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
291291

292+
- Clang now emits a warning instead of an error when using the one or two
293+
argument form of GCC 11's ``__attribute__((malloc(deallocator)))``
294+
or ``__attribute__((malloc(deallocator, ptr-index)))``
295+
(`#51607 <https://github.com/llvm/llvm-project/issues/51607>`).
296+
292297
Bug Fixes to C++ Support
293298
^^^^^^^^^^^^^^^^^^^^^^^^
294299

clang/include/clang/Basic/Attr.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,8 @@ def IFunc : Attr, TargetSpecificAttr<TargetELF> {
16291629

16301630
def Restrict : InheritableAttr {
16311631
let Spellings = [Declspec<"restrict">, GCC<"malloc">];
1632+
let Args = [IdentifierArgument<"Deallocator", /*opt*/ 1>,
1633+
ParamIdxArgument<"DeallocatorPtrArgIndex", /*opt*/ 1>];
16321634
let Subjects = SubjectList<[Function]>;
16331635
let Documentation = [RestrictDocs];
16341636
}

clang/include/clang/Basic/AttrDocs.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4122,6 +4122,9 @@ def RestrictDocs : Documentation {
41224122
The ``malloc`` attribute indicates that the function acts like a system memory
41234123
allocation function, returning a pointer to allocated storage disjoint from the
41244124
storage for any other object accessible to the caller.
4125+
4126+
The form of ``malloc`` with one or two arguments (supported by GCC 11) is
4127+
currently ignored by Clang.
41254128
}];
41264129
}
41274130

clang/include/clang/Basic/DiagnosticCommonKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,10 @@ def warn_unknown_attribute_ignored : Warning<
177177
"unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
178178
def warn_attribute_ignored : Warning<"%0 attribute ignored">,
179179
InGroup<IgnoredAttributes>;
180+
def warn_multiarg_malloc_attribute_ignored: Warning<
181+
"'malloc' attribute ignored because"
182+
" Clang does not support the one/two argument form">,
183+
InGroup<IgnoredAttributes>;
180184
def err_keyword_not_supported_on_target : Error<
181185
"%0 is not supported on this target">;
182186
def err_use_of_tag_name_without_tag : Error<

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,13 +2064,27 @@ static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20642064

20652065
static void handleRestrictAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20662066
QualType ResultType = getFunctionOrMethodResultType(D);
2067-
if (ResultType->isAnyPointerType() || ResultType->isBlockPointerType()) {
2067+
if (!ResultType->isAnyPointerType() && !ResultType->isBlockPointerType()) {
2068+
S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
2069+
<< AL << getFunctionOrMethodResultSourceRange(D);
2070+
return;
2071+
}
2072+
2073+
if (getNumAttributeArgs(AL) == 0) {
20682074
D->addAttr(::new (S.Context) RestrictAttr(S.Context, AL));
20692075
return;
20702076
}
20712077

2072-
S.Diag(AL.getLoc(), diag::warn_attribute_return_pointers_only)
2073-
<< AL << getFunctionOrMethodResultSourceRange(D);
2078+
if (AL.getAttributeSpellingListIndex() == RestrictAttr::Declspec_restrict) {
2079+
// __declspec(restrict) accepts no arguments
2080+
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 0;
2081+
return;
2082+
}
2083+
2084+
// FIXME: GCC uses [[malloc(my_func)]] to specify a deallocator for the
2085+
// returned pointer, but this isn't currently supported in LLVM
2086+
// see https://github.com/llvm/llvm-project/issues/51607
2087+
S.Diag(AL.getLoc(), diag::warn_multiarg_malloc_attribute_ignored);
20742088
}
20752089

20762090
static void handleCPUSpecificAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

clang/test/Sema/attr-args.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
// RUN: %clang_cc1 -verify -Wunused -Wused-but-marked-unused -Wunused-parameter -fsyntax-only %s
1+
// RUN: %clang_cc1 -verify -Wunused -Wused-but-marked-unused -Wunused-parameter -fsyntax-only -fdeclspec %s
22
int a;
33

44
inline __attribute__((noreturn(a))) void *f1(void); // expected-error {{'noreturn' attribute takes no arguments}}
55
inline __attribute__((always_inline(a))) void *f2(void); // expected-error {{'always_inline' attribute takes no arguments}}
66
inline __attribute__((cdecl(a))) void *f3(void); // expected-error {{'cdecl' attribute takes no arguments}}
77
inline __attribute__((const(a))) void *f4(void); // expected-error {{'const' attribute takes no arguments}}
88
inline __attribute__((fastcall(a))) void *f5(void); // expected-error {{'fastcall' attribute takes no arguments}}
9-
inline __attribute__((malloc(a))) void *f5(void); // expected-error {{'malloc' attribute takes no arguments}}
9+
inline __declspec(restrict(a)) void *f6_a(void); // expected-error {{'restrict' attribute takes no arguments}}
10+
inline __attribute__((malloc(a, 1, a))) void *f6_b(void); // expected-error {{'malloc' attribute takes no more than 2 arguments}}
11+
inline __attribute__((malloc(a, 1))) void *f6_c(void); // expected-warning {{'malloc' attribute ignored because Clang does not support the one/two argument form}}
1012
inline __attribute__((nothrow(a))) void *f7(void); // expected-error {{'nothrow' attribute takes no arguments}}
1113
inline __attribute__((stdcall(a))) void *f8(void); // expected-error {{'stdcall' attribute takes no arguments}}
1214
inline __attribute__((used(a))) void *f9(void); // expected-error {{'used' attribute takes no arguments}}

clang/test/SemaCXX/attr-print.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ int v __attribute__((visibility("hidden")));
2828
// CHECK: char *PR24565() __attribute__((malloc))
2929
char *PR24565() __attribute__((__malloc__));
3030

31+
void my_cleanup_func(char *);
32+
33+
// using __attribute__(malloc()) with args is currently ignored by Clang
34+
// CHECK: char *PR52265_a()
35+
__attribute__((malloc(my_cleanup_func))) char *PR52265_a();
36+
// CHECK: char *PR52265_b()
37+
__attribute__((malloc(my_cleanup_func, 1))) char *PR52265_b();
38+
3139
// CHECK: class __attribute__((consumable("unknown"))) AttrTester1
3240
class __attribute__((consumable(unknown))) AttrTester1 {
3341
// CHECK: void callableWhen() __attribute__((callable_when("unconsumed", "consumed")));

0 commit comments

Comments
 (0)