Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,9 @@ class Qualifiers {
// to implicitly cast into the default address space.
(A == LangAS::Default &&
(B == LangAS::cuda_constant || B == LangAS::cuda_device ||
B == LangAS::cuda_shared));
B == LangAS::cuda_shared)) ||
// Otherwise, assume the default address space is compatible.
(A == LangAS::Default);
Copy link
Contributor

Choose a reason for hiding this comment

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

Default is kind of broken, at least for OpenCL. Should avoid attaching any behavior to it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I noted there's actually a case where OpenCL touches this for function pointers. I might just have the OpenCL language call a different version of this. Overall the other targets just allow any AS to decay to default and that's likely the behavior we want when not bound by OpenCL semantics.

Copy link
Contributor

Choose a reason for hiding this comment

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

@jhuber6, I agree with you, but you might want to check with @AnastasiaStulova.

We had a couple of lengthy discussions about re-using OpenCL attributes in SYCL mode (here and here), but if I recall it correctly the conclusion was that OpenCL attributes inherit OpenCL semantics in non-OpenCL modes as well. The solution for SYCL mode was adding new attributes (review).

@Naghasan, FYI.

Choose a reason for hiding this comment

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

that's likely the behavior we want when not bound by OpenCL semantics.

I kind of agree, but that's up to the target to tell if this makes sense IMO. My mental model of what Default means in the case of CUDA/HIP/SYCL/OpenMP is "the address of a variable maps to the flat address space of the target".

My understanding here is you want a bypass for target address spaces to decay into default. While I think this is desirable in general, this disregards potential target limitations. The one I have in mind is for SPIR/SPIR-V, the target address space for constant shouldn't be allowed to decay into Default. There is some related discussions here as well.

}

