1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
2*f4a2713aSLionel Sambuc 
3*f4a2713aSLionel Sambuc typedef struct ompi_datatype_t *MPI_Datatype;
4*f4a2713aSLionel Sambuc 
5*f4a2713aSLionel Sambuc #define OMPI_PREDEFINED_GLOBAL(type, global) ((type) &(global))
6*f4a2713aSLionel Sambuc 
7*f4a2713aSLionel Sambuc #define MPI_FLOAT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_float)
8*f4a2713aSLionel Sambuc #define MPI_INT   OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_int)
9*f4a2713aSLionel Sambuc #define MPI_NULL  OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_null)
10*f4a2713aSLionel Sambuc 
11*f4a2713aSLionel Sambuc extern struct ompi_predefined_datatype_t ompi_mpi_float __attribute__(( type_tag_for_datatype(mpi,float) ));
12*f4a2713aSLionel Sambuc extern struct ompi_predefined_datatype_t ompi_mpi_int   __attribute__(( type_tag_for_datatype(mpi,int) ));
13*f4a2713aSLionel Sambuc extern struct ompi_predefined_datatype_t ompi_mpi_null  __attribute__(( type_tag_for_datatype(mpi,void,must_be_null) ));
14*f4a2713aSLionel Sambuc 
f(int x)15*f4a2713aSLionel Sambuc int f(int x) { return x; }
16*f4a2713aSLionel Sambuc 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}}
17*f4a2713aSLionel Sambuc 
18*f4a2713aSLionel Sambuc //===--- Tests ------------------------------------------------------------===//
19*f4a2713aSLionel Sambuc // Check that hidden 'this' is handled correctly.
20*f4a2713aSLionel Sambuc 
21*f4a2713aSLionel Sambuc class C
22*f4a2713aSLionel Sambuc {
23*f4a2713aSLionel Sambuc public:
24*f4a2713aSLionel Sambuc   void f1(void *buf, int count, MPI_Datatype datatype)
25*f4a2713aSLionel Sambuc        __attribute__(( pointer_with_type_tag(mpi,5,6) )); // expected-error {{attribute parameter 2 is out of bounds}}
26*f4a2713aSLionel Sambuc 
27*f4a2713aSLionel Sambuc   void f2(void *buf, int count, MPI_Datatype datatype)
28*f4a2713aSLionel Sambuc        __attribute__(( pointer_with_type_tag(mpi,2,5) )); // expected-error {{attribute parameter 3 is out of bounds}}
29*f4a2713aSLionel Sambuc 
30*f4a2713aSLionel Sambuc   void f3(void *buf, int count, MPI_Datatype datatype)
31*f4a2713aSLionel Sambuc        __attribute__(( pointer_with_type_tag(mpi,1,5) )); // expected-error {{attribute is invalid for the implicit this argument}}
32*f4a2713aSLionel Sambuc 
33*f4a2713aSLionel Sambuc   void f4(void *buf, int count, MPI_Datatype datatype)
34*f4a2713aSLionel Sambuc        __attribute__(( pointer_with_type_tag(mpi,2,1) )); // expected-error {{attribute is invalid for the implicit this argument}}
35*f4a2713aSLionel Sambuc 
36*f4a2713aSLionel Sambuc   void MPI_Send(void *buf, int count, MPI_Datatype datatype)
37*f4a2713aSLionel Sambuc        __attribute__(( pointer_with_type_tag(mpi,2,4) )); // no-error
38*f4a2713aSLionel Sambuc };
39*f4a2713aSLionel Sambuc 
40*f4a2713aSLionel Sambuc // Check that we don't crash on type and value dependent expressions.
41*f4a2713aSLionel Sambuc template<int a>
42*f4a2713aSLionel Sambuc void value_dep(void *buf, int count, MPI_Datatype datatype)
43*f4a2713aSLionel Sambuc      __attribute__(( pointer_with_type_tag(mpi,a,5) )); // expected-error {{attribute requires parameter 2 to be an integer constant}}
44*f4a2713aSLionel Sambuc 
45*f4a2713aSLionel Sambuc class OperatorIntStar
46*f4a2713aSLionel Sambuc {
47*f4a2713aSLionel Sambuc public:
48*f4a2713aSLionel Sambuc   operator int*();
49*f4a2713aSLionel Sambuc };
50*f4a2713aSLionel Sambuc 
test1(C * c,int * int_buf)51*f4a2713aSLionel Sambuc void test1(C *c, int *int_buf)
52*f4a2713aSLionel Sambuc {
53*f4a2713aSLionel Sambuc   c->MPI_Send(int_buf, 1, MPI_INT); // no-warning
54*f4a2713aSLionel Sambuc   c->MPI_Send(int_buf, 1, MPI_FLOAT); // expected-warning {{argument type 'int *' doesn't match specified 'mpi' type tag that requires 'float *'}}
55*f4a2713aSLionel Sambuc   c->MPI_Send(0, 0, MPI_INT); // no-warning
56*f4a2713aSLionel Sambuc   c->MPI_Send(nullptr, 0, MPI_INT); // no-warning
57*f4a2713aSLionel Sambuc 
58*f4a2713aSLionel Sambuc   OperatorIntStar i;
59*f4a2713aSLionel Sambuc   c->MPI_Send(i, 1, MPI_INT); // no-warning
60*f4a2713aSLionel Sambuc   c->MPI_Send(i, 1, MPI_FLOAT); // expected-warning {{argument type 'int *' doesn't match specified 'mpi' type tag that requires 'float *'}}
61*f4a2713aSLionel Sambuc }
62*f4a2713aSLionel Sambuc 
63*f4a2713aSLionel Sambuc template<typename T>
test2(C * c,int * int_buf,T tag)64*f4a2713aSLionel Sambuc void test2(C *c, int *int_buf, T tag)
65*f4a2713aSLionel Sambuc {
66*f4a2713aSLionel Sambuc   c->MPI_Send(int_buf, 1, tag); // no-warning
67*f4a2713aSLionel Sambuc }
68*f4a2713aSLionel Sambuc 
test3(C * c,int * int_buf)69*f4a2713aSLionel Sambuc void test3(C *c, int *int_buf) {
70*f4a2713aSLionel Sambuc   test2(c, int_buf, MPI_INT);
71*f4a2713aSLionel Sambuc   test2(c, int_buf, MPI_NULL);
72*f4a2713aSLionel Sambuc }
73*f4a2713aSLionel Sambuc 
74