Skip to content

[Clang] allow restrict qualifier for array types with pointer types as element types #120896

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

Merged
merged 37 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
295df25
[Clang] allow restrict qualifier for array types with pointer types a…
a-tarasyuk Dec 22, 2024
2165846
Merge branch 'main' into fix/92847
a-tarasyuk Jan 10, 2025
34d359e
Merge branch 'main' into fix/92847
a-tarasyuk Jan 16, 2025
0bd41e6
Merge branch 'main' into fix/92847
a-tarasyuk Jan 24, 2025
13ca652
Merge branch 'main' into fix/92847
a-tarasyuk Jan 28, 2025
d718e08
Merge branch 'main' into fix/92847
a-tarasyuk Jan 28, 2025
4346935
Merge branch 'main' into fix/92847
a-tarasyuk Jan 31, 2025
9e8dcdb
add additional tests
a-tarasyuk Jan 31, 2025
1495465
Merge branch 'fix/92847' of https://github.com/a-tarasyuk/llvm-projec…
a-tarasyuk Jan 31, 2025
700d23e
Merge branch 'main' of https://github.com/llvm/llvm-project into fix/…
a-tarasyuk Jan 31, 2025
7c85906
adjust array handling for clearer inner type check
a-tarasyuk Feb 1, 2025
82a8cf1
Merge branch 'main' into fix/92847
a-tarasyuk Feb 3, 2025
2dd3d22
eliminate recursion in type qualification handling
a-tarasyuk Feb 4, 2025
67e045d
Merge branch 'main' of https://github.com/llvm/llvm-project into fix/…
a-tarasyuk Feb 4, 2025
ec17c32
Merge branch 'fix/92847' of https://github.com/a-tarasyuk/llvm-projec…
a-tarasyuk Feb 4, 2025
0f097e7
cleanup
a-tarasyuk Feb 4, 2025
152ca6d
Merge branch 'main' into fix/92847
a-tarasyuk Feb 4, 2025
10ed4c2
cleanup
a-tarasyuk Feb 5, 2025
62f4c33
add additional test case
a-tarasyuk Feb 5, 2025
90b92a5
Merge branch 'fix/92847' of https://github.com/a-tarasyuk/llvm-projec…
a-tarasyuk Feb 5, 2025
31c0d88
Merge branch 'main' of https://github.com/llvm/llvm-project into fix/…
a-tarasyuk Feb 7, 2025
2554ca7
Merge branch 'main' into fix/92847
a-tarasyuk Feb 8, 2025
f66627b
add additional diagnostics
a-tarasyuk Feb 11, 2025
78833ba
Merge branch 'fix/92847' of https://github.com/a-tarasyuk/llvm-projec…
a-tarasyuk Feb 11, 2025
a2b4193
Merge branch 'main' of https://github.com/llvm/llvm-project into fix/…
a-tarasyuk Feb 11, 2025
b3fbbbd
update diagnostic messages
a-tarasyuk Feb 11, 2025
417f3c9
Merge branch 'main' of https://github.com/llvm/llvm-project into fix/…
a-tarasyuk Feb 11, 2025
1bd2f01
update C2x diagnostic handling logic
a-tarasyuk Feb 11, 2025
e9fa671
Merge branch 'main' into fix/92847
a-tarasyuk Feb 12, 2025
33c24e3
Merge branch 'main' into fix/92847
a-tarasyuk Feb 12, 2025
707e807
Merge branch 'main' into fix/92847
a-tarasyuk Feb 12, 2025
88b2b07
cleanup duplicate error messages
a-tarasyuk Feb 12, 2025
edaaeb1
update test to remove useless errors
a-tarasyuk Feb 12, 2025
bc9e0de
change code styles
a-tarasyuk Feb 12, 2025
5891ded
Merge branch 'fix/92847' of https://github.com/a-tarasyuk/llvm-projec…
a-tarasyuk Feb 12, 2025
d7de475
Merge branch 'main' of https://github.com/llvm/llvm-project into fix/…
a-tarasyuk Feb 12, 2025
ebf1dea
Merge branch 'main' into fix/92847
a-tarasyuk Feb 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ C Language Changes

