mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-27 13:36:07 +00:00

Given the following invalid code, ```cpp template <class T> struct S { T *a; }; S s = {1}; ``` we produce such diagnostics currently: ``` <source>:2:8: note: candidate template ignored: could not match 'S<T>' against 'int' 2 | struct S { | ^ <source>:2:8: note: candidate template ignored: could not match 'T *' against 'int' ``` Which I think is confusing because there's no `S<T>` nor `T *` at the location it points to. This is because we're deducing the initializer against implicitly generated deduction guides, and their source locations just point to the corresponding `RecordDecl`. Hence the misleading notes. This patch alleviates the issue by adding extra notes demonstrating which implicit deduction guide we're deducing against. In other words, in addition to the note of `could not match 'T *' against 'int'`, we would also say the implicit deduction guide we're trying to use: `template <class T> S(T *) -> S<T>`, which looks clearer IMO. --------- Co-authored-by: Sirraide <aeternalmail@gmail.com>
94 lines
4.1 KiB
C++
94 lines
4.1 KiB
C++
// TLS variable cannot be aligned to more than 32 bytes on PS4.
|
|
|
|
// RUN: %clang_cc1 -triple x86_64-scei-ps4 -std=c++17 -fsyntax-only -verify %s
|
|
|
|
|
|
// A non-aligned type.
|
|
struct non_aligned_struct {
|
|
int some_data[16]; // 64 bytes of stuff, non aligned.
|
|
};
|
|
|
|
// An aligned type.
|
|
struct __attribute__(( aligned(64) )) aligned_struct {
|
|
int some_data[12]; // 48 bytes of stuff, aligned to 64.
|
|
};
|
|
|
|
// A type with an aligned field.
|
|
struct struct_with_aligned_field {
|
|
int some_aligned_data[12] __attribute__(( aligned(64) )); // 48 bytes of stuff, aligned to 64.
|
|
};
|
|
|
|
// A templated type
|
|
template <typename>
|
|
struct templated_struct {};
|
|
// expected-note@-1{{candidate template ignored: couldn't infer template argument ''}}
|
|
// expected-note@-2{{implicit deduction guide declared as 'template <typename> templated_struct() -> templated_struct<type-parameter-0-0>'}}
|
|
// expected-note@-3{{candidate function template not viable: requires 1 argument, but 0 were provided}}
|
|
// expected-note@-4{{implicit deduction guide declared as 'template <typename> templated_struct(templated_struct<type-parameter-0-0>) -> templated_struct<type-parameter-0-0>'}}
|
|
|
|
// A typedef of the aligned struct.
|
|
typedef aligned_struct another_aligned_struct;
|
|
|
|
// A typedef to redefine a non-aligned struct as aligned.
|
|
typedef __attribute__(( aligned(64) )) non_aligned_struct yet_another_aligned_struct;
|
|
|
|
// Non aligned variable doesn't cause an error.
|
|
__thread non_aligned_struct foo;
|
|
|
|
// Variable aligned because of its type should cause an error.
|
|
__thread aligned_struct bar; // expected-error{{alignment (64) of thread-local variable}}
|
|
|
|
// Variable explicitly aligned in the declaration should cause an error.
|
|
__thread non_aligned_struct bar2 __attribute__(( aligned(64) )); // expected-error{{alignment (64) of thread-local variable}}
|
|
|
|
// Variable aligned because of one of its fields should cause an error.
|
|
__thread struct_with_aligned_field bar3; // expected-error{{alignment (64) of thread-local variable}}
|
|
|
|
// Variable aligned because of typedef, first case.
|
|
__thread another_aligned_struct bar4; // expected-error{{alignment (64) of thread-local variable}}
|
|
|
|
// Variable aligned because of typedef, second case.
|
|
__thread yet_another_aligned_struct bar5; // expected-error{{alignment (64) of thread-local variable}}
|
|
|
|
// No crash for undeduced type.
|
|
__thread templated_struct bar6; // expected-error{{no viable constructor or deduction guide for deduction of template arguments of 'templated_struct'}}
|
|
|
|
int baz ()
|
|
{
|
|
return foo.some_data[0] + bar.some_data[1] + bar2.some_data[2] +
|
|
bar3.some_aligned_data[3] + bar4.some_data[4] +
|
|
bar5.some_data[5];
|
|
}
|
|
|
|
template<class T> struct templated_tls {
|
|
static __thread T t;
|
|
T other_t __attribute__(( aligned(64) ));
|
|
};
|
|
__thread templated_tls<int> blah; // expected-error{{alignment (64) of thread-local variable}}
|
|
|
|
template <int N>
|
|
struct S {
|
|
struct alignas(64) B {};
|
|
struct alignas(N) C {};
|
|
static inline void f() {
|
|
thread_local B b; // expected-error{{alignment (64) of thread-local variable}}
|
|
thread_local C c; // expected-error{{alignment (64) of thread-local variable}}
|
|
}
|
|
template<int J> static inline thread_local int b alignas(J) = J; // expected-error{{alignment (64) of thread-local variable}}
|
|
static int __thread __attribute__((aligned(N))) x; // expected-error{{alignment (64) of thread-local variable}}
|
|
};
|
|
|
|
int blag() {
|
|
// Verify alignment check where the alignment is a template parameter.
|
|
// The check is only performed during instantiation.
|
|
S<64> s_instance; // expected-note{{in instantiation of template class 'S<64>' requested here}}
|
|
|
|
// Verify alignment for dependent local variables.
|
|
S<64>::f(); // expected-note{{in instantiation of member function 'S<64>::f' requested here}}
|
|
|
|
// Verify alignment check where a dependent type is involved.
|
|
// The check is (correctly) not performed on "t", but the check still is
|
|
// performed on the structure as a whole once it has been instantiated.
|
|
return blah.other_t * 2 + S<64>::b<64>; // expected-note{{in instantiation of static data member 'S<64>::b' requested here}}
|
|
}
|