/// Returns true if the address space in these qualifiers is equal to or
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Misc/diag-overload-cand-ranges.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ void baz(__attribute__((opencl_private)) int *Data) {}
void fizz() {
int *Nop;
baz(Nop);
// CHECK: error: no matching function
// CHECK: :[[@LINE+1]]:53: note: {{.*}}: 'this' object is in address space '__private'


__attribute__((opencl_private)) static auto err = [&]() {};
err();
}
Expand Down
14 changes: 7 additions & 7 deletions clang/test/Sema/address_space_print_macro.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@ char *cmp(AS1 char *x, AS2 char *y) {

__attribute__((address_space(1))) char test_array[10];
void test3(void) {
extern void test3_helper(char *p); // expected-note{{passing argument to parameter 'p' here}}
test3_helper(test_array); // expected-error{{passing '__attribute__((address_space(1))) char *' to parameter of type 'char *' changes address space of pointer}}
extern void test3_helper(char *p);
test3_helper(test_array);
}

char AS2 *test4_array;
void test4(void) {
extern void test3_helper(char *p); // expected-note{{passing argument to parameter 'p' here}}
test3_helper(test4_array); // expected-error{{passing 'AS2 char *' to parameter of type 'char *' changes address space of pointer}}
extern void test3_helper(char *p);
test3_helper(test4_array);
}

void func(void) {
char AS1 *x;
char AS3 *x2;
AS5 *x3;
char *y;
y = x; // expected-error{{assigning 'AS1 char *' to 'char *' changes address space of pointer}}
y = x2; // expected-error{{assigning 'AS3 char *' to 'char *' changes address space of pointer}}
y = x3; // expected-error{{assigning '__attribute__((address_space(5))) char *' to 'char *' changes address space of pointer}}
y = x;
y = x2;
y = x3;
}

void multiple_attrs(AS_ND int *x) {
Expand Down
6 changes: 3 additions & 3 deletions clang/test/Sema/address_spaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ struct _st {

__attribute__((address_space(256))) void * * const base = 0;
void * get_0(void) {
return base[0]; // expected-error {{returning '__attribute__((address_space(256))) void *' from a function with result type 'void *' changes address space of pointer}}
return base[0];
}

__attribute__((address_space(1))) char test3_array[10];
void test3(void) {
extern void test3_helper(char *p); // expected-note {{passing argument to parameter 'p' here}}
test3_helper(test3_array); // expected-error {{changes address space of pointer}}
extern void test3_helper(char *p);
test3_helper(test3_array);
}

typedef void ft(void);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/conditional-expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ void foo(void) {
test0 ? adr2 : adr3; // expected-error{{conditional operator with the second and third operands of type ('__attribute__((address_space(2))) int *' and '__attribute__((address_space(3))) int *') which are pointers to non-overlapping address spaces}}

// Make sure address-space mask ends up in the result type
(test0 ? (test0 ? adr2 : adr2) : nonconst_int); // expected-error{{conditional operator with the second and third operands of type ('__attribute__((address_space(2))) int *' and 'int *') which are pointers to non-overlapping address spaces}}
(void)(test0 ? (test0 ? adr2 : adr2) : nonconst_int);
}

int Postgresql(void) {
Expand Down
5 changes: 2 additions & 3 deletions clang/test/Sema/wasm-refs-and-tables.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,8 @@ __externref_t func(__externref_t ref) {
static __externref_t lt2[0]; // expected-error {{WebAssembly table cannot be declared within a function}}
static __externref_t lt3[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are not allowed}}
static __externref_t(*lt4)[0]; // expected-error {{cannot form a pointer to a WebAssembly table}}
// conly-error@+2 {{cannot use WebAssembly table as a function parameter}}
// cpp-error@+1 {{no matching function for call to 'illegal_argument_1'}}
illegal_argument_1(table);

illegal_argument_1(table); // expected-error {{cannot use WebAssembly table as a function parameter}}
varargs(1, table); // expected-error {{cannot use WebAssembly table as a function parameter}}
table == 1; // expected-error {{invalid operands to binary expression ('__attribute__((address_space(1))) __externref_t[0]' and 'int')}}
1 >= table; // expected-error {{invalid operands to binary expression ('int' and '__attribute__((address_space(1))) __externref_t[0]')}}
Expand Down
38 changes: 18 additions & 20 deletions clang/test/SemaCXX/address-space-conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,30 +69,30 @@ void test_static_cast(void_ptr vp, void_ptr_1 vp1, void_ptr_2 vp2,
(void)static_cast<A_ptr_2>(vp2);

// Ill-formed upcasts
(void)static_cast<A_ptr>(bp1); // expected-error{{is not allowed}}
(void)static_cast<A_ptr>(bp2); // expected-error{{is not allowed}}
(void)static_cast<A_ptr>(bp1);
(void)static_cast<A_ptr>(bp2);
(void)static_cast<A_ptr_1>(bp); // expected-error{{is not allowed}}
(void)static_cast<A_ptr_1>(bp2); // expected-error{{is not allowed}}
(void)static_cast<A_ptr_2>(bp); // expected-error{{is not allowed}}
(void)static_cast<A_ptr_2>(bp1); // expected-error{{is not allowed}}

// Ill-formed downcasts
(void)static_cast<B_ptr>(ap1); // expected-error{{casts away qualifiers}}
(void)static_cast<B_ptr>(ap2); // expected-error{{casts away qualifiers}}
(void)static_cast<B_ptr>(ap1);
(void)static_cast<B_ptr>(ap2);
(void)static_cast<B_ptr_1>(ap); // expected-error{{casts away qualifiers}}
(void)static_cast<B_ptr_1>(ap2); // expected-error{{casts away qualifiers}}
(void)static_cast<B_ptr_2>(ap); // expected-error{{casts away qualifiers}}
(void)static_cast<B_ptr_2>(ap1); // expected-error{{casts away qualifiers}}

// Ill-formed cast to/from void
(void)static_cast<void_ptr>(ap1); // expected-error{{is not allowed}}
(void)static_cast<void_ptr>(ap2); // expected-error{{is not allowed}}
(void)static_cast<void_ptr>(ap1);
(void)static_cast<void_ptr>(ap2);
(void)static_cast<void_ptr_1>(ap); // expected-error{{is not allowed}}
(void)static_cast<void_ptr_1>(ap2); // expected-error{{is not allowed}}
(void)static_cast<void_ptr_2>(ap); // expected-error{{is not allowed}}
(void)static_cast<void_ptr_2>(ap1); // expected-error{{is not allowed}}
(void)static_cast<A_ptr>(vp1); // expected-error{{casts away qualifiers}}
(void)static_cast<A_ptr>(vp2); // expected-error{{casts away qualifiers}}
(void)static_cast<A_ptr>(vp1);
(void)static_cast<A_ptr>(vp2);
(void)static_cast<A_ptr_1>(vp); // expected-error{{casts away qualifiers}}
(void)static_cast<A_ptr_1>(vp2); // expected-error{{casts away qualifiers}}
(void)static_cast<A_ptr_2>(vp); // expected-error{{casts away qualifiers}}
Expand All @@ -112,16 +112,16 @@ void test_dynamic_cast(A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2,
(void)dynamic_cast<B_ptr_2>(ap2);

// Ill-formed upcasts
(void)dynamic_cast<A_ptr>(bp1); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<A_ptr>(bp2); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<A_ptr>(bp1);
(void)dynamic_cast<A_ptr>(bp2);
(void)dynamic_cast<A_ptr_1>(bp); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<A_ptr_1>(bp2); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<A_ptr_2>(bp); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<A_ptr_2>(bp1); // expected-error{{casts away qualifiers}}

// Ill-formed downcasts
(void)dynamic_cast<B_ptr>(ap1); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<B_ptr>(ap2); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<B_ptr>(ap1);
(void)dynamic_cast<B_ptr>(ap2);
(void)dynamic_cast<B_ptr_1>(ap); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<B_ptr_1>(ap2); // expected-error{{casts away qualifiers}}
(void)dynamic_cast<B_ptr_2>(ap); // expected-error{{casts away qualifiers}}
Expand All @@ -133,14 +133,14 @@ void test_reinterpret_cast(void_ptr vp, void_ptr_1 vp1, void_ptr_2 vp2,
B_ptr bp, B_ptr_1 bp1, B_ptr_2 bp2,
const void __attribute__((address_space(1))) * cvp1) {
// reinterpret_cast can't be used to cast to a different address space unless they are matching (i.e. overlapping).
(void)reinterpret_cast<A_ptr>(ap1); // expected-error{{reinterpret_cast from 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') to 'A_ptr' (aka 'A *') is not allowed}}
(void)reinterpret_cast<A_ptr>(ap2); // expected-error{{reinterpret_cast from 'A_ptr_2' (aka '__attribute__((address_space(2))) A *') to 'A_ptr' (aka 'A *') is not allowed}}
(void)reinterpret_cast<A_ptr>(ap1);
(void)reinterpret_cast<A_ptr>(ap2);
(void)reinterpret_cast<A_ptr>(bp);
(void)reinterpret_cast<A_ptr>(bp1); // expected-error{{reinterpret_cast from 'B_ptr_1' (aka '__attribute__((address_space(1))) B *') to 'A_ptr' (aka 'A *') is not allowed}}
(void)reinterpret_cast<A_ptr>(bp2); // expected-error{{reinterpret_cast from 'B_ptr_2' (aka '__attribute__((address_space(2))) B *') to 'A_ptr' (aka 'A *') is not allowed}}
(void)reinterpret_cast<A_ptr>(bp1);
(void)reinterpret_cast<A_ptr>(bp2);
(void)reinterpret_cast<A_ptr>(vp);
(void)reinterpret_cast<A_ptr>(vp1); // expected-error{{reinterpret_cast from 'void_ptr_1' (aka '__attribute__((address_space(1))) void *') to 'A_ptr' (aka 'A *') is not allowed}}
(void)reinterpret_cast<A_ptr>(vp2); // expected-error{{reinterpret_cast from 'void_ptr_2' (aka '__attribute__((address_space(2))) void *') to 'A_ptr' (aka 'A *') is not allowed}}
(void)reinterpret_cast<A_ptr>(vp1);
(void)reinterpret_cast<A_ptr>(vp2);
(void)reinterpret_cast<A_ptr_1>(ap); // expected-error{{reinterpret_cast from 'A_ptr' (aka 'A *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}}
(void)reinterpret_cast<A_ptr_1>(ap2); // expected-error{{reinterpret_cast from 'A_ptr_2' (aka '__attribute__((address_space(2))) A *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}}
(void)reinterpret_cast<A_ptr_1>(bp); // expected-error{{reinterpret_cast from 'B_ptr' (aka 'B *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}}
Expand Down Expand Up @@ -190,8 +190,6 @@ void test_implicit_conversion(void_ptr vp, void_ptr_1 vp1, void_ptr_2 vp2,
A_ptr_2 ap_A2 = bp2;

// Ill-formed conversions
void_ptr vpB = ap1; // expected-error{{cannot initialize a variable of type}}
void_ptr_1 vp_1B = ap2; // expected-error{{cannot initialize a variable of type}}
A_ptr ap_B = bp1; // expected-error{{cannot initialize a variable of type}}
A_ptr_1 ap_B1 = bp2; // expected-error{{cannot initialize a variable of type}}
}
14 changes: 4 additions & 10 deletions clang/test/SemaCXX/address-space-ctor.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
// RUN: %clang_cc1 %s -std=c++14 -triple=spir -verify -fsyntax-only
// RUN: %clang_cc1 %s -std=c++17 -triple=spir -verify -fsyntax-only

// expected-no-diagnostics

struct MyType {
MyType(int i) : i(i) {}
int i;
};

//expected-note@-5{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const MyType &' for 1st argument}}
//expected-note@-6{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'MyType &&' for 1st argument}}
//expected-note@-6{{candidate constructor ignored: cannot be used to construct an object in address space '__attribute__((address_space(10)))'}}
//expected-note@-8{{candidate constructor ignored: cannot be used to construct an object in address space '__attribute__((address_space(10)))'}}
//expected-note@-9{{candidate constructor ignored: cannot be used to construct an object in address space '__attribute__((address_space(10)))'}}
//expected-note@-9{{candidate constructor ignored: cannot be used to construct an object in address space '__attribute__((address_space(10)))'}}

// FIXME: We can't implicitly convert between address spaces yet.
MyType __attribute__((address_space(10))) m1 = 123; //expected-error{{no viable conversion from 'int' to '__attribute__((address_space(10))) MyType'}}
MyType __attribute__((address_space(10))) m2(123); //expected-error{{no matching constructor for initialization of '__attribute__((address_space(10))) MyType'}}
MyType __attribute__((address_space(10))) m1 = 123;
MyType __attribute__((address_space(10))) m2(123);
6 changes: 0 additions & 6 deletions clang/test/SemaOpenCL/func.cl
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,6 @@ void bar()
foo((void*)foo);
#ifndef FUNCPTREXT
// expected-error@-2{{taking address of function is not allowed}}
#else
// FIXME: Functions should probably be in the address space defined by the
// implementation. It might make sense to put them into the Default address
// space that is bind to a physical segment by the target rather than fixing
// it to any of the concrete OpenCL address spaces during parsing.
// expected-error@-8{{casting 'void (*)(__private void *__private)' to type '__private void *' changes address space}}
#endif

foo(&foo);
Expand Down
27 changes: 6 additions & 21 deletions clang/test/SemaOpenCLCXX/address-space-lambda.clcpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,13 @@ __kernel void test_qual() {
//CHECK: |-CXXMethodDecl {{.*}} constexpr operator() 'void () {{.*}}const __generic'
auto priv2 = []() __generic {};
priv2();
auto priv3 = []() __global {}; //expected-note{{candidate function not viable: 'this' object is in address space '__private', but method expects object in address space '__global'}}
#if defined(_WIN32) && !defined(_WIN64)
//expected-note@35{{conversion candidate of type 'void (*)() __attribute__((thiscall))'}}
#else
//expected-note@35{{conversion candidate of type 'void (*)()'}}
#endif
priv3(); //expected-error{{no matching function for call to object of type}}
auto priv3 = []() __global {};
priv3();

__constant auto const1 = []() __private{}; //expected-note{{candidate function not viable: 'this' object is in address space '__constant', but method expects object in address space '__private'}}
#if defined(_WIN32) && !defined(_WIN64)
//expected-note@43{{conversion candidate of type 'void (*)() __attribute__((thiscall))'}}
#else
//expected-note@43{{conversion candidate of type 'void (*)()'}}
#endif
const1(); //expected-error{{no matching function for call to object of type '__constant (lambda at}}
__constant auto const2 = []() __generic{}; //expected-note{{candidate function not viable: 'this' object is in address space '__constant', but method expects object in address space '__generic'}}
#if defined(_WIN32) && !defined(_WIN64)
//expected-note@50{{conversion candidate of type 'void (*)() __attribute__((thiscall))'}}
#else
//expected-note@50{{conversion candidate of type 'void (*)()'}}
#endif
const2(); //expected-error{{no matching function for call to object of type '__constant (lambda at}}
__constant auto const1 = []() __private{};
const1();
__constant auto const2 = []() __generic{};
const2();
//CHECK: |-CXXMethodDecl {{.*}} constexpr operator() 'void () {{.*}}const __constant'
__constant auto const3 = []() __constant{};
const3();
Expand Down
10 changes: 5 additions & 5 deletions clang/test/SemaTemplate/address_space-dependent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ struct fooFunction {
__attribute__((address_space(I))) void **const base = 0;

void *get_0(void) {
return base[0]; // expected-error {{cannot initialize return object of type 'void *' with an lvalue of type '__attribute__((address_space(1))) void *}}
return base[0];
}

__attribute__((address_space(I))) ft qf; // expected-error {{function type may not be qualified with an address space}}
__attribute__((address_space(I))) char *test3_val;

void test3(void) {
extern void test3_helper(char *p); // expected-note {{passing argument to parameter 'p' here}}
test3_helper(test3_val); // expected-error {{cannot initialize a parameter of type 'char *' with an lvalue of type '__attribute__((address_space(1))) char *'}}
extern void test3_helper(char *p);
test3_helper(test3_val);
}
};

Expand Down Expand Up @@ -109,9 +109,9 @@ int main() {
cmp<1, 2>(x, y); // expected-note {{in instantiation of function template specialization 'cmp<1, 2>' requested here}}

fooFunction<1> ff;
ff.get_0(); // expected-note {{in instantiation of member function 'fooFunction<1>::get_0' requested here}}
ff.get_0();
ff.qf();
ff.test3(); // expected-note {{in instantiation of member function 'fooFunction<1>::test3' requested here}}
ff.test3();

static_assert(partial_spec_deduce_as<int __attribute__((address_space(3))) *>::value == 3, "address space value has been incorrectly deduced");

Expand Down
Loading