reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
// RUN: %clang_cc1 -std=c++14 -triple i686-pc-win32 -fms-extensions -DMSABI -verify %s
// RUN: %clang_cc1 -std=c++14 -triple i686-pc-mingw32 -verify %s
// RUN: %clang_cc1 -std=c++14 -triple i686-pc-mingw32 -fms-extensions -verify %s

typedef void void_fun_t();
typedef void __cdecl cdecl_fun_t();

// Pointers to free functions
void            free_func_default(); // expected-note 2 {{previous declaration is here}}
void __cdecl    free_func_cdecl(); // expected-note 2 {{previous declaration is here}}
void __stdcall  free_func_stdcall(); // expected-note 2 {{previous declaration is here}}
void __fastcall free_func_fastcall(); // expected-note 2 {{previous declaration is here}}
void __vectorcall free_func_vectorcall(); // expected-note 2 {{previous declaration is here}}

void __cdecl    free_func_default();
void __stdcall  free_func_default(); // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
void __fastcall free_func_default(); // expected-error {{function declared 'fastcall' here was previously declared without calling convention}}

void            free_func_cdecl();
void __stdcall  free_func_cdecl(); // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}}
void __fastcall free_func_cdecl(); // expected-error {{function declared 'fastcall' here was previously declared 'cdecl'}}

void            free_func_stdcall();
void __cdecl    free_func_stdcall(); // expected-error {{function declared 'cdecl' here was previously declared 'stdcall'}}
void __fastcall free_func_stdcall(); // expected-error {{function declared 'fastcall' here was previously declared 'stdcall'}}

void __cdecl    free_func_fastcall(); // expected-error {{function declared 'cdecl' here was previously declared 'fastcall'}}
void __stdcall  free_func_fastcall(); // expected-error {{function declared 'stdcall' here was previously declared 'fastcall'}}
void            free_func_fastcall();

void __cdecl    free_func_vectorcall(); // expected-error {{function declared 'cdecl' here was previously declared 'vectorcall'}}
void __stdcall  free_func_vectorcall(); // expected-error {{function declared 'stdcall' here was previously declared 'vectorcall'}}
void            free_func_vectorcall();

// Overloaded functions may have different calling conventions
void __fastcall free_func_default(int);
void __cdecl    free_func_default(int *);

void __thiscall free_func_cdecl(char *);
void __cdecl    free_func_cdecl(double);

typedef void void_fun_t();
typedef void __cdecl cdecl_fun_t();

// Pointers to member functions
struct S {
  void            member_default1(); // expected-note {{previous declaration is here}}
  void            member_default2();
  void __cdecl    member_cdecl1();
  void __cdecl    member_cdecl2(); // expected-note {{previous declaration is here}}
  void __thiscall member_thiscall1();
  void __thiscall member_thiscall2(); // expected-note {{previous declaration is here}}
  void __vectorcall member_vectorcall1();
  void __vectorcall member_vectorcall2(); // expected-note {{previous declaration is here}}

  // Typedefs carrying the __cdecl convention are adjusted to __thiscall.
  void_fun_t           member_typedef_default; // expected-note {{previous declaration is here}}
  cdecl_fun_t          member_typedef_cdecl1;  // expected-note {{previous declaration is here}}
  cdecl_fun_t __cdecl  member_typedef_cdecl2;
  void_fun_t __stdcall member_typedef_stdcall;

  // Static member functions can't be __thiscall
  static void            static_member_default1();
  static void            static_member_default2();
  static void            static_member_default3(); // expected-note {{previous declaration is here}}
  static void __cdecl    static_member_cdecl1();
  static void __cdecl    static_member_cdecl2(); // expected-note {{previous declaration is here}}
  static void __stdcall  static_member_stdcall1();
  static void __stdcall  static_member_stdcall2();

  // Variadic functions can't be other than default or __cdecl
  void            member_variadic_default(int x, ...);
  void __cdecl    member_variadic_cdecl(int x, ...);

  static void            static_member_variadic_default(int x, ...);
  static void __cdecl    static_member_variadic_cdecl(int x, ...);

  // Structors can't be other than default in MS ABI environment
#ifdef MSABI
  __vectorcall S(); // expected-warning {{vectorcall calling convention is not supported on constructor/destructor}}
#endif
};

void __cdecl    S::member_default1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}
void __thiscall S::member_default2() {}

void __cdecl   S::member_typedef_default() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}
void __cdecl   S::member_typedef_cdecl1() {} // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}
void __cdecl   S::member_typedef_cdecl2() {}
void __stdcall S::member_typedef_stdcall() {}

void            S::member_cdecl1() {}
void __thiscall S::member_cdecl2() {} // expected-error {{function declared 'thiscall' here was previously declared 'cdecl'}}

void            S::member_thiscall1() {}
void __cdecl    S::member_thiscall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'thiscall'}}

void            S::member_vectorcall1() {}
void __cdecl    S::member_vectorcall2() {} // expected-error {{function declared 'cdecl' here was previously declared 'vectorcall'}}

