summaryrefslogtreecommitdiffstats
path: root/test/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'test/Sema')
-rw-r--r--test/Sema/128bitint.c19
-rw-r--r--test/Sema/arm-asm.c7
-rw-r--r--test/Sema/builtins-decl.c5
-rw-r--r--test/Sema/callingconv.c8
-rw-r--r--test/Sema/static-array.c46
-rw-r--r--test/Sema/tentative-decls.c5
-rw-r--r--test/Sema/warn-documentation.cpp60
-rw-r--r--test/Sema/warn-type-safety-mpi-hdf5.c307
-rw-r--r--test/Sema/warn-type-safety.c152
-rw-r--r--test/Sema/warn-type-safety.cpp71
10 files changed, 661 insertions, 19 deletions
diff --git a/test/Sema/128bitint.c b/test/Sema/128bitint.c
index ddad835..600c25a 100644
--- a/test/Sema/128bitint.c
+++ b/test/Sema/128bitint.c
@@ -18,3 +18,22 @@ long long Signed64 = 123456789012345678901234567890i128; // expected-warning {{i
unsigned long long UnsignedTooBig = 123456789012345678901234567890; // expected-warning {{integer constant is too large for its type}}
__uint128_t Unsigned128 = 123456789012345678901234567890Ui128;
unsigned long long Unsigned64 = 123456789012345678901234567890Ui128; // expected-warning {{implicit conversion from 'unsigned __int128' to 'unsigned long long' changes value from 123456789012345678901234567890 to 14083847773837265618}}
+
+// Ensure we don't crash when user passes 128-bit values to type safety
+// attributes.
+void pointer_with_type_tag_arg_num_1(void *buf, int datatype)
+ __attribute__(( pointer_with_type_tag(mpi,0x10000000000000001i128,1) )); // expected-error {{attribute parameter 2 is out of bounds}}
+
+void pointer_with_type_tag_arg_num_2(void *buf, int datatype)
+ __attribute__(( pointer_with_type_tag(mpi,1,0x10000000000000001i128) )); // expected-error {{attribute parameter 3 is out of bounds}}
+
+void MPI_Send(void *buf, int datatype) __attribute__(( pointer_with_type_tag(mpi,1,2) ));
+
+static const __uint128_t mpi_int_wrong __attribute__(( type_tag_for_datatype(mpi,int) )) = 0x10000000000000001i128; // expected-error {{'type_tag_for_datatype' attribute requires the initializer to be an integer constant expression that can be represented by a 64 bit integer}}
+static const int mpi_int __attribute__(( type_tag_for_datatype(mpi,int) )) = 10;
+
+void test(int *buf)
+{
+ MPI_Send(buf, 0x10000000000000001i128); // expected-warning {{implicit conversion from '__int128' to 'int' changes value}}
+}
+
diff --git a/test/Sema/arm-asm.c b/test/Sema/arm-asm.c
new file mode 100644
index 0000000..3fc0eeb
--- /dev/null
+++ b/test/Sema/arm-asm.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 %s -triple armv7-apple-darwin -verify -fsyntax-only
+
+void f (void) {
+ int Val;
+ asm volatile ("lw (r1), %0[val]": "=&b"(Val)); // expected-error {{invalid output constraint '=&b' in asm}}
+ return;
+}
diff --git a/test/Sema/builtins-decl.c b/test/Sema/builtins-decl.c
index 19bdb84..d6b004a 100644
--- a/test/Sema/builtins-decl.c
+++ b/test/Sema/builtins-decl.c
@@ -6,3 +6,8 @@
extern unsigned int __builtin_ia32_crc32qi (unsigned int, unsigned char);
extern unsigned int __builtin_ia32_crc32hi (unsigned int, unsigned short);
extern unsigned int __builtin_ia32_crc32si (unsigned int, unsigned int);
+
+// GCC documents these as unsigned, but they are defined with a signed argument.
+extern int __builtin_ffs(int);
+extern int __builtin_ffsl(long);
+extern int __builtin_ffsll(long long);
diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c
index 25669f0..6c844a3 100644
--- a/test/Sema/callingconv.c
+++ b/test/Sema/callingconv.c
@@ -36,6 +36,14 @@ void (__attribute__((cdecl)) *pctest2)() = ctest2;
typedef void (__attribute__((fastcall)) *Handler) (float *);
Handler H = foo;
+int __attribute__((pcs("aapcs", "aapcs"))) pcs1(void); // expected-error {{attribute takes one argument}}
+int __attribute__((pcs())) pcs2(void); // expected-error {{attribute takes one argument}}
+int __attribute__((pcs(pcs1))) pcs3(void); // expected-error {{attribute takes one argument}}
+int __attribute__((pcs(0))) pcs4(void); // expected-error {{'pcs' attribute requires parameter 1 to be a string}}
+int __attribute__((pcs("aapcs"))) pcs5(void); // no-error
+int __attribute__((pcs("aapcs-vfp"))) pcs6(void); // no-error
+int __attribute__((pcs("foo"))) pcs7(void); // expected-error {{Invalid PCS type}}
+
// PR6361
void ctest3();
void __attribute__((cdecl)) ctest3() {}
diff --git a/test/Sema/static-array.c b/test/Sema/static-array.c
index 2d4b968..5ca693b 100644
--- a/test/Sema/static-array.c
+++ b/test/Sema/static-array.c
@@ -1,12 +1,9 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
void cat0(int a[static 0]) {} // expected-warning {{'static' has no effect on zero-length arrays}}
void cat(int a[static 3]) {} // expected-note 2 {{callee declares array parameter as static here}}
-typedef int i3[static 3];
-void tcat(i3 a) {}
-
void vat(int i, int a[static i]) {} // expected-note {{callee declares array parameter as static here}}
void f(int *p) {
@@ -20,12 +17,41 @@ void f(int *p) {
cat(c);
cat(p);
- tcat(0); // expected-warning {{null passed to a callee which requires a non-null argument}}
- tcat(a); // expected-warning {{array argument is too small; contains 2 elements, callee requires at least 3}}
- tcat(b);
- tcat(c);
- tcat(p);
-
vat(1, 0); // expected-warning {{null passed to a callee which requires a non-null argument}}
vat(3, b);
}
+
+
+typedef int td[static 3]; // expected-error {{'static' used in array declarator outside of function prototype}}
+typedef void(*fp)(int[static 42]); // no-warning
+
+void g(void) {
+ int a[static 42]; // expected-error {{'static' used in array declarator outside of function prototype}}
+
+ int b[const 10]; // expected-error {{type qualifier used in array declarator outside of function prototype}}
+ int c[volatile 10]; // expected-error {{type qualifier used in array declarator outside of function prototype}}
+ int d[restrict 10]; // expected-error {{type qualifier used in array declarator outside of function prototype}}
+
+ int e[static restrict 1]; // expected-error {{'static' used in array declarator outside of function prototype}}
+}
+
+void h(int [static const 10][42]); // no-warning
+
+void i(int [10]
+ [static 42]); // expected-error {{'static' used in non-outermost array type derivation}}
+
+void j(int [10]
+ [const 42]); // expected-error {{type qualifier used in non-outermost array type derivation}}
+
+void k(int (*x)[static 10]); // expected-error {{'static' used in non-outermost array type derivation}}
+void l(int (x)[static 10]); // no-warning
+void m(int *x[static 10]); // no-warning
+void n(int *(x)[static 10]); // no-warning
+
+void o(int (x[static 10])(void)); // expected-error{{'x' declared as array of functions of type 'int (void)'}}
+void p(int (^x)[static 10]); // expected-error{{block pointer to non-function type is invalid}}
+void q(int (^x[static 10])()); // no-warning
+
+void r(x)
+ int x[restrict]; // no-warning
+{}
diff --git a/test/Sema/tentative-decls.c b/test/Sema/tentative-decls.c
index b15537b..e14540b 100644
--- a/test/Sema/tentative-decls.c
+++ b/test/Sema/tentative-decls.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
+// RUN: %clang_cc1 %s -fsyntax-only -Wprivate-extern -verify
// PR3310
struct a x1; // expected-note 2{{forward declaration of 'struct a'}}
@@ -32,7 +32,8 @@ int i2 = 3; // expected-error{{non-static declaration of 'i2' follows static dec
static int i3 = 5;
extern int i3;
-__private_extern__ int pExtern;
+// rdar://7703982
+__private_extern__ int pExtern; // expected-warning {{Use of __private_extern__ on tentative definition has unexpected behaviour}}
int pExtern = 0;
int i4;
diff --git a/test/Sema/warn-documentation.cpp b/test/Sema/warn-documentation.cpp
index 16ba429..d99520b 100644
--- a/test/Sema/warn-documentation.cpp
+++ b/test/Sema/warn-documentation.cpp
@@ -624,13 +624,9 @@ class test_attach37 {
/// \brief\author Aaa
/// \tparam T Aaa
void test_attach38(int aaa, int bbb);
-};
-// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
-/// \brief\author Aaa
-/// \tparam T Aaa
-template<typename T>
-void test_attach37<T>::test_attach38(int aaa, int bbb) {}
+ void test_attach39(int aaa, int bbb);
+};
// expected-warning@+2 {{empty paragraph passed to '\brief' command}}
// expected-warning@+2 {{template parameter 'T' not found in the template declaration}}
@@ -639,6 +635,29 @@ void test_attach37<T>::test_attach38(int aaa, int bbb) {}
template<>
void test_attach37<int>::test_attach38(int aaa, int bbb) {}
+// expected-warning@+1 {{empty paragraph passed to '\brief' command}}
+/// \brief\author Aaa
+/// \tparam T Aaa
+template<typename T>
+void test_attach37<T>::test_attach39(int aaa, int bbb) {}
+
+// We used to emit warning that parameter 'a' is not found because we parsed
+// the comment in context of the redeclaration which does not have parameter
+// names.
+template <typename T>
+struct test_attach38 {
+ /*!
+ \param a First param
+ \param b Second param
+ */
+ template <typename B>
+ void test_attach39(T a, B b);
+};
+
+template <>
+template <typename B>
+void test_attach38<int>::test_attach39(int, B);
+
// PR13411, reduced. We used to crash on this.
/**
@@ -652,7 +671,7 @@ void test_nocrash1(int);
/// \param\brief
void test_nocrash2(int);
-// PR13593
+// PR13593, example 1 and 2
/**
* Bla.
@@ -668,3 +687,30 @@ template <typename>
void test_nocrash3()
{
}
+
+// PR13593, example 3
+
+/**
+ * aaa
+ */
+template <typename T>
+inline T test_nocrash5(T a1)
+{
+ return a1;
+}
+
+///
+//,
+
+inline void test_nocrash6()
+{
+ test_nocrash5(1);
+}
+
+// We used to crash on this.
+
+/*!
+ Blah.
+*/
+typedef const struct test_nocrash7 * test_nocrash8;
+
diff --git a/test/Sema/warn-type-safety-mpi-hdf5.c b/test/Sema/warn-type-safety-mpi-hdf5.c
new file mode 100644
index 0000000..9c2ee96
--- /dev/null
+++ b/test/Sema/warn-type-safety-mpi-hdf5.c
@@ -0,0 +1,307 @@
+// RUN: %clang_cc1 -std=c99 -DOPEN_MPI -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c99 -DMPICH -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -std=c++98 -DOPEN_MPI -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -std=c++98 -DMPICH -fsyntax-only -verify %s
+//
+// RUN: %clang_cc1 -std=c99 -DOPEN_MPI -fno-signed-char -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c99 -DMPICH -fno-signed-char -fsyntax-only -verify %s
+
+//===--- limits.h mock ----------------------------------------------------===//
+
+#ifdef __CHAR_UNSIGNED__
+#define CHAR_MIN 0
+#define CHAR_MAX (__SCHAR_MAX__*2 +1)
+#else
+#define CHAR_MIN (-__SCHAR_MAX__-1)
+#define CHAR_MAX __SCHAR_MAX__
+#endif
+
+//===--- mpi.h mock -------------------------------------------------------===//
+
+#define NULL ((void *)0)
+
+#ifdef OPEN_MPI
+typedef struct ompi_datatype_t *MPI_Datatype;
+#endif
+
+#ifdef MPICH
+typedef int MPI_Datatype;
+#endif
+
+int MPI_Send(void *buf, int count, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,1,3) ));
+
+int MPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype,
+ void *recvbuf, int recvcount, MPI_Datatype recvtype)
+ __attribute__(( pointer_with_type_tag(mpi,1,3), pointer_with_type_tag(mpi,4,6) ));
+
+#ifdef OPEN_MPI
+// OpenMPI and LAM/MPI-style datatype definitions
+
+#define OMPI_PREDEFINED_GLOBAL(type, global) ((type) &(global))
+
+#define MPI_DATATYPE_NULL OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_datatype_null)
+#define MPI_FLOAT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_float)
+#define MPI_INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_int)
+#define MPI_LONG OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_long)
+#define MPI_LONG_LONG_INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_long_long_int)
+#define MPI_CHAR OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_char)
+
+#define MPI_FLOAT_INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_float_int)
+#define MPI_2INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_2int)
+
+#define MPI_IN_PLACE ((void *) 1)
+
+extern struct ompi_predefined_datatype_t ompi_mpi_datatype_null __attribute__(( type_tag_for_datatype(mpi,void,must_be_null) ));
+extern struct ompi_predefined_datatype_t ompi_mpi_float __attribute__(( type_tag_for_datatype(mpi,float) ));
+extern struct ompi_predefined_datatype_t ompi_mpi_int __attribute__(( type_tag_for_datatype(mpi,int) ));
+extern struct ompi_predefined_datatype_t ompi_mpi_long __attribute__(( type_tag_for_datatype(mpi,long) ));
+extern struct ompi_predefined_datatype_t ompi_mpi_long_long_int __attribute__(( type_tag_for_datatype(mpi,long long int) ));
+extern struct ompi_predefined_datatype_t ompi_mpi_char __attribute__(( type_tag_for_datatype(mpi,char) ));
+
+struct ompi_struct_mpi_float_int {float f; int i;};
+extern struct ompi_predefined_datatype_t ompi_mpi_float_int __attribute__(( type_tag_for_datatype(mpi, struct ompi_struct_mpi_float_int, layout_compatible) ));
+
+struct ompi_struct_mpi_2int {int i1; int i2;};
+extern struct ompi_predefined_datatype_t ompi_mpi_2int __attribute__(( type_tag_for_datatype(mpi, struct ompi_struct_mpi_2int, layout_compatible) ));
+#endif
+
+#ifdef MPICH
+// MPICH2 and MVAPICH2-style datatype definitions
+
+#define MPI_COMM_WORLD ((MPI_Comm) 0x44000000)
+
+#define MPI_DATATYPE_NULL ((MPI_Datatype) 0xa0000000)
+#define MPI_FLOAT ((MPI_Datatype) 0xa0000001)
+#define MPI_INT ((MPI_Datatype) 0xa0000002)
+#define MPI_LONG ((MPI_Datatype) 0xa0000003)
+#define MPI_LONG_LONG_INT ((MPI_Datatype) 0xa0000004)
+#define MPI_CHAR ((MPI_Datatype) 0xa0000005)
+
+#define MPI_FLOAT_INT ((MPI_Datatype) 0xa0000006)
+#define MPI_2INT ((MPI_Datatype) 0xa0000007)
+
+#define MPI_IN_PLACE (void *) -1
+
+static const MPI_Datatype mpich_mpi_datatype_null __attribute__(( type_tag_for_datatype(mpi,void,must_be_null) )) = 0xa0000000;
+static const MPI_Datatype mpich_mpi_float __attribute__(( type_tag_for_datatype(mpi,float) )) = 0xa0000001;
+static const MPI_Datatype mpich_mpi_int __attribute__(( type_tag_for_datatype(mpi,int) )) = 0xa0000002;
+static const MPI_Datatype mpich_mpi_long __attribute__(( type_tag_for_datatype(mpi,long) )) = 0xa0000003;
+static const MPI_Datatype mpich_mpi_long_long_int __attribute__(( type_tag_for_datatype(mpi,long long int) )) = 0xa0000004;
+static const MPI_Datatype mpich_mpi_char __attribute__(( type_tag_for_datatype(mpi,char) )) = 0xa0000005;
+
+struct mpich_struct_mpi_float_int { float f; int i; };
+struct mpich_struct_mpi_2int { int i1; int i2; };
+static const MPI_Datatype mpich_mpi_float_int __attribute__(( type_tag_for_datatype(mpi, struct mpich_struct_mpi_float_int, layout_compatible) )) = 0xa0000006;
+static const MPI_Datatype mpich_mpi_2int __attribute__(( type_tag_for_datatype(mpi, struct mpich_struct_mpi_2int, layout_compatible) )) = 0xa0000007;
+#endif
+
+//===--- HDF5 headers mock ------------------------------------------------===//
+
+typedef int hid_t;
+void H5open(void);
+
+#ifndef HDF_PRIVATE
+#define H5OPEN H5open(),
+#else
+#define H5OPEN
+#endif
+
+#define H5T_NATIVE_CHAR (CHAR_MIN?H5T_NATIVE_SCHAR:H5T_NATIVE_UCHAR)
+#define H5T_NATIVE_SCHAR (H5OPEN H5T_NATIVE_SCHAR_g)
+#define H5T_NATIVE_UCHAR (H5OPEN H5T_NATIVE_UCHAR_g)
+#define H5T_NATIVE_INT (H5OPEN H5T_NATIVE_INT_g)
+#define H5T_NATIVE_LONG (H5OPEN H5T_NATIVE_LONG_g)
+
+hid_t H5T_NATIVE_SCHAR_g __attribute__(( type_tag_for_datatype(hdf5,signed char) ));
+hid_t H5T_NATIVE_UCHAR_g __attribute__(( type_tag_for_datatype(hdf5,unsigned char) ));
+hid_t H5T_NATIVE_INT_g __attribute__(( type_tag_for_datatype(hdf5,int) ));
+hid_t H5T_NATIVE_LONG_g __attribute__(( type_tag_for_datatype(hdf5,long) ));
+
+void H5Dwrite(hid_t mem_type_id, const void *buf) __attribute__(( pointer_with_type_tag(hdf5,2,1) ));
+
+//===--- Tests ------------------------------------------------------------===//
+
+//===--- MPI
+
+struct pair_float_int
+{
+ float f; int i;
+};
+
+struct pair_int_int
+{
+ int i1; int i2;
+};
+
+void test_mpi_predefined_types(
+ int *int_buf,
+ long *long_buf1,
+ long *long_buf2,
+ void *void_buf,
+ struct pair_float_int *pfi,
+ struct pair_int_int *pii)
+{
+ char char_buf[255];
+
+ // Layout-compatible scalar types.
+ MPI_Send(int_buf, 1, MPI_INT); // no-warning
+
+ // Layout-compatible class types.
+ MPI_Send(pfi, 1, MPI_FLOAT_INT); // no-warning
+ MPI_Send(pii, 1, MPI_2INT); // no-warning
+
+ // Layout-incompatible scalar types.
+ MPI_Send(long_buf1, 1, MPI_INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}}
+
+ // Layout-incompatible class types.
+ MPI_Send(pii, 1, MPI_FLOAT_INT); // expected-warning {{argument type 'struct pair_int_int *' doesn't match specified 'mpi' type tag}}
+ MPI_Send(pfi, 1, MPI_2INT); // expected-warning {{argument type 'struct pair_float_int *' doesn't match specified 'mpi' type tag}}
+
+ // Layout-incompatible class-scalar types.
+ MPI_Send(long_buf1, 1, MPI_2INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag}}
+
+ // Function with two buffers.
+ MPI_Gather(long_buf1, 1, MPI_INT, // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}}
+ long_buf2, 1, MPI_INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}}
+
+ // Array buffers should work like pointer buffers.
+ MPI_Send(char_buf, 255, MPI_CHAR); // no-warning
+
+ // Explicit casts should not be dropped.
+ MPI_Send((int *) char_buf, 255, MPI_INT); // no-warning
+ MPI_Send((int *) char_buf, 255, MPI_CHAR); // expected-warning {{argument type 'int *' doesn't match specified 'mpi' type tag that requires 'char *'}}
+
+ // `void*' buffer should never warn.
+ MPI_Send(void_buf, 255, MPI_CHAR); // no-warning
+
+ // We expect that MPI_IN_PLACE is `void*', shouldn't warn.
+ MPI_Gather(MPI_IN_PLACE, 0, MPI_INT,
+ int_buf, 1, MPI_INT);
+
+ // Special handling for MPI_DATATYPE_NULL: buffer pointer should be either
+ // a `void*' pointer or a null pointer constant.
+ MPI_Gather(NULL, 0, MPI_DATATYPE_NULL, // no-warning
+ int_buf, 1, MPI_INT);
+
+ MPI_Gather(int_buf, 0, MPI_DATATYPE_NULL, // expected-warning {{specified mpi type tag requires a null pointer}}
+ int_buf, 1, MPI_INT);
+}
+
+MPI_Datatype my_int_datatype __attribute__(( type_tag_for_datatype(mpi,int) ));
+
+struct S1 { int a; int b; };
+MPI_Datatype my_s1_datatype __attribute__(( type_tag_for_datatype(mpi,struct S1) ));
+
+// Layout-compatible to S1, but should be treated as a different type.
+struct S2 { int a; int b; };
+MPI_Datatype my_s2_datatype __attribute__(( type_tag_for_datatype(mpi,struct S2) ));
+
+void test_user_types(int *int_buf,
+ long *long_buf,
+ struct S1 *s1_buf,
+ struct S2 *s2_buf)
+{
+ MPI_Send(int_buf, 1, my_int_datatype); // no-warning
+ MPI_Send(long_buf, 1, my_int_datatype); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}}
+
+ MPI_Send(s1_buf, 1, my_s1_datatype); // no-warning
+ MPI_Send(s1_buf, 1, my_s2_datatype); // expected-warning {{argument type 'struct S1 *' doesn't match specified 'mpi' type tag that requires 'struct S2 *'}}
+
+ MPI_Send(long_buf, 1, my_s1_datatype); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'struct S1 *'}}
+ MPI_Send(s1_buf, 1, MPI_INT); // expected-warning {{argument type 'struct S1 *' doesn't match specified 'mpi' type tag that requires 'int *'}}
+}
+
+MPI_Datatype my_unknown_datatype;
+
+void test_not_annotated(int *int_buf,
+ long *long_buf,
+ MPI_Datatype type)
+{
+ // Using 'MPI_Datatype's without attributes should not produce warnings.
+ MPI_Send(long_buf, 1, my_unknown_datatype); // no-warning
+ MPI_Send(int_buf, 1, type); // no-warning
+}
+
+struct S1_compat { int a; int b; };
+MPI_Datatype my_s1_compat_datatype
+ __attribute__(( type_tag_for_datatype(mpi, struct S1_compat, layout_compatible) ));
+
+struct S3 { int a; long b; double c; double d; struct S1 s1; };
+struct S3_compat { int a; long b; double c; double d; struct S2 s2; };
+MPI_Datatype my_s3_compat_datatype
+ __attribute__(( type_tag_for_datatype(mpi, struct S3_compat, layout_compatible) ));
+
+struct S4 { char c; };
+struct S4_compat { signed char c; };
+MPI_Datatype my_s4_compat_datatype
+ __attribute__(( type_tag_for_datatype(mpi, struct S4_compat, layout_compatible) ));
+
+union U1 { int a; long b; double c; double d; struct S1 s1; };
+union U1_compat { long b; double c; struct S2 s; int a; double d; };
+MPI_Datatype my_u1_compat_datatype
+ __attribute__(( type_tag_for_datatype(mpi, union U1_compat, layout_compatible) ));
+
+union U2 { int a; long b; double c; struct S1 s1; };
+MPI_Datatype my_u2_datatype
+ __attribute__(( type_tag_for_datatype(mpi, union U2, layout_compatible) ));
+
+void test_layout_compatibility(struct S1 *s1_buf, struct S3 *s3_buf,
+ struct S4 *s4_buf,
+ union U1 *u1_buf, union U2 *u2_buf)
+{
+ MPI_Send(s1_buf, 1, my_s1_compat_datatype); // no-warning
+ MPI_Send(s3_buf, 1, my_s3_compat_datatype); // no-warning
+ MPI_Send(s1_buf, 1, my_s3_compat_datatype); // expected-warning {{argument type 'struct S1 *' doesn't match specified 'mpi' type tag}}
+ MPI_Send(s4_buf, 1, my_s4_compat_datatype); // expected-warning {{argument type 'struct S4 *' doesn't match specified 'mpi' type tag}}
+ MPI_Send(u1_buf, 1, my_u1_compat_datatype); // no-warning
+ MPI_Send(u1_buf, 1, my_u2_datatype); // expected-warning {{argument type 'union U1 *' doesn't match specified 'mpi' type tag}}
+ MPI_Send(u2_buf, 1, my_u1_compat_datatype); // expected-warning {{argument type 'union U2 *' doesn't match specified 'mpi' type tag}}
+}
+
+// There is an MPI_REAL predefined in MPI, but some existing MPI programs do
+// this.
+typedef float real;
+#define MPI_REAL MPI_FLOAT
+
+void test_mpi_real_user_type(real *real_buf, float *float_buf)
+{
+ MPI_Send(real_buf, 1, MPI_REAL); // no-warning
+ MPI_Send(real_buf, 1, MPI_FLOAT); // no-warning
+ MPI_Send(float_buf, 1, MPI_REAL); // no-warning
+ MPI_Send(float_buf, 1, MPI_FLOAT); // no-warning
+}
+
+//===--- HDF5
+
+void test_hdf5(char *char_buf,
+ signed char *schar_buf,
+ unsigned char *uchar_buf,
+ int *int_buf,
+ long *long_buf)
+{
+ H5Dwrite(H5T_NATIVE_CHAR, char_buf); // no-warning
+#ifdef __CHAR_UNSIGNED__
+ H5Dwrite(H5T_NATIVE_CHAR, schar_buf); // expected-warning {{argument type 'signed char *' doesn't match specified 'hdf5' type tag that requires 'unsigned char *'}}
+ H5Dwrite(H5T_NATIVE_CHAR, uchar_buf); // no-warning
+#else
+ H5Dwrite(H5T_NATIVE_CHAR, schar_buf); // no-warning
+ H5Dwrite(H5T_NATIVE_CHAR, uchar_buf); // expected-warning {{argument type 'unsigned char *' doesn't match specified 'hdf5' type tag that requires 'signed char *'}}
+#endif
+ H5Dwrite(H5T_NATIVE_SCHAR, schar_buf); // no-warning
+ H5Dwrite(H5T_NATIVE_UCHAR, uchar_buf); // no-warning
+ H5Dwrite(H5T_NATIVE_INT, int_buf); // no-warning
+ H5Dwrite(H5T_NATIVE_LONG, long_buf); // no-warning
+
+#ifdef __CHAR_UNSIGNED__
+ H5Dwrite(H5T_NATIVE_CHAR, int_buf); // expected-warning {{argument type 'int *' doesn't match specified 'hdf5' type tag that requires 'unsigned char *'}}
+#else
+ H5Dwrite(H5T_NATIVE_CHAR, int_buf); // expected-warning {{argument type 'int *' doesn't match specified 'hdf5' type tag that requires 'signed char *'}}
+#endif
+ H5Dwrite(H5T_NATIVE_INT, long_buf); // expected-warning {{argument type 'long *' doesn't match specified 'hdf5' type tag that requires 'int *'}}
+
+ // FIXME: we should warn here, but it will cause false positives because
+ // different kinds may use same magic values.
+ //H5Dwrite(MPI_INT, int_buf);
+}
+
diff --git a/test/Sema/warn-type-safety.c b/test/Sema/warn-type-safety.c
new file mode 100644
index 0000000..6f548aa
--- /dev/null
+++ b/test/Sema/warn-type-safety.c
@@ -0,0 +1,152 @@
+// RUN: %clang_cc1 -std=c99 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++ -std=c++98 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c99 -fno-signed-char -fsyntax-only -verify %s
+
+struct A {};
+
+typedef struct A *MPI_Datatype;
+
+int wrong1(void *buf, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag )); // expected-error {{attribute requires parameter 1 to be an identifier}}
+
+int wrong2(void *buf, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,0,7) )); // expected-error {{attribute parameter 2 is out of bounds}}
+
+int wrong3(void *buf, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,3,7) )); // expected-error {{attribute parameter 2 is out of bounds}}
+
+int wrong4(void *buf, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,1,0) )); // expected-error {{attribute parameter 3 is out of bounds}}
+
+int wrong5(void *buf, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,1,3) )); // expected-error {{attribute parameter 3 is out of bounds}}
+
+int wrong6(void *buf, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,0x8000000000000001ULL,1) )); // expected-error {{attribute parameter 2 is out of bounds}}
+
+extern int x;
+
+int wrong7(void *buf, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,x,2) )); // expected-error {{attribute requires parameter 2 to be an integer constant}}
+
+int wrong8(void *buf, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,1,x) )); // expected-error {{attribute requires parameter 3 to be an integer constant}}
+
+int wrong9 __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{attribute only applies to functions and methods}}
+
+int wrong10(double buf, MPI_Datatype type)
+ __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{'pointer_with_type_tag' attribute only applies to pointer arguments}}
+
+
+extern struct A datatype_wrong1
+ __attribute__(( type_tag_for_datatype )); // expected-error {{attribute requires parameter 1 to be an identifier}}
+
+extern struct A datatype_wrong2
+ __attribute__(( type_tag_for_datatype(mpi,1,2) )); // expected-error {{expected a type}}
+
+extern struct A datatype_wrong3
+ __attribute__(( type_tag_for_datatype(mpi,not_a_type) )); // expected-error {{unknown type name 'not_a_type'}}
+
+extern struct A datatype_wrong4
+ __attribute__(( type_tag_for_datatype(mpi,int,int) )); // expected-error {{expected identifier}}
+
+extern struct A datatype_wrong5
+ __attribute__(( type_tag_for_datatype(mpi,int,not_a_flag) )); // expected-error {{invalid comparison flag 'not_a_flag'}}
+
+extern struct A datatype_wrong6
+ __attribute__(( type_tag_for_datatype(mpi,int,layout_compatible,not_a_flag) )); // expected-error {{invalid comparison flag 'not_a_flag'}}
+
+
+// Using a tag with kind A in a place where the function requires kind B should
+// warn.
+
+void A_func(void *ptr, void *tag) __attribute__(( pointer_with_type_tag(a,1,2) ));
+
+extern struct A A_tag __attribute__(( type_tag_for_datatype(a,int) ));
+extern struct A B_tag __attribute__(( type_tag_for_datatype(b,int) ));
+
+void C_func(void *ptr, int tag) __attribute__(( pointer_with_type_tag(c,1,2) ));
+
+static const int C_tag __attribute__(( type_tag_for_datatype(c,int) )) = 10;
+static const int D_tag __attribute__(( type_tag_for_datatype(d,int) )) = 20;
+
+void test_tag_mismatch(int *ptr)
+{
+ A_func(ptr, &A_tag); // no-warning
+ A_func(ptr, &B_tag); // expected-warning {{this type tag was not designed to be used with this function}}
+ C_func(ptr, C_tag); // no-warning
+ C_func(ptr, D_tag); // expected-warning {{this type tag was not designed to be used with this function}}
+ C_func(ptr, 10); // no-warning
+ C_func(ptr, 20); // should warn, but may cause false positives
+}
+
+// Check that we look through typedefs in the special case of allowing 'char'
+// to be matched with 'signed char' or 'unsigned char'.
+void E_func(void *ptr, int tag) __attribute__(( pointer_with_type_tag(e,1,2) ));
+
+typedef char E_char;
+typedef char E_char_2;
+typedef signed char E_char_signed;
+typedef unsigned char E_char_unsigned;
+
+static const int E_tag __attribute__(( type_tag_for_datatype(e,E_char) )) = 10;
+
+void test_char_typedef(char *char_buf,
+ E_char_2 *e_char_buf,
+ E_char_signed *e_char_signed_buf,
+ E_char_unsigned *e_char_unsigned_buf)
+{
+ E_func(char_buf, E_tag);
+ E_func(e_char_buf, E_tag);
+#ifdef __CHAR_UNSIGNED__
+ E_func(e_char_signed_buf, E_tag); // expected-warning {{argument type 'E_char_signed *' (aka 'signed char *') doesn't match specified 'e' type tag that requires 'E_char *' (aka 'char *')}}
+ E_func(e_char_unsigned_buf, E_tag);
+#else
+ E_func(e_char_signed_buf, E_tag);
+ E_func(e_char_unsigned_buf, E_tag); // expected-warning {{argument type 'E_char_unsigned *' (aka 'unsigned char *') doesn't match specified 'e' type tag that requires 'E_char *' (aka 'char *')}}
+#endif
+}
+
+// Tests for argument_with_type_tag.
+
+#define F_DUPFD 10
+#define F_SETLK 20
+
+struct flock { };
+
+static const int F_DUPFD_tag __attribute__(( type_tag_for_datatype(fcntl,int) )) = F_DUPFD;
+static const int F_SETLK_tag __attribute__(( type_tag_for_datatype(fcntl,struct flock *) )) = F_SETLK;
+
+int fcntl(int fd, int cmd, ...) __attribute__(( argument_with_type_tag(fcntl,3,2) ));
+
+void test_argument_with_type_tag(struct flock *f)
+{
+ fcntl(0, F_DUPFD, 10); // no-warning
+ fcntl(0, F_SETLK, f); // no-warning
+
+ fcntl(0, F_SETLK, 10); // expected-warning {{argument type 'int' doesn't match specified 'fcntl' type tag that requires 'struct flock *'}}
+ fcntl(0, F_DUPFD, f); // expected-warning {{argument type 'struct flock *' doesn't match specified 'fcntl' type tag that requires 'int'}}
+}
+
+void test_tag_expresssion(int b) {
+ fcntl(0, b ? F_DUPFD : F_SETLK, 10); // no-warning
+ fcntl(0, b + F_DUPFD, 10); // no-warning
+ fcntl(0, (b, F_DUPFD), 10); // expected-warning {{expression result unused}}
+}
+
+// Check that using 64-bit magic values as tags works and tag values do not
+// overflow internally.
+void F_func(void *ptr, unsigned long long tag) __attribute__((pointer_with_type_tag(f,1,2) ));
+
+static const unsigned long long F_tag1 __attribute__(( type_tag_for_datatype(f,int) )) = 0xFFFFFFFFFFFFFFFFULL;
+static const unsigned long long F_tag2 __attribute__(( type_tag_for_datatype(f,float) )) = 0xFFFFFFFFULL;
+
+void test_64bit_magic(int *int_ptr, float *float_ptr)
+{
+ F_func(int_ptr, 0xFFFFFFFFFFFFFFFFULL);
+ F_func(int_ptr, 0xFFFFFFFFULL); // expected-warning {{argument type 'int *' doesn't match specified 'f' type tag that requires 'float *'}}
+ F_func(float_ptr, 0xFFFFFFFFFFFFFFFFULL); // expected-warning {{argument type 'float *' doesn't match specified 'f' type tag that requires 'int *'}}
+ F_func(float_ptr, 0xFFFFFFFFULL);
+}
+
+
diff --git a/test/Sema/warn-type-safety.cpp b/test/Sema/warn-type-safety.cpp
new file mode 100644
index 0000000..d053fba
--- /dev/null
+++ b/test/Sema/warn-type-safety.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+typedef struct ompi_datatype_t *MPI_Datatype;
+
+#define OMPI_PREDEFINED_GLOBAL(type, global) ((type) &(global))
+
+#define MPI_FLOAT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_float)
+#define MPI_INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_int)
+#define MPI_NULL OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_null)
+
+extern struct ompi_predefined_datatype_t ompi_mpi_float __attribute__(( type_tag_for_datatype(mpi,float) ));
+extern struct ompi_predefined_datatype_t ompi_mpi_int __attribute__(( type_tag_for_datatype(mpi,int) ));
+extern struct ompi_predefined_datatype_t ompi_mpi_null __attribute__(( type_tag_for_datatype(mpi,void,must_be_null) ));
+
+int f(int x) { return x; }
+static const int wrong_init __attribute__(( type_tag_for_datatype(zzz,int) )) = f(100); // expected-error {{'type_tag_for_datatype' attribute requires the initializer to be an integral constant expression}}
+
+//===--- Tests ------------------------------------------------------------===//
+// Check that hidden 'this' is handled correctly.
+
+class C
+{
+public:
+ void f1(void *buf, int count, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,5,6) )); // expected-error {{attribute parameter 2 is out of bounds}}
+
+ void f2(void *buf, int count, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,2,5) )); // expected-error {{attribute parameter 3 is out of bounds}}
+
+ void f3(void *buf, int count, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,1,5) )); // expected-error {{attribute is invalid for the implicit this argument}}
+
+ void f4(void *buf, int count, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,2,1) )); // expected-error {{attribute is invalid for the implicit this argument}}
+
+ void MPI_Send(void *buf, int count, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,2,4) )); // no-error
+};
+
+// Check that we don't crash on type and value dependent expressions.
+template<int a>
+void value_dep(void *buf, int count, MPI_Datatype datatype)
+ __attribute__(( pointer_with_type_tag(mpi,a,5) )); // expected-error {{attribute requires parameter 2 to be an integer constant}}
+
+class OperatorIntStar
+{
+public:
+ operator int*();
+};
+
+void test1(C *c, int *int_buf)
+{
+ c->MPI_Send(int_buf, 1, MPI_INT); // no-warning
+ c->MPI_Send(int_buf, 1, MPI_FLOAT); // expected-warning {{argument type 'int *' doesn't match specified 'mpi' type tag that requires 'float *'}}
+
+ OperatorIntStar i;
+ c->MPI_Send(i, 1, MPI_INT); // no-warning
+ c->MPI_Send(i, 1, MPI_FLOAT); // expected-warning {{argument type 'int *' doesn't match specified 'mpi' type tag that requires 'float *'}}
+}
+
+template<typename T>
+void test2(C *c, int *int_buf, T tag)
+{
+ c->MPI_Send(int_buf, 1, tag); // no-warning
+}
+
+void test3(C *c, int *int_buf) {
+ test2(c, int_buf, MPI_INT);
+ test2(c, int_buf, MPI_NULL);
+}
+
OpenPOWER on IntegriCloud