1 // RUN: %clang_cc1 -Wfortify-source -triple x86_64-apple-macosx10.14.0 %s -verify
2 // RUN: %clang_cc1 -Wfortify-source -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify
4 typedef unsigned long size_t;
6 __attribute__((diagnose_as_builtin(__builtin_memcpy
, 3, 1, 2))) int x
; // expected-warning {{'diagnose_as_builtin' attribute only applies to functions}}
8 void *test_memcpy(const void *src
, size_t c
, void *dst
) __attribute__((diagnose_as_builtin(__builtin_memcpy
, 3, 1, 2))) {
9 return __builtin_memcpy(dst
, src
, c
);
12 void call_test_memcpy(void) {
15 test_memcpy(bufferB
, 10, bufferA
);
16 test_memcpy(bufferB
, 11, bufferA
); // expected-warning {{'memcpy' will always overflow; destination buffer has size 10, but size argument is 11}}
19 void failure_function_doesnt_exist(void) __attribute__((diagnose_as_builtin(__function_that_doesnt_exist
))) {} // expected-error {{use of undeclared identifier '__function_that_doesnt_exist'}}
21 void not_a_builtin(void) {}
23 void failure_not_a_builtin(void) __attribute__((diagnose_as_builtin(not_a_builtin
))) {} // expected-error {{'diagnose_as_builtin' attribute requires parameter 1 to be a builtin function}}
25 void failure_too_many_parameters(void *dst
, const void *src
, size_t count
, size_t nothing
) __attribute__((diagnose_as_builtin(__builtin_memcpy
, 1, 2, 3, 4))) {} // expected-error {{'diagnose_as_builtin' attribute references function '__builtin_memcpy', which takes exactly 3 arguments}}
27 void failure_too_few_parameters(void *dst
, const void *src
) __attribute__((diagnose_as_builtin(__builtin_memcpy
, 1, 2))) {} // expected-error{{'diagnose_as_builtin' attribute references function '__builtin_memcpy', which takes exactly 3 arguments}}
29 void failure_not_an_integer(void *dst
, const void *src
, size_t count
) __attribute__((diagnose_as_builtin(__builtin_memcpy
, "abc", 2, 3))) {} // expected-error{{'diagnose_as_builtin' attribute requires parameter 2 to be an integer constant}}
31 void failure_not_a_builtin2(void) __attribute__((diagnose_as_builtin("abc"))) {} // expected-error{{'diagnose_as_builtin' attribute requires parameter 1 to be a builtin function}}
33 void failure_parameter_index_bounds(void *dst
, const void *src
) __attribute__((diagnose_as_builtin(__builtin_memcpy
, 1, 2, 3))) {} // expected-error{{'diagnose_as_builtin' attribute references parameter 3, but the function 'failure_parameter_index_bounds' has only 2 parameters}}
35 void failure_parameter_types(double dst
, const void *src
, size_t count
) __attribute__((diagnose_as_builtin(__builtin_memcpy
, 1, 2, 3))) {} // expected-error{{'diagnose_as_builtin' attribute parameter types do not match: parameter 1 of function 'failure_parameter_types' has type 'double', but parameter 1 of function '__builtin_memcpy' has type 'void *'}}
37 void to_redeclare(void *dst
, const void *src
, size_t count
);
39 void use_to_redeclare(void) {
42 // We shouldn't get an error yet.
43 to_redeclare(dst
, src
, 10);
46 void to_redeclare(void *dst
, const void *src
, size_t count
) __attribute((diagnose_as_builtin(__builtin_memcpy
, 1, 2, 3)));
48 void error_to_redeclare(void) {
51 // Now we get an error.
52 to_redeclare(dst
, src
, 10); // expected-warning {{'memcpy' will always overflow; destination buffer has size 9, but size argument is 10}}
55 // Make sure this works even with extra qualifiers and the pass_object_size attribute.
56 void *memcpy2(void *const dst
__attribute__((pass_object_size(0))), const void *src
, size_t copy_amount
) __attribute((diagnose_as_builtin(__builtin_memcpy
, 1, 2, 3)));
58 void call_memcpy2(void) {
61 memcpy2(buf1
, buf2
, 11); // expected-warning {{'memcpy' will always overflow; destination buffer has size 10, but size argument is 11}}
64 // We require the types to be identical, modulo canonicalization and qualifiers.
65 // Maybe this could be relaxed if it proves too restrictive.
66 void failure_type(void *dest
, char val
, size_t n
) __attribute__((diagnose_as_builtin(__builtin_memset
, 1, 2, 3))) {} // expected-error {{'diagnose_as_builtin' attribute parameter types do not match: parameter 2 of function 'failure_type' has type 'char', but parameter 2 of function '__builtin_memset' has type 'int'}}
72 extern int sscanf(const char *input
, const char *format
, ...);
78 // Variadics should work.
79 int mysscanf(const char *str
, const char *format
, ...) __attribute__((diagnose_as_builtin(sscanf
, 1, 2)));
81 void warn_mysccanf(void) {
83 mysscanf("", "%10s", buf
); // expected-warning{{'sscanf' may overflow; destination buffer in argument 3 has size 10, but the corresponding specifier may require size 11}}
89 void some_templated_function(int x
) {
93 void failure_template(int x
) __attribute__((diagnose_as_builtin(some_templated_function
, 1))) {} // expected-error{{'diagnose_as_builtin' attribute requires parameter 1 to be a builtin function}}
95 void failure_template_instantiation(int x
) __attribute__((diagnose_as_builtin(some_templated_function
<int>, 1))) {} // expected-error{{'diagnose_as_builtin' attribute requires parameter 1 to be a builtin function}}
97 void overloaded_function(unsigned);
99 void overloaded_function(int);
101 void failure_overloaded_function(int) __attribute__((diagnose_as_builtin(overloaded_function
, 1))) {} // expected-error{{'diagnose_as_builtin' attribute requires parameter 1 to be a builtin function}}
104 __attribute__((diagnose_as_builtin(__builtin_memset
))) void f(); // expected-error{{'diagnose_as_builtin' attribute cannot be applied to non-static member functions}}
106 __attribute__((diagnose_as_builtin(__builtin_memcpy
, 3, 1, 2))) static void *test_memcpy(const void *src
, size_t c
, void *dst
) {
107 return __builtin_memcpy(dst
, src
, c
);
111 void call_static_test_memcpy(void) {
114 S::test_memcpy(bufferB
, 10, bufferA
);
115 S::test_memcpy(bufferB
, 11, bufferA
); // expected-warning {{'memcpy' will always overflow; destination buffer has size 10, but size argument is 11}}