void            S::static_member_default1() {}
void __cdecl    S::static_member_default2() {}
void __stdcall  S::static_member_default3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}

void            S::static_member_cdecl1() {}
void __stdcall  S::static_member_cdecl2() {} // expected-error {{function declared 'stdcall' here was previously declared 'cdecl'}}

void __cdecl    S::member_variadic_default(int x, ...) { (void)x; }
void            S::member_variadic_cdecl(int x, ...) { (void)x; }

void __cdecl    S::static_member_variadic_default(int x, ...) { (void)x; }
void            S::static_member_variadic_cdecl(int x, ...) { (void)x; }

// Declare a template using a calling convention.
template <class CharT> inline int __cdecl mystrlen(const CharT *str) {
  int i;
  for (i = 0; str[i]; i++) { }
  return i;
}
extern int sse_strlen(const char *str);
template <> inline int __cdecl mystrlen(const char *str) {
  return sse_strlen(str);
}
void use_tmpl(const char *str, const int *ints) {
  mystrlen(str);
  mystrlen(ints);
}

struct MixedCCStaticOverload {
  static void overloaded(int a);
  static void __stdcall overloaded(short a);
};

void MixedCCStaticOverload::overloaded(int a) {}
void MixedCCStaticOverload::overloaded(short a) {}

// Friend function decls are cdecl by default, not thiscall.  Friend method
// decls should always be redeclarations, because the class cannot be
// incomplete.
struct FriendClass {
  void friend_method() {}
};
void __stdcall friend_stdcall1() {}
class MakeFriendDecls {
  int x;
  friend void FriendClass::friend_method();
  friend void              friend_default();
  friend void              friend_stdcall1();
  friend void __stdcall    friend_stdcall2();
  friend void              friend_stdcall3(); // expected-note {{previous declaration is here}}
};
void           friend_default() {}
void __stdcall friend_stdcall3() {} // expected-error {{function declared 'stdcall' here was previously declared without calling convention}}
void __stdcall friend_stdcall2() {}

// Test functions with multiple attributes.
void __attribute__((noreturn)) __stdcall __attribute__((regparm(1))) multi_attribute(int x);
void multi_attribute(int x) { __builtin_unreachable(); }


// expected-error@+3 {{vectorcall and cdecl attributes are not compatible}}
// expected-error@+2 {{stdcall and cdecl attributes are not compatible}}
// expected-error@+1 {{fastcall and cdecl attributes are not compatible}}
void __cdecl __cdecl __stdcall __cdecl __fastcall __vectorcall multi_cc(int x);

template <typename T> void __stdcall StdcallTemplate(T) {}
template <> void StdcallTemplate<int>(int) {}
template <> void __stdcall StdcallTemplate<short>(short) {}

// FIXME: Note the template, not the implicit instantiation.
// expected-error@+2 {{function declared 'cdecl' here was previously declared 'stdcall}}
// expected-note@+1 {{previous declaration is here}}
template <> void __cdecl StdcallTemplate<long>(long) {}

struct ExactlyInt {
  template <typename T> static int cast_to_int(T) {
    return T::this_is_not_an_int();
  }
};
template <> inline int ExactlyInt::cast_to_int<int>(int x) { return x; }

namespace test2 {
  class foo {
    template <typename T> void bar(T v);
  };
  extern template void foo::bar(const void *);
}

namespace test3 {
  struct foo {
    typedef void bar();
  };
  bool zed(foo::bar *);
  void bah() {}
  void baz() { zed(bah); }
}

namespace test4 {
  class foo {
    template <typename T> static void bar(T v);
  };
  extern template void foo::bar(const void *);
}

namespace test5 {
  template <class T>
  class valarray {
    void bar();
  };
  extern template void valarray<int>::bar();
}

namespace test6 {
  struct foo {
    int bar();
  };
  typedef int bar_t();
  void zed(bar_t foo::*) {
  }
  void baz() {
    zed(&foo::bar);
  }
}

namespace test7 {
  template <typename T>
  struct S {
    void f(T t) {
      t = 42;
    }
  };
  template<> void S<void*>::f(void*);
  void g(S<void*> s, void* p) {
    s.f(p);
  }
}

namespace test8 {
  template <typename T>
  struct S {
    void f(T t) { // expected-note {{previous declaration is here}}
      t = 42; // expected-error {{assigning to 'void *' from incompatible type 'int'}}
    }
  };
  template<> void __cdecl S<void*>::f(void*); // expected-error {{function declared 'cdecl' here was previously declared without calling convention}}
  void g(S<void*> s, void* p) {
    s.f(p); // expected-note {{in instantiation of member function 'test8::S<void *>::f' requested here}}
  }
}

namespace test9 {
  // Used to fail when we forgot to make lambda call operators use __thiscall.
  template <typename F>
  decltype(auto) deduce(F f) {
    return &decltype(f)::operator();
  }
  template <typename C, typename R, typename A>
  decltype(auto) signaturehelper(R (C::*f)(A) const) {
    return R();
  }
  void f() {
    auto l = [](int x) { return x * 2; };
    decltype(signaturehelper(deduce(l))) p;
  }
}