diff options
Diffstat (limited to 'clang/test')
21 files changed, 499 insertions, 36 deletions
diff --git a/clang/test/AST/Interp/builtin-align-cxx.cpp b/clang/test/AST/Interp/builtin-align-cxx.cpp new file mode 100644 index 000000000000..62d73dba929b --- /dev/null +++ b/clang/test/AST/Interp/builtin-align-cxx.cpp @@ -0,0 +1,258 @@ +// C++-specific checks for the alignment builtins +// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=expected,both -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=ref,both + + +/// This is just a copy of the one from test/SemaCXX/ with some of the +/// diagnostic output adapted. +/// Also, align32array has an initializer now, which means it's not just +/// a dummy pointer for us and we do actually have type information for it. +/// In the future, we need to retain type information for dummy pointers as +/// well, so here is a test that will break once we do that: +namespace { + _Alignas(32) char heh[4]; + static_assert(!__builtin_is_aligned(&heh[1], 4), ""); // expected-error {{failed}} +} + + +// Check that we don't crash when using dependent types in __builtin_align: +template <typename a, a b> +void *c(void *d) { // both-note{{candidate template ignored}} + return __builtin_align_down(d, b); +} + +struct x {}; +x foo; +void test(void *value) { + c<int, 16>(value); + c<struct x, foo>(value); // both-error{{no matching function for call to 'c'}} +} + +template <typename T, long Alignment, long ArraySize = 16> +void test_templated_arguments() { + T array[ArraySize]; // both-error{{variable has incomplete type 'fwddecl'}} + static_assert(__is_same(decltype(__builtin_align_up(array, Alignment)), T *), // both-error{{requested alignment is not a power of 2}} + "return type should be the decayed array type"); + static_assert(__is_same(decltype(__builtin_align_down(array, Alignment)), T *), + "return type should be the decayed array type"); + static_assert(__is_same(decltype(__builtin_is_aligned(array, Alignment)), bool), + "return type should be bool"); + T *x1 = __builtin_align_up(array, Alignment); + T *x2 = __builtin_align_down(array, Alignment); + bool x3 = __builtin_align_up(array, Alignment); +} + +void test() { + test_templated_arguments<int, 32>(); // fine + test_templated_arguments<struct fwddecl, 16>(); + // both-note@-1{{in instantiation of function template specialization 'test_templated_arguments<fwddecl, 16L, 16L>'}} + // both-note@-2{{forward declaration of 'fwddecl'}} + test_templated_arguments<int, 7>(); // invalid alignment value + // both-note@-1{{in instantiation of function template specialization 'test_templated_arguments<int, 7L, 16L>'}} +} + +template <typename T, long ArraySize> +void test_incorrect_alignment_without_instatiation(T value) { + int array[32]; + static_assert(__is_same(decltype(__builtin_align_up(array, 31)), int *), // both-error{{requested alignment is not a power of 2}} + "return type should be the decayed array type"); + static_assert(__is_same(decltype(__builtin_align_down(array, 7)), int *), // both-error{{requested alignment is not a power of 2}} + "return type should be the decayed array type"); + static_assert(__is_same(decltype(__builtin_is_aligned(array, -1)), bool), // both-error{{requested alignment must be 1 or greater}} + "return type should be bool"); + __builtin_align_up(array); // both-error{{too few arguments to function call, expected 2, have 1}} + __builtin_align_up(array, 31); // both-error{{requested alignment is not a power of 2}} + __builtin_align_down(array, 31); // both-error{{requested alignment is not a power of 2}} + __builtin_align_up(array, 31); // both-error{{requested alignment is not a power of 2}} + __builtin_align_up(value, 31); // This shouldn't want since the type is dependent + __builtin_align_up(value); // Same here + + __builtin_align_up(array, sizeof(sizeof(value)) - 1); // both-error{{requested alignment is not a power of 2}} + __builtin_align_up(array, value); // no diagnostic as the alignment is value dependent. + (void)__builtin_align_up(array, ArraySize); // The same above here +} + +// The original fix for the issue above broke some legitimate code. +// Here is a regression test: +typedef __SIZE_TYPE__ size_t; +void *allocate_impl(size_t size); +template <typename T> +T *allocate() { + constexpr size_t allocation_size = + __builtin_align_up(sizeof(T), sizeof(void *)); + return static_cast<T *>( + __builtin_assume_aligned(allocate_impl(allocation_size), sizeof(void *))); +} +struct Foo { + int value; +}; +void *test2() { + return allocate<struct Foo>(); +} + +// Check that pointers-to-members cannot be used: +class MemPtr { +public: + int data; + void func(); + virtual void vfunc(); +}; +void test_member_ptr() { + __builtin_align_up(&MemPtr::data, 64); // both-error{{operand of type 'int MemPtr::*' where arithmetic or pointer type is required}} + __builtin_align_down(&MemPtr::func, 64); // both-error{{operand of type 'void (MemPtr::*)()' where arithmetic or pointer type is required}} + __builtin_is_aligned(&MemPtr::vfunc, 64); // both-error{{operand of type 'void (MemPtr::*)()' where arithmetic or pointer type is required}} +} + +void test_references(Foo &i) { + // Check that the builtins look at the referenced type rather than the reference itself. + (void)__builtin_align_up(i, 64); // both-error{{operand of type 'Foo' where arithmetic or pointer type is required}} + (void)__builtin_align_up(static_cast<Foo &>(i), 64); // both-error{{operand of type 'Foo' where arithmetic or pointer type is required}} + (void)__builtin_align_up(static_cast<const Foo &>(i), 64); // both-error{{operand of type 'const Foo' where arithmetic or pointer type is required}} + (void)__builtin_align_up(static_cast<Foo &&>(i), 64); // both-error{{operand of type 'Foo' where arithmetic or pointer type is required}} + (void)__builtin_align_up(static_cast<const Foo &&>(i), 64); // both-error{{operand of type 'const Foo' where arithmetic or pointer type is required}} + (void)__builtin_align_up(&i, 64); +} + +// Check that constexpr wrapper functions can be constant-evaluated. +template <typename T> +constexpr bool wrap_is_aligned(T ptr, long align) { + return __builtin_is_aligned(ptr, align); + // both-note@-1{{requested alignment -3 is not a positive power of two}} + // both-note@-2{{requested alignment 19 is not a positive power of two}} + // both-note@-3{{requested alignment must be 128 or less for type 'char'; 4194304 is invalid}} +} +template <typename T> +constexpr T wrap_align_up(T ptr, long align) { + return __builtin_align_up(ptr, align); + // both-note@-1{{requested alignment -2 is not a positive power of two}} + // both-note@-2{{requested alignment 18 is not a positive power of two}} + // both-note@-3{{requested alignment must be 2147483648 or less for type 'int'; 8589934592 is invalid}} + // both-error@-4{{operand of type 'bool' where arithmetic or pointer type is required}} +} + +template <typename T> +constexpr T wrap_align_down(T ptr, long align) { + return __builtin_align_down(ptr, align); + // both-note@-1{{requested alignment -1 is not a positive power of two}} + // both-note@-2{{requested alignment 17 is not a positive power of two}} + // both-note@-3{{requested alignment must be 32768 or less for type 'short'; 1048576 is invalid}} +} + +constexpr int a1 = wrap_align_up(22, 32); +static_assert(a1 == 32, ""); +constexpr int a2 = wrap_align_down(22, 16); +static_assert(a2 == 16, ""); +constexpr bool a3 = wrap_is_aligned(22, 32); +static_assert(!a3, ""); +static_assert(wrap_align_down(wrap_align_up(22, 16), 32) == 32, ""); +static_assert(wrap_is_aligned(wrap_align_down(wrap_align_up(22, 16), 32), 32), ""); +static_assert(!wrap_is_aligned(wrap_align_down(wrap_align_up(22, 16), 32), 64), ""); + +constexpr long const_value(long l) { return l; } +// Check some invalid values during constant-evaluation +static_assert(wrap_align_down(1, const_value(-1)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to}} +static_assert(wrap_align_up(1, const_value(-2)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to}} +static_assert(wrap_is_aligned(1, const_value(-3)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to}} +static_assert(wrap_align_down(1, const_value(17)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to}} +static_assert(wrap_align_up(1, const_value(18)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to}} +static_assert(wrap_is_aligned(1, const_value(19)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to}} + +// Check invalid values for smaller types: +static_assert(wrap_align_down(static_cast<short>(1), const_value(1 << 20)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to }} +// Check invalid boolean type +static_assert(wrap_align_up(static_cast<int>(1), const_value(1ull << 33)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to}} +static_assert(wrap_is_aligned(static_cast<char>(1), const_value(1 << 22)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in call to}} + +// Check invalid boolean type +static_assert(wrap_align_up(static_cast<bool>(1), const_value(1 << 21)), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{in instantiation of function template specialization 'wrap_align_up<bool>' requested here}} + +// Check constant evaluation for pointers: +_Alignas(32) char align32array[128] = {}; +static_assert(&align32array[0] == &align32array[0], ""); +// __builtin_align_up/down can be constant evaluated as a no-op for values +// that are known to have greater alignment: +static_assert(__builtin_align_up(&align32array[0], 32) == &align32array[0], ""); +static_assert(__builtin_align_up(&align32array[0], 4) == &align32array[0], ""); +static_assert(__builtin_align_down(&align32array[0], 4) == __builtin_align_up(&align32array[0], 8), ""); +// But it can not be evaluated if the alignment is greater than the minimum +// known alignment, since in that case the value might be the same if it happens +// to actually be aligned to 64 bytes at run time. +static_assert(&align32array[0] == __builtin_align_up(&align32array[0], 64), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{cannot constant evaluate the result of adjusting alignment to 64}} +static_assert(__builtin_align_up(&align32array[0], 64) == __builtin_align_up(&align32array[0], 64), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{cannot constant evaluate the result of adjusting alignment to 64}} + +// However, we can compute in case the requested alignment is less than the +// base alignment: +static_assert(__builtin_align_up(&align32array[0], 4) == &align32array[0], ""); +static_assert(__builtin_align_up(&align32array[1], 4) == &align32array[4], ""); +static_assert(__builtin_align_up(&align32array[2], 4) == &align32array[4], ""); +static_assert(__builtin_align_up(&align32array[3], 4) == &align32array[4], ""); +static_assert(__builtin_align_up(&align32array[4], 4) == &align32array[4], ""); +static_assert(__builtin_align_up(&align32array[5], 4) == &align32array[8], ""); +static_assert(__builtin_align_up(&align32array[6], 4) == &align32array[8], ""); +static_assert(__builtin_align_up(&align32array[7], 4) == &align32array[8], ""); +static_assert(__builtin_align_up(&align32array[8], 4) == &align32array[8], ""); + +static_assert(__builtin_align_down(&align32array[0], 4) == &align32array[0], ""); +static_assert(__builtin_align_down(&align32array[1], 4) == &align32array[0], ""); +static_assert(__builtin_align_down(&align32array[2], 4) == &align32array[0], ""); +static_assert(__builtin_align_down(&align32array[3], 4) == &align32array[0], ""); +static_assert(__builtin_align_down(&align32array[4], 4) == &align32array[4], ""); +static_assert(__builtin_align_down(&align32array[5], 4) == &align32array[4], ""); +static_assert(__builtin_align_down(&align32array[6], 4) == &align32array[4], ""); +static_assert(__builtin_align_down(&align32array[7], 4) == &align32array[4], ""); +static_assert(__builtin_align_down(&align32array[8], 4) == &align32array[8], ""); + +// Achieving the same thing using casts to uintptr_t is not allowed: +static_assert((char *)((__UINTPTR_TYPE__)&align32array[7] & ~3) == &align32array[4], ""); // both-error{{not an integral constant expression}} \ + // expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + +static_assert(__builtin_align_down(&align32array[1], 4) == &align32array[0], ""); +static_assert(__builtin_align_down(&align32array[1], 64) == &align32array[0], ""); // both-error{{not an integral constant expression}} +// both-note@-1{{cannot constant evaluate the result of adjusting alignment to 64}} + +// Add some checks for __builtin_is_aligned: +static_assert(__builtin_is_aligned(&align32array[0], 32), ""); +static_assert(__builtin_is_aligned(&align32array[4], 4), ""); +// We cannot constant evaluate whether the array is aligned to > 32 since this +// may well be true at run time. +static_assert(!__builtin_is_aligned(&align32array[0], 64), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{cannot constant evaluate whether run-time alignment is at least 64}} + +// However, if the alignment being checked is less than the minimum alignment of +// the base object we can check the low bits of the alignment: +static_assert(__builtin_is_aligned(&align32array[0], 4), ""); +static_assert(!__builtin_is_aligned(&align32array[1], 4), ""); +static_assert(!__builtin_is_aligned(&align32array[2], 4), ""); +static_assert(!__builtin_is_aligned(&align32array[3], 4), ""); +static_assert(__builtin_is_aligned(&align32array[4], 4), ""); + +// TODO: this should evaluate to true even though we can't evaluate the result +// of __builtin_align_up() to a concrete value +static_assert(__builtin_is_aligned(__builtin_align_up(&align32array[0], 64), 64), ""); // both-error{{not an integral constant expression}} +// both-note@-1{{cannot constant evaluate the result of adjusting alignment to 64}} + +// Check different source and alignment type widths are handled correctly. +static_assert(!__builtin_is_aligned(static_cast<signed long>(7), static_cast<signed short>(4)), ""); +static_assert(!__builtin_is_aligned(static_cast<signed short>(7), static_cast<signed long>(4)), ""); +// Also check signed -- unsigned mismatch. +static_assert(!__builtin_is_aligned(static_cast<signed long>(7), static_cast<signed long>(4)), ""); +static_assert(!__builtin_is_aligned(static_cast<unsigned long>(7), static_cast<unsigned long>(4)), ""); +static_assert(!__builtin_is_aligned(static_cast<signed long>(7), static_cast<unsigned long>(4)), ""); +static_assert(!__builtin_is_aligned(static_cast<unsigned long>(7), static_cast<signed long>(4)), ""); +static_assert(!__builtin_is_aligned(static_cast<signed long>(7), static_cast<unsigned short>(4)), ""); +static_assert(!__builtin_is_aligned(static_cast<unsigned short>(7), static_cast<signed long>(4)), ""); + +// Check the diagnostic message +_Alignas(void) char align_void_array[1]; // both-error {{invalid application of '_Alignas' to an incomplete type 'void'}} diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index a7adc92d3714..1a29a664d7ce 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -24,16 +24,13 @@ namespace strcmp { static_assert(__builtin_strcmp("abab", "abab\0banana") == 0, ""); static_assert(__builtin_strcmp("abab\0banana", "abab\0canada") == 0, ""); static_assert(__builtin_strcmp(0, "abab") == 0, ""); // both-error {{not an integral constant}} \ - // both-note {{dereferenced null}} \ - // expected-note {{in call to}} + // both-note {{dereferenced null}} static_assert(__builtin_strcmp("abab", 0) == 0, ""); // both-error {{not an integral constant}} \ - // both-note {{dereferenced null}} \ - // expected-note {{in call to}} + // both-note {{dereferenced null}} static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar) == -1, ""); static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0, ""); // both-error {{not an integral constant}} \ - // both-note {{dereferenced one-past-the-end}} \ - // expected-note {{in call to}} + // both-note {{dereferenced one-past-the-end}} /// Used to assert because we're passing a dummy pointer to /// __builtin_strcmp() when evaluating the return statement. @@ -72,14 +69,11 @@ constexpr const char *a = "foo\0quux"; static_assert(check(c), ""); constexpr int over1 = __builtin_strlen(a + 9); // both-error {{constant expression}} \ - // both-note {{one-past-the-end}} \ - // expected-note {{in call to}} + // both-note {{one-past-the-end}} constexpr int over2 = __builtin_strlen(b + 9); // both-error {{constant expression}} \ - // both-note {{one-past-the-end}} \ - // expected-note {{in call to}} + // both-note {{one-past-the-end}} constexpr int over3 = __builtin_strlen(c + 9); // both-error {{constant expression}} \ - // both-note {{one-past-the-end}} \ - // expected-note {{in call to}} + // both-note {{one-past-the-end}} constexpr int under1 = __builtin_strlen(a - 1); // both-error {{constant expression}} \ // both-note {{cannot refer to element -1}} @@ -90,8 +84,7 @@ constexpr const char *a = "foo\0quux"; constexpr char d[] = { 'f', 'o', 'o' }; // no nul terminator. constexpr int bad = __builtin_strlen(d); // both-error {{constant expression}} \ - // both-note {{one-past-the-end}} \ - // expected-note {{in call to}} + // both-note {{one-past-the-end}} } namespace nan { @@ -114,8 +107,7 @@ namespace nan { /// FIXME: Current interpreter misses diagnostics. constexpr char f2[] = {'0', 'x', 'A', 'E'}; /// No trailing 0 byte. constexpr double NaN7 = __builtin_nan(f2); // both-error {{must be initialized by a constant expression}} \ - // expected-note {{read of dereferenced one-past-the-end pointer}} \ - // expected-note {{in call to}} + // expected-note {{read of dereferenced one-past-the-end pointer}} static_assert(!__builtin_issignaling(__builtin_nan("")), ""); static_assert(__builtin_issignaling(__builtin_nans("")), ""); } diff --git a/clang/test/AST/Interp/cxx03.cpp b/clang/test/AST/Interp/cxx03.cpp index d30cbb2fd7a2..b6aaf0840cfb 100644 --- a/clang/test/AST/Interp/cxx03.cpp +++ b/clang/test/AST/Interp/cxx03.cpp @@ -10,3 +10,17 @@ namespace NonInitializingMemberExpr { // both-note {{required by}} \ // both-note {{subexpression not valid}} } + + +namespace NonLValueMemberExpr { + struct PODType { + int value; + }; + +#define ATTR __attribute__((require_constant_initialization)) + struct TT1 { + ATTR static const int &subobj_init; + }; + + const int &TT1::subobj_init = PODType().value; +} diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp index 4fb3c816000a..f9bb5d53634e 100644 --- a/clang/test/AST/Interp/functions.cpp +++ b/clang/test/AST/Interp/functions.cpp @@ -584,9 +584,20 @@ namespace VariadicOperator { namespace WeakCompare { [[gnu::weak]]void weak_method(); static_assert(weak_method != nullptr, ""); // both-error {{not an integral constant expression}} \ - // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}} + // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}} constexpr auto A = &weak_method; static_assert(A != nullptr, ""); // both-error {{not an integral constant expression}} \ - // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}} + // both-note {{comparison against address of weak declaration '&weak_method' can only be performed at runtim}} +} + +namespace FromIntegral { +#if __cplusplus >= 202002L + typedef double (*DoubleFn)(); + int a[(int)DoubleFn((void*)-1)()]; // both-error {{not allowed at file scope}} \ + // both-warning {{variable length arrays}} + int b[(int)DoubleFn((void*)(-1 + 1))()]; // both-error {{not allowed at file scope}} \ + // expected-note {{evaluates to a null function pointer}} \ + // both-warning {{variable length arrays}} +#endif } diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index f251497ed701..2c33fa1bf884 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1309,3 +1309,11 @@ namespace pr18633 { func2<int>(); } } + +namespace { + struct F { + static constexpr int Z = 12; + }; + F f; + static_assert(f.Z == 12, ""); +} diff --git a/clang/test/AST/Interp/vectors.cpp b/clang/test/AST/Interp/vectors.cpp index 8afef3c897bf..6c5d916f51f5 100644 --- a/clang/test/AST/Interp/vectors.cpp +++ b/clang/test/AST/Interp/vectors.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s // RUN: %clang_cc1 -verify=ref,both %s -// both-no-diagnostics +// ref-no-diagnostics typedef int __attribute__((vector_size(16))) VI4; constexpr VI4 A = {1,2,3,4}; @@ -13,10 +13,18 @@ namespace Vector { return VI4 { n * 3, n + 4, n - 5, n / 6 }; } constexpr auto v1 = f(10); + static_assert(__builtin_vectorelements(v1) == (16 / sizeof(int)), ""); typedef double __attribute__((vector_size(32))) VD4; constexpr VD4 g(int n) { return (VD4) { n / 2.0, n + 1.5, n - 5.4, n * 0.9 }; } constexpr auto v2 = g(4); + static_assert(__builtin_vectorelements(v2) == (32 / sizeof(double)), ""); +} + +/// FIXME: We need to support BitCasts between vector types. +namespace { + typedef float __attribute__((vector_size(16))) VI42; + constexpr VI42 A2 = A; // expected-error {{must be initialized by a constant expression}} } diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index 85db68d41a6c..1c2be322f83c 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -1106,6 +1106,7 @@ using ostream = basic_ostream<char>; extern std::ostream cout; ostream &operator<<(ostream &, const string &); + #if __cplusplus >= 202002L template <class T> ostream &operator<<(ostream &, const std::unique_ptr<T> &); @@ -1122,11 +1123,12 @@ istream &getline(istream &, string &, char); istream &getline(istream &, string &); } // namespace std -#ifdef TEST_INLINABLE_ALLOCATORS namespace std { void *malloc(size_t); void free(void *); -} +} // namespace std + +#ifdef TEST_INLINABLE_ALLOCATORS void* operator new(std::size_t size, const std::nothrow_t&) throw() { return std::malloc(size); } void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return std::malloc(size); } void operator delete(void* ptr, const std::nothrow_t&) throw() { std::free(ptr); } diff --git a/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp index fc067dd04428..f46a2c9bc368 100644 --- a/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp +++ b/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,optin.cplusplus.UninitializedObject \ // RUN: -analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \ // RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \ // RUN: -std=c++11 -verify %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,optin.cplusplus.UninitializedObject \ // RUN: -analyzer-config optin.cplusplus.UninitializedObject:CheckPointeeInitialization=true \ // RUN: -std=c++11 -verify %s @@ -316,7 +316,10 @@ void fCyclicPointerTest2() { // Void pointer tests are mainly no-crash tests. -void *malloc(int size); +typedef __typeof(sizeof(int)) size_t; + +void *calloc(size_t nmemb, size_t size); +void free(void *p); class VoidPointerTest1 { void *vptr; @@ -328,8 +331,9 @@ public: }; void fVoidPointerTest1() { - void *vptr = malloc(sizeof(int)); + void *vptr = calloc(1, sizeof(int)); VoidPointerTest1(vptr, char()); + free(vptr); } class VoidPointerTest2 { @@ -342,8 +346,9 @@ public: }; void fVoidPointerTest2() { - void *vptr = malloc(sizeof(int)); + void *vptr = calloc(1, sizeof(int)); VoidPointerTest2(&vptr, char()); + free(vptr); } class VoidPointerRRefTest1 { @@ -359,8 +364,9 @@ upon returning to the caller. This will be a dangling reference}} }; void fVoidPointerRRefTest1() { - void *vptr = malloc(sizeof(int)); + void *vptr = calloc(1, sizeof(int)); VoidPointerRRefTest1(vptr, char()); + free(vptr); } class VoidPointerRRefTest2 { @@ -376,8 +382,9 @@ upon returning to the caller. This will be a dangling reference}} }; void fVoidPointerRRefTest2() { - void *vptr = malloc(sizeof(int)); + void *vptr = calloc(1, sizeof(int)); VoidPointerRRefTest2(&vptr, char()); + free(vptr); } class VoidPointerLRefTest { @@ -393,8 +400,9 @@ upon returning to the caller. This will be a dangling reference}} }; void fVoidPointerLRefTest() { - void *vptr = malloc(sizeof(int)); + void *vptr = calloc(1, sizeof(int)); VoidPointerLRefTest(vptr, char()); + free(vptr); } struct CyclicVoidPointerTest { diff --git a/clang/test/Analysis/exercise-ps.c b/clang/test/Analysis/exercise-ps.c index d214c3959b20..d1e1771afddb 100644 --- a/clang/test/Analysis/exercise-ps.c +++ b/clang/test/Analysis/exercise-ps.c @@ -1,5 +1,5 @@ // RUN: %clang_analyze_cc1 %s -verify -Wno-error=implicit-function-declaration \ -// RUN: -analyzer-checker=core \ +// RUN: -analyzer-checker=core,unix.Malloc \ // RUN: -analyzer-config core.CallAndMessage:ArgPointeeInitializedness=true // // Just exercise the analyzer on code that has at one point caused issues diff --git a/clang/test/Analysis/explain-svals.cpp b/clang/test/Analysis/explain-svals.cpp index 30368b6976cc..33fce10c4e2b 100644 --- a/clang/test/Analysis/explain-svals.cpp +++ b/clang/test/Analysis/explain-svals.cpp @@ -1,7 +1,7 @@ // RUN: %clang_analyze_cc1 -triple i386-apple-darwin10 -verify %s \ -// RUN: -analyzer-checker=core.builtin \ // RUN: -analyzer-checker=debug.ExprInspection \ // RUN: -analyzer-checker=unix.cstring \ +// RUN: -analyzer-checker=unix.Malloc \ // RUN: -analyzer-config display-checker-name=false typedef unsigned long size_t; diff --git a/clang/test/Analysis/malloc-std-namespace.cpp b/clang/test/Analysis/malloc-std-namespace.cpp new file mode 100644 index 000000000000..d4e397bb812a --- /dev/null +++ b/clang/test/Analysis/malloc-std-namespace.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -analyzer-output=text %s + +// This file tests that unix.Malloc can handle C++ code where e.g. malloc and +// free are declared within the namespace 'std' by the header <cstdlib>. + +#include "Inputs/system-header-simulator-cxx.h" + +void leak() { + int *p = static_cast<int*>(std::malloc(sizeof(int))); // expected-note{{Memory is allocated}} +} // expected-warning{{Potential leak of memory pointed to by 'p'}} + // expected-note@-1{{Potential leak of memory pointed to by 'p'}} + +void no_leak() { + int *p = static_cast<int*>(std::malloc(sizeof(int))); + std::free(p); // no-warning +} + +void invalid_free() { + int i; + int *p = &i; + //expected-note@+2{{Argument to free() is the address of the local variable 'i', which is not memory allocated by malloc()}} + //expected-warning@+1{{Argument to free() is the address of the local variable 'i', which is not memory allocated by malloc()}} + std::free(p); +} diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c index 09cd4b0bfce6..e5cb45ba7335 100644 --- a/clang/test/Analysis/malloc.c +++ b/clang/test/Analysis/malloc.c @@ -740,6 +740,17 @@ void allocaFree(void) { free(p); // expected-warning {{Memory allocated by alloca() should not be deallocated}} } +void allocaFreeBuiltin(void) { + int *p = __builtin_alloca(sizeof(int)); + free(p); // expected-warning {{Memory allocated by alloca() should not be deallocated}} +} + +void allocaFreeBuiltinAlign(void) { + int *p = __builtin_alloca_with_align(sizeof(int), 64); + free(p); // expected-warning {{Memory allocated by alloca() should not be deallocated}} +} + + int* mallocEscapeRet(void) { int *p = malloc(12); return p; // no warning diff --git a/clang/test/Analysis/malloc.cpp b/clang/test/Analysis/malloc.cpp index 14b4c0576384..300b344ab25d 100644 --- a/clang/test/Analysis/malloc.cpp +++ b/clang/test/Analysis/malloc.cpp @@ -214,3 +214,14 @@ void *realloc(void **ptr, size_t size) { realloc(ptr, size); } // no-crash namespace pr46253_paramty2{ void *realloc(void *ptr, int size) { realloc(ptr, size); } // no-crash } // namespace pr46253_paramty2 + +namespace pr81597 { +struct S {}; +struct T { + void free(const S& s); +}; +void f(T& t) { + S s; + t.free(s); // no-warning: This is not the free you are looking for... +} +} // namespace pr81597 diff --git a/clang/test/Analysis/stack-addr-ps.c b/clang/test/Analysis/stack-addr-ps.c index e469396e1bb2..e69ab4189b52 100644 --- a/clang/test/Analysis/stack-addr-ps.c +++ b/clang/test/Analysis/stack-addr-ps.c @@ -1,4 +1,4 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -fblocks -verify %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -fblocks -verify %s int* f1(void) { int x = 0; diff --git a/clang/test/Analysis/stackaddrleak.c b/clang/test/Analysis/stackaddrleak.c index 0583bfc18711..39c29f2a2635 100644 --- a/clang/test/Analysis/stackaddrleak.c +++ b/clang/test/Analysis/stackaddrleak.c @@ -1,5 +1,5 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -std=c99 -Dbool=_Bool -Wno-bool-conversion %s -// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify -x c++ -Wno-bool-conversion %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -std=c99 -Dbool=_Bool -Wno-bool-conversion %s +// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc -verify -x c++ -Wno-bool-conversion %s typedef __INTPTR_TYPE__ intptr_t; char const *p; diff --git a/clang/test/CodeGen/target-data.c b/clang/test/CodeGen/target-data.c index acff367d50eb..c184f314f68f 100644 --- a/clang/test/CodeGen/target-data.c +++ b/clang/test/CodeGen/target-data.c @@ -251,11 +251,11 @@ // RUN: %clang_cc1 -triple spir-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=SPIR -// SPIR: target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +// SPIR: target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1" // RUN: %clang_cc1 -triple spir64-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=SPIR64 -// SPIR64: target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +// SPIR64: target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1" // RUN: %clang_cc1 -triple bpfel -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=BPFEL diff --git a/clang/test/CodeGenCXX/control-flow-in-stmt-expr.cpp b/clang/test/CodeGenCXX/control-flow-in-stmt-expr.cpp index 95deee8bb1f1..0a51b0e4121c 100644 --- a/clang/test/CodeGenCXX/control-flow-in-stmt-expr.cpp +++ b/clang/test/CodeGenCXX/control-flow-in-stmt-expr.cpp @@ -391,3 +391,19 @@ void ArrayInitWithContinue() { })}; } } + +struct [[clang::trivial_abi]] HasTrivialABI { + HasTrivialABI(); + ~HasTrivialABI(); +}; +void AcceptTrivialABI(HasTrivialABI, int); +void TrivialABI() { + // CHECK-LABEL: define dso_local void @_Z10TrivialABIv() + AcceptTrivialABI(HasTrivialABI(), ({ + if (foo()) return; + // CHECK: if.then: + // CHECK-NEXT: call void @_ZN13HasTrivialABID1Ev + // CHECK-NEXT: br label %return + 0; + })); +} diff --git a/clang/test/Driver/windows-seh-async-verify.cpp b/clang/test/Driver/windows-seh-async-verify.cpp new file mode 100644 index 000000000000..ace93cf44a31 --- /dev/null +++ b/clang/test/Driver/windows-seh-async-verify.cpp @@ -0,0 +1,24 @@ +// RUN: %clang --target=x86_64-pc-windows -fasync-exceptions -fsyntax-only -### %s 2>&1 | FileCheck %s +// RUN: %clang_cl --target=x86_64-pc-windows /EHa -fsyntax-only -### -- %s 2>&1 | FileCheck %s +// RUN: %clang --target=x86_64-pc-windows-gnu -fasync-exceptions -fsyntax-only -### %s 2>&1 | FileCheck %s --check-prefixes=GNU-ALL,GNU +// RUN: %clang_cl --target=x86_64-pc-windows-gnu /EHa -fsyntax-only -### -- %s 2>&1 | FileCheck %s --check-prefixes=GNU-ALL,CL-GNU + +// CHECK-NOT: warning +// GNU: warning: argument unused during compilation: '-fasync-exceptions' [-Wunused-command-line-argument] +// CL-GNU: warning: argument unused during compilation: '/EHa' [-Wunused-command-line-argument] + +// CHECK: -fasync-exceptions +// GNU-ALL-NOT: -fasync-exceptions +struct S { + union _Un { + ~_Un() {} + char _Buf[12]; + }; + _Un _un; +}; + +struct Embed { + S v2; +}; + +void PR62449() { Embed v{}; } diff --git a/clang/test/Index/USR/func-type.cpp b/clang/test/Index/USR/func-type.cpp index ff1cd37a7fc4..459a8cd6da55 100644 --- a/clang/test/Index/USR/func-type.cpp +++ b/clang/test/Index/USR/func-type.cpp @@ -16,3 +16,15 @@ void Func( void (* (*)(int, int))(int, int) ); // CHECK: {{[0-9]+}}:6 | function/C | Func | c:@F@Func#*F*Fv(#I#I)(#I#I)# | void Func( void (* (*)(int, int, int))(int) ); // CHECK: {{[0-9]+}}:6 | function/C | Func | c:@F@Func#*F*Fv(#I)(#I#I#I)# | + +// Functions with parameter types that only differ in top-level cv-qualification should generate the same USR. + +void f( const int ); +// CHECK: {{[0-9]+}}:6 | function/C | f | c:@F@f#I# | +void f( int ); +// CHECK: {{[0-9]+}}:6 | function/C | f | c:@F@f#I# | + +void g( int ); +// CHECK: {{[0-9]+}}:6 | function/C | g | c:@F@g#I# | +void g( const int ); +// CHECK: {{[0-9]+}}:6 | function/C | g | c:@F@g#I# | diff --git a/clang/test/Modules/hashing-decls-in-exprs-from-gmf-2.cppm b/clang/test/Modules/hashing-decls-in-exprs-from-gmf-2.cppm new file mode 100644 index 000000000000..66143102cb9e --- /dev/null +++ b/clang/test/Modules/hashing-decls-in-exprs-from-gmf-2.cppm @@ -0,0 +1,44 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t +// +// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/A.cppm -emit-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 -fskip-odr-check-in-gmf %t/test.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + +//--- header.h +#pragma once +template <class _Tp> +class Optional {}; + +template <class _Tp> +concept C = requires(const _Tp& __t) { + []<class _Up>(const Optional<_Up>&) {}(__t); +}; + +//--- func.h +#include "header.h" +template <C T> +void func() {} + +//--- test_func.h +#include "func.h" + +inline void test_func() { + func<Optional<int>>(); +} + +//--- A.cppm +module; +#include "header.h" +#include "test_func.h" +export module A; +export using ::test_func; + +//--- test.cpp +// expected-no-diagnostics +import A; +#include "test_func.h" + +void test() { + test_func(); +} diff --git a/clang/test/SemaCXX/instantiate-new-placement-size.cpp b/clang/test/SemaCXX/instantiate-new-placement-size.cpp new file mode 100644 index 000000000000..7a29d3dee849 --- /dev/null +++ b/clang/test/SemaCXX/instantiate-new-placement-size.cpp @@ -0,0 +1,20 @@ +// RUN: %clang -S -fno-discard-value-names -emit-llvm -o - %s | FileCheck %s +// Issue no: 41441 +#include <new> + +// CHECK: call void @llvm.memset.p0.i64(ptr align 1 %x, i8 0, i64 8, i1 false) +// CHECK: call void @llvm.memset.p0.i64(ptr align 16 %x, i8 0, i64 32, i1 false) +template <typename TYPE> +void f() +{ + typedef TYPE TArray[8]; + + TArray x; + new(&x) TArray(); +} + +int main() +{ + f<char>(); + f<int>(); +} |