xref: /llvm-project/clang/test/SemaCXX/pass-object-size.cpp (revision 7204ed97dd930e0cb159985a5973bc9993740726)
108a4a8c3SGeorge Burgess IV // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
208a4a8c3SGeorge Burgess IV 
308a4a8c3SGeorge Burgess IV namespace simple {
408a4a8c3SGeorge Burgess IV int Foo(void *const p __attribute__((pass_object_size(0))));
508a4a8c3SGeorge Burgess IV 
608a4a8c3SGeorge Burgess IV int OvlFoo(void *const p __attribute__((pass_object_size(0))));
708a4a8c3SGeorge Burgess IV int OvlFoo(void *const p, int);
808a4a8c3SGeorge Burgess IV 
908a4a8c3SGeorge Burgess IV struct Statics {
1008a4a8c3SGeorge Burgess IV   static int Foo(void *const p __attribute__((pass_object_size(0))));
1108a4a8c3SGeorge Burgess IV   static int OvlFoo(void *const p __attribute__((pass_object_size(0))));
1208a4a8c3SGeorge Burgess IV   static int OvlFoo(void *const p __attribute__((pass_object_size(1)))); // expected-error{{conflicting pass_object_size attributes on parameters}} expected-note@-1{{previous declaration is here}}
1308a4a8c3SGeorge Burgess IV   static int OvlFoo(double *p);
1408a4a8c3SGeorge Burgess IV };
1508a4a8c3SGeorge Burgess IV 
1608a4a8c3SGeorge Burgess IV struct Members {
1708a4a8c3SGeorge Burgess IV   int Foo(void *const p __attribute__((pass_object_size(0))));
1808a4a8c3SGeorge Burgess IV   int OvlFoo(void *const p __attribute__((pass_object_size(0))));
1908a4a8c3SGeorge Burgess IV   int OvlFoo(void *const p, int);
2008a4a8c3SGeorge Burgess IV };
2108a4a8c3SGeorge Burgess IV 
Decls()2208a4a8c3SGeorge Burgess IV void Decls() {
2308a4a8c3SGeorge Burgess IV   int (*A)(void *) = &Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
2408a4a8c3SGeorge Burgess IV   int (*B)(void *) = Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
2508a4a8c3SGeorge Burgess IV 
2608a4a8c3SGeorge Burgess IV   int (*C)(void *) = &OvlFoo; //expected-error{{address of overloaded function 'OvlFoo' does not match required type 'int (void *)'}} expected-note@6{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@7{{candidate function has different number of parameters (expected 1 but has 2)}}
2708a4a8c3SGeorge Burgess IV   int (*D)(void *) = OvlFoo; //expected-error{{address of overloaded function 'OvlFoo' does not match required type 'int (void *)'}} expected-note@6{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@7{{candidate function has different number of parameters (expected 1 but has 2)}}
2808a4a8c3SGeorge Burgess IV 
2908a4a8c3SGeorge Burgess IV   int (*E)(void *) = &Statics::Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
3008a4a8c3SGeorge Burgess IV   int (*F)(void *) = &Statics::OvlFoo; //expected-error{{address of overloaded function 'OvlFoo' does not match required type 'int (void *)'}} expected-note@11{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@13{{candidate function has type mismatch at 1st parameter (expected 'void *' but has 'double *')}}
3108a4a8c3SGeorge Burgess IV 
3208a4a8c3SGeorge Burgess IV   int (*G)(void *) = &Members::Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
3308a4a8c3SGeorge Burgess IV   int (*H)(void *) = &Members::OvlFoo; //expected-error{{address of overloaded function 'OvlFoo' does not match required type 'int (void *)'}} expected-note@18{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@19{{candidate function has different number of parameters (expected 1 but has 2)}}
3408a4a8c3SGeorge Burgess IV }
3508a4a8c3SGeorge Burgess IV 
Assigns()3608a4a8c3SGeorge Burgess IV void Assigns() {
3708a4a8c3SGeorge Burgess IV   int (*A)(void *);
3808a4a8c3SGeorge Burgess IV   A = &Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
3908a4a8c3SGeorge Burgess IV   A = Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
4008a4a8c3SGeorge Burgess IV 
4108a4a8c3SGeorge Burgess IV   A = &OvlFoo; //expected-error{{assigning to 'int (*)(void *)' from incompatible type '<overloaded function type>'}} expected-note@6{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@7{{candidate function has different number of parameters (expected 1 but has 2)}}
4208a4a8c3SGeorge Burgess IV   A = OvlFoo; //expected-error{{assigning to 'int (*)(void *)' from incompatible type '<overloaded function type>'}} expected-note@6{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@7{{candidate function has different number of parameters (expected 1 but has 2)}}
4308a4a8c3SGeorge Burgess IV 
4408a4a8c3SGeorge Burgess IV   A = &Statics::Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
4508a4a8c3SGeorge Burgess IV   A = &Statics::OvlFoo; //expected-error{{assigning to 'int (*)(void *)' from incompatible type '<overloaded function type>'}} expected-note@11{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@13{{candidate function has type mismatch at 1st parameter (expected 'void *' but has 'double *')}}
4608a4a8c3SGeorge Burgess IV 
4708a4a8c3SGeorge Burgess IV   int (Members::*M)(void *);
4808a4a8c3SGeorge Burgess IV   M = &Members::Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
495e8701c3SGeorge Burgess IV   M = &Members::OvlFoo; //expected-error-re{{assigning to '{{.*}}' from incompatible type '<overloaded function type>'}} expected-note@18{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@19{{candidate function has different number of parameters (expected 1 but has 2)}}
5008a4a8c3SGeorge Burgess IV }
5108a4a8c3SGeorge Burgess IV 
5208a4a8c3SGeorge Burgess IV } // namespace simple
5308a4a8c3SGeorge Burgess IV 
5408a4a8c3SGeorge Burgess IV namespace templates {
5508a4a8c3SGeorge Burgess IV template <typename T>
Foo(void * const)5608a4a8c3SGeorge Burgess IV int Foo(void *const __attribute__((pass_object_size(0)))) {
5708a4a8c3SGeorge Burgess IV   return 0;
5808a4a8c3SGeorge Burgess IV }
5908a4a8c3SGeorge Burgess IV 
6008a4a8c3SGeorge Burgess IV template <typename T> struct Bar {
6108a4a8c3SGeorge Burgess IV   template <typename U>
Footemplates::Bar6208a4a8c3SGeorge Burgess IV   int Foo(void *const __attribute__((pass_object_size(0)))) {
6308a4a8c3SGeorge Burgess IV     return 0;
6408a4a8c3SGeorge Burgess IV   }
6508a4a8c3SGeorge Burgess IV };
6608a4a8c3SGeorge Burgess IV 
Decls()6708a4a8c3SGeorge Burgess IV void Decls() {
6808a4a8c3SGeorge Burgess IV   int (*A)(void *) = &Foo<void*>; //expected-error{{address of overloaded function 'Foo' does not match required type 'int (void *)'}} expected-note@56{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}}
695e8701c3SGeorge Burgess IV   int (Bar<int>::*B)(void *) = &Bar<int>::Foo<double>; //expected-error{{address of overloaded function 'Foo' does not match required type}} expected-note@62{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}}
7008a4a8c3SGeorge Burgess IV }
7108a4a8c3SGeorge Burgess IV 
Assigns()7208a4a8c3SGeorge Burgess IV void Assigns() {
7308a4a8c3SGeorge Burgess IV   int (*A)(void *);
7408a4a8c3SGeorge Burgess IV   A = &Foo<void*>; // expected-error{{assigning to 'int (*)(void *)' from incompatible type '<overloaded function type>'}} expected-note@56{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}}
755e8701c3SGeorge Burgess IV   int (Bar<int>::*B)(void *) = &Bar<int>::Foo<double>; //expected-error{{address of overloaded function 'Foo' does not match required type}} expected-note@62{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}}
7608a4a8c3SGeorge Burgess IV }
7708a4a8c3SGeorge Burgess IV } // namespace templates
7808a4a8c3SGeorge Burgess IV 
7908a4a8c3SGeorge Burgess IV namespace virt {
8008a4a8c3SGeorge Burgess IV struct Foo {
8108a4a8c3SGeorge Burgess IV   virtual void DoIt(void *const p __attribute__((pass_object_size(0))));
8208a4a8c3SGeorge Burgess IV };
8308a4a8c3SGeorge Burgess IV 
8408a4a8c3SGeorge Burgess IV struct Bar : public Foo {
8508a4a8c3SGeorge Burgess IV   void DoIt(void *const p __attribute__((pass_object_size(0)))) override; // OK
8608a4a8c3SGeorge Burgess IV };
8708a4a8c3SGeorge Burgess IV 
8808a4a8c3SGeorge Burgess IV struct Baz : public Foo {
8908a4a8c3SGeorge Burgess IV   void DoIt(void *const p) override; //expected-error{{non-virtual member function marked 'override' hides virtual member function}} expected-note@81{{hidden overloaded virtual function 'virt::Foo::DoIt' declared here}}
9008a4a8c3SGeorge Burgess IV };
9108a4a8c3SGeorge Burgess IV }
9208a4a8c3SGeorge Burgess IV 
9308a4a8c3SGeorge Burgess IV namespace why {
9408a4a8c3SGeorge Burgess IV void TakeFn(void (*)(int, void *));
9508a4a8c3SGeorge Burgess IV void ObjSize(int, void *const __attribute__((pass_object_size(0))));
9608a4a8c3SGeorge Burgess IV 
Check()9708a4a8c3SGeorge Burgess IV void Check() {
9808a4a8c3SGeorge Burgess IV   TakeFn(ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
9908a4a8c3SGeorge Burgess IV   TakeFn(&ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
10008a4a8c3SGeorge Burgess IV   TakeFn(*ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
10108a4a8c3SGeorge Burgess IV   TakeFn(*****ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
10208a4a8c3SGeorge Burgess IV   TakeFn(*****&ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
10308a4a8c3SGeorge Burgess IV 
10408a4a8c3SGeorge Burgess IV   void (*P)(int, void *) = ****ObjSize; //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
10508a4a8c3SGeorge Burgess IV   P = ****ObjSize; //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
10608a4a8c3SGeorge Burgess IV 
10708a4a8c3SGeorge Burgess IV   TakeFn((ObjSize)); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
10808a4a8c3SGeorge Burgess IV   TakeFn((void*)ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
10908a4a8c3SGeorge Burgess IV   TakeFn((decltype(P))((void*)ObjSize)); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
11008a4a8c3SGeorge Burgess IV }
11108a4a8c3SGeorge Burgess IV }
11208a4a8c3SGeorge Burgess IV 
11308a4a8c3SGeorge Burgess IV namespace constexpr_support {
getObjSizeType()11408a4a8c3SGeorge Burgess IV constexpr int getObjSizeType() { return 0; }
11508a4a8c3SGeorge Burgess IV void Foo(void *p __attribute__((pass_object_size(getObjSizeType()))));
11608a4a8c3SGeorge Burgess IV }
11708a4a8c3SGeorge Burgess IV 
11808a4a8c3SGeorge Burgess IV namespace lambdas {
Bar()11908a4a8c3SGeorge Burgess IV void Bar() {
12008a4a8c3SGeorge Burgess IV   (void)+[](void *const p __attribute__((pass_object_size(0)))) {}; //expected-error-re{{invalid argument type '(lambda at {{.*}})' to unary expression}}
12108a4a8c3SGeorge Burgess IV }
12208a4a8c3SGeorge Burgess IV }
123*7204ed97SGeorge Burgess IV 
124*7204ed97SGeorge Burgess IV namespace ovlbug {
125*7204ed97SGeorge Burgess IV // Directly calling an address-of function expression (e.g. in (&foo)(args...))
126*7204ed97SGeorge Burgess IV // doesn't go through regular address-of-overload logic. This caused the above
127*7204ed97SGeorge Burgess IV // code to generate an ICE.
128*7204ed97SGeorge Burgess IV void DirectAddrOf(void *__attribute__((pass_object_size(0))));
129*7204ed97SGeorge Burgess IV void DirectAddrOfOvl(void *__attribute__((pass_object_size(0))));
130*7204ed97SGeorge Burgess IV void DirectAddrOfOvl(int *);
131*7204ed97SGeorge Burgess IV 
Test()132*7204ed97SGeorge Burgess IV void Test() {
133*7204ed97SGeorge Burgess IV   (&DirectAddrOf)(nullptr); //expected-error{{cannot take address of function 'DirectAddrOf' because parameter 1 has pass_object_size attribute}}
134*7204ed97SGeorge Burgess IV   (&DirectAddrOfOvl)((char*)nullptr); //expected-error{{no matching function}} expected-note@129{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@130{{candidate function not viable: no known conversion from 'char *' to 'int *' for 1st argument}}
135*7204ed97SGeorge Burgess IV }
136*7204ed97SGeorge Burgess IV }
137