- Clang now allows an ``inline`` specifier on a typedef declaration of a
function type in Microsoft compatibility mode. #GH124869
- Clang now allows ``restrict`` qualifier for array types with pointer elements (#GH92847).

C2y Feature Support
^^^^^^^^^^^^^^^^^^^
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -7413,6 +7413,11 @@ def warn_c23_compat_utf8_string : Warning<
def note_cxx20_c23_compat_utf8_string_remove_u8 : Note<
"remove 'u8' prefix to avoid a change of behavior; "
"Clang encodes unprefixed narrow string literals as UTF-8">;
def warn_c23_compat_restrict_on_array_of_pointers : Warning<
"'restrict' qualifier on an array of pointers is incompatible with C standards before C23">,
InGroup<CPre23Compat>, DefaultIgnore;
def ext_restrict_on_array_of_pointers_c23 : Extension<
"'restrict' qualifier on an array of pointers is a C23 extension">, InGroup<C23>;
def err_array_init_different_type : Error<
"cannot initialize array %diff{of type $ with array of type $|"
"with different type of array}0,1">;
Expand Down
31 changes: 17 additions & 14 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1593,35 +1593,38 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
// object or incomplete types shall not be restrict-qualified."
if (Qs.hasRestrict()) {
unsigned DiagID = 0;
QualType ProblemTy;

if (T->isAnyPointerType() || T->isReferenceType() ||
T->isMemberPointerType()) {
QualType EltTy;
if (T->isObjCObjectPointerType())
EltTy = T;
else if (const MemberPointerType *PTy = T->getAs<MemberPointerType>())
QualType EltTy = Context.getBaseElementType(T);

if (EltTy->isAnyPointerType() || EltTy->isReferenceType() ||
EltTy->isMemberPointerType()) {

if (const auto *PTy = EltTy->getAs<MemberPointerType>())
EltTy = PTy->getPointeeType();
else
EltTy = T->getPointeeType();
EltTy = EltTy->getPointeeType();

// If we have a pointer or reference, the pointee must have an object
// incomplete type.
if (!EltTy->isIncompleteOrObjectType()) {
if (!EltTy->isIncompleteOrObjectType())
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
ProblemTy = EltTy;
}

} else if (!isDependentOrGNUAutoType(T)) {
// For an __auto_type variable, we may not have seen the initializer yet
// and so have no idea whether the underlying type is a pointer type or
// not.
DiagID = diag::err_typecheck_invalid_restrict_not_pointer;
ProblemTy = T;
EltTy = T;
}

Loc = DS ? DS->getRestrictSpecLoc() : Loc;
if (DiagID) {
Diag(DS ? DS->getRestrictSpecLoc() : Loc, DiagID) << ProblemTy;
Diag(Loc, DiagID) << EltTy;
Qs.removeRestrict();
} else {
if (T->isArrayType())
Diag(Loc, getLangOpts().C23
? diag::warn_c23_compat_restrict_on_array_of_pointers
: diag::ext_restrict_on_array_of_pointers_c23);
}
}

Expand Down
21 changes: 21 additions & 0 deletions clang/test/Sema/pre-c2x-restrict-qualifier.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s
// RUN: %clang_cc1 -std=c17 -fsyntax-only -pedantic -verify=pedantic,expected %s
// RUN: %clang_cc1 -std=c2x -fsyntax-only -Wpre-c2x-compat -verify=c2x-compat,expected %s

typedef int (*T1)[2];
restrict T1 t1;

typedef int *T2[2];
restrict T2 t2; // pedantic-warning {{'restrict' qualifier on an array of pointers is a C23 extension}} \
// c2x-compat-warning {{'restrict' qualifier on an array of pointers is incompatible with C standards before C23}}

typedef int *T3[2][2];
restrict T3 t3; // pedantic-warning {{'restrict' qualifier on an array of pointers is a C23 extension}} \
// c2x-compat-warning {{'restrict' qualifier on an array of pointers is incompatible with C standards before C23}}

typedef int (*t4)(); // pedantic-warning {{a function declaration without a prototype is deprecated in all versions of C}}
typedef t4 t5[2];
typedef t5 restrict t6; // // expected-error-re {{pointer to function type 'int {{\((void)?\)}}' may not be 'restrict' qualified}}

typedef int t7[2];
typedef t7 restrict t8; // expected-error {{restrict requires a pointer or reference ('t7' (aka 'int[2]') is invalid)}}
21 changes: 21 additions & 0 deletions clang/test/Sema/restrict-qualifier.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// RUN: %clang_cc1 -std=c2y -fsyntax-only -verify -pedantic %s

typedef int (*T1)[2];
restrict T1 t1;
static_assert(_Generic(typeof (t1), int (*restrict)[2] : 1, default : 0));

typedef int *T2[2];
restrict T2 t2;
static_assert(_Generic(typeof (t2), int *restrict[2] : 1, default : 0));

typedef int *T3[2][2];
restrict T3 t3;
static_assert(_Generic(typeof (t3), int *restrict[2][2] : 1, default : 0));
static_assert(_Generic(void(T3 restrict), void(int *restrict (*)[2]): 1, default: 0));

typedef int (*t4)();
typedef t4 t5[2];
typedef t5 restrict t6; // expected-error {{pointer to function type 'int (void)' may not be 'restrict' qualified}}

typedef int t7[2];
typedef t7 restrict t8; // expected-error {{restrict requires a pointer or reference ('t7' (aka 'int[2]')}}
10 changes: 5 additions & 5 deletions clang/test/Sema/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ typedef int (*T)[2];
restrict T x;

typedef int *S[2];
restrict S y; // expected-error {{restrict requires a pointer or reference ('S' (aka 'int *[2]') is invalid)}}


restrict S y; // expected-warning {{'restrict' qualifier on an array of pointers is a C23 extension}}

// int128_t is available.
int a(void) {
void a(void) {
__int128_t s;
__uint128_t t;
}

// but not a keyword
int b(void) {
void b(void) {
int __int128_t;
int __uint128_t;
}

// __int128 is a keyword
int c(void) {
__int128 i;
Expand Down