Add tests for pass_object_size.
authorGeorge Burgess IV <george.burgess.iv@gmail.com>
Thu, 3 Dec 2015 19:19:09 +0000 (19:19 +0000)
committerGeorge Burgess IV <george.burgess.iv@gmail.com>
Thu, 3 Dec 2015 19:19:09 +0000 (19:19 +0000)
These additions were meant to go in as a part of r254554; while it's
certainly nice to have new functionality, it's nicer if we have tests to
go with it. :)

llvm-svn: 254632

clang/test/CodeGen/pass-object-size.c [new file with mode: 0644]
clang/test/CodeGenCXX/pass-object-size.cpp [new file with mode: 0644]
clang/test/Sema/pass-object-size.c [new file with mode: 0644]
clang/test/SemaCXX/pass-object-size.cpp [new file with mode: 0644]

diff --git a/clang/test/CodeGen/pass-object-size.c b/clang/test/CodeGen/pass-object-size.c
new file mode 100644 (file)
index 0000000..1ad3f85
--- /dev/null
@@ -0,0 +1,353 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s
+
+typedef unsigned long size_t;
+
+struct Foo {
+  int t[10];
+};
+
+#define PS(N) __attribute__((pass_object_size(N)))
+
+int gi = 0;
+
+// CHECK-LABEL: define i32 @ObjectSize0(i8* %{{.*}}, i64)
+int ObjectSize0(void *const p PS(0)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 0);
+}
+
+// CHECK-LABEL: define i32 @ObjectSize1(i8* %{{.*}}, i64)
+int ObjectSize1(void *const p PS(1)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 1);
+}
+
+// CHECK-LABEL: define i32 @ObjectSize2(i8* %{{.*}}, i64)
+int ObjectSize2(void *const p PS(2)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 2);
+}
+
+// CHECK-LABEL: define i32 @ObjectSize3(i8* %{{.*}}, i64)
+int ObjectSize3(void *const p PS(3)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 3);
+}
+
+// CHECK-LABEL: define void @test1
+void test1() {
+  struct Foo t[10];
+
+  // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 360)
+  gi = ObjectSize0(&t[1]);
+  // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 360)
+  gi = ObjectSize1(&t[1]);
+  // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 360)
+  gi = ObjectSize2(&t[1]);
+  // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 360)
+  gi = ObjectSize3(&t[1]);
+
+  // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 356)
+  gi = ObjectSize0(&t[1].t[1]);
+  // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
+  gi = ObjectSize1(&t[1].t[1]);
+  // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 356)
+  gi = ObjectSize2(&t[1].t[1]);
+  // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
+  gi = ObjectSize3(&t[1].t[1]);
+}
+
+// CHECK-LABEL: define void @test2
+void test2(struct Foo *t) {
+  // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
+  gi = ObjectSize1(&t->t[1]);
+  // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
+  gi = ObjectSize3(&t->t[1]);
+}
+
+// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
+int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {
+  // CHECK: @llvm.objectsize
+  return __builtin_object_size(p, 0);
+}
+
+// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize1Pv
+int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {
+  // CHECK: @llvm.objectsize
+  return __builtin_object_size(p, 1);
+}
+
+// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize2Pv
+int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {
+  // CHECK: @llvm.objectsize
+  return __builtin_object_size(p, 2);
+}
+
+// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize3Pv
+int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 3);
+}
+
+// CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv
+// CHECK-NOT: @llvm.objectsize
+int NoViableOverloadObjectSize0(void *const p PS(0))
+    __attribute__((overloadable)) {
+  return __builtin_object_size(p, 0);
+}
+
+int NoViableOverloadObjectSize1(void *const p PS(1))
+    __attribute__((overloadable)) {
+  return __builtin_object_size(p, 1);
+}
+
+int NoViableOverloadObjectSize2(void *const p PS(2))
+    __attribute__((overloadable)) {
+  return __builtin_object_size(p, 2);
+}
+
+int NoViableOverloadObjectSize3(void *const p PS(3))
+    __attribute__((overloadable)) {
+  return __builtin_object_size(p, 3);
+}
+
+const static int SHOULDNT_BE_CALLED = -100;
+int NoViableOverloadObjectSize0(void *const p PS(0))
+    __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
+  return SHOULDNT_BE_CALLED;
+}
+
+int NoViableOverloadObjectSize1(void *const p PS(1))
+    __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
+  return SHOULDNT_BE_CALLED;
+}
+
+int NoViableOverloadObjectSize2(void *const p PS(2))
+    __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
+  return SHOULDNT_BE_CALLED;
+}
+
+int NoViableOverloadObjectSize3(void *const p PS(3))
+    __attribute__((overloadable, enable_if(p == 0, "never selected"))) {
+  return SHOULDNT_BE_CALLED;
+}
+
+// CHECK-LABEL: define void @test3
+void test3() {
+  struct Foo t[10];
+
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 360)
+  gi = NoViableOverloadObjectSize0(&t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 360)
+  gi = NoViableOverloadObjectSize1(&t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 360)
+  gi = NoViableOverloadObjectSize2(&t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 360)
+  gi = NoViableOverloadObjectSize3(&t[1]);
+
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 356)
+  gi = NoViableOverloadObjectSize0(&t[1].t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
+  gi = NoViableOverloadObjectSize1(&t[1].t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 356)
+  gi = NoViableOverloadObjectSize2(&t[1].t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
+  gi = NoViableOverloadObjectSize3(&t[1].t[1]);
+}
+
+// CHECK-LABEL: define void @test4
+void test4(struct Foo *t) {
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
+  gi = NoViableOverloadObjectSize0(&t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 %{{.*}})
+  gi = NoViableOverloadObjectSize1(&t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
+  gi = NoViableOverloadObjectSize2(&t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 0)
+  gi = NoViableOverloadObjectSize3(&t[1]);
+
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
+  gi = NoViableOverloadObjectSize0(&t[1].t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
+  gi = NoViableOverloadObjectSize1(&t[1].t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
+  gi = NoViableOverloadObjectSize2(&t[1].t[1]);
+  // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
+  gi = NoViableOverloadObjectSize3(&t[1].t[1]);
+}
+
+void test5() {
+  struct Foo t[10];
+
+  int (*f)(void *) = &NoViableOverloadObjectSize0;
+  gi = f(&t[1]);
+}
+
+// CHECK-LABEL: define i32 @IndirectObjectSize0
+int IndirectObjectSize0(void *const p PS(0)) {
+  // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}})
+  // CHECK-NOT: @llvm.objectsize
+  return ObjectSize0(p);
+}
+
+// CHECK-LABEL: define i32 @IndirectObjectSize1
+int IndirectObjectSize1(void *const p PS(1)) {
+  // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 %{{.*}})
+  // CHECK-NOT: @llvm.objectsize
+  return ObjectSize1(p);
+}
+
+// CHECK-LABEL: define i32 @IndirectObjectSize2
+int IndirectObjectSize2(void *const p PS(2)) {
+  // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 %{{.*}})
+  // CHECK-NOT: @llvm.objectsize
+  return ObjectSize2(p);
+}
+
+// CHECK-LABEL: define i32 @IndirectObjectSize3
+int IndirectObjectSize3(void *const p PS(3)) {
+  // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 %{{.*}})
+  // CHECK-NOT: @llvm.objectsize
+  return ObjectSize3(p);
+}
+
+int Overload0(void *, size_t, void *, size_t);
+int OverloadNoSize(void *, void *);
+
+int OverloadedObjectSize(void *const p PS(0),
+                         void *const c PS(0))
+    __attribute__((overloadable)) __asm__("Overload0");
+
+int OverloadedObjectSize(void *const p, void *const c)
+    __attribute__((overloadable)) __asm__("OverloadNoSize");
+
+// CHECK-LABEL: define void @test6
+void test6() {
+  int known[10], *opaque;
+
+  // CHECK: call i32 @"\01Overload0"
+  gi = OverloadedObjectSize(&known[0], &known[0]);
+
+  // CHECK: call i32 @"\01Overload0"
+  gi = OverloadedObjectSize(&known[0], opaque);
+
+  // CHECK: call i32 @"\01Overload0"
+  gi = OverloadedObjectSize(opaque, &known[0]);
+
+  // CHECK: call i32 @"\01Overload0"
+  gi = OverloadedObjectSize(opaque, opaque);
+}
+
+int Identity(void *p, size_t i) { return i; }
+
+// CHECK-NOT: define void @AsmObjectSize
+int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");
+
+int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");
+
+int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");
+
+int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");
+
+// CHECK-LABEL: define void @test7
+void test7() {
+  struct Foo t[10];
+
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
+  gi = AsmObjectSize0(&t[1]);
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
+  gi = AsmObjectSize1(&t[1]);
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
+  gi = AsmObjectSize2(&t[1]);
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
+  gi = AsmObjectSize3(&t[1]);
+
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
+  gi = AsmObjectSize0(&t[1].t[1]);
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
+  gi = AsmObjectSize1(&t[1].t[1]);
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
+  gi = AsmObjectSize2(&t[1].t[1]);
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
+  gi = AsmObjectSize3(&t[1].t[1]);
+}
+
+// CHECK-LABEL: define void @test8
+void test8(struct Foo *t) {
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
+  gi = AsmObjectSize1(&t[1].t[1]);
+  // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
+  gi = AsmObjectSize3(&t[1].t[1]);
+}
+
+void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0))));
+void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1))));
+void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2))));
+void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3))));
+
+// CHECK-LABEL: define void @test9
+void test9(void *const p __attribute__((pass_object_size(0)))) {
+  // CHECK: @llvm.objectsize
+  DifferingObjectSize2(p);
+
+  // CHECK-NOT: @llvm.objectsize
+  DifferingObjectSize0(p);
+  DifferingObjectSize1(p);
+
+  // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
+  DifferingObjectSize3(p);
+}
+
+// CHECK-LABEL: define void @test10
+void test10(void *const p __attribute__((pass_object_size(1)))) {
+  // CHECK: @llvm.objectsize
+  DifferingObjectSize2(p);
+  // CHECK: @llvm.objectsize
+  DifferingObjectSize0(p);
+
+  // CHECK-NOT: @llvm.objectsize
+  DifferingObjectSize1(p);
+
+  // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
+  DifferingObjectSize3(p);
+}
+
+// CHECK-LABEL: define void @test11
+void test11(void *const p __attribute__((pass_object_size(2)))) {
+  // CHECK: @llvm.objectsize
+  DifferingObjectSize0(p);
+  // CHECK: @llvm.objectsize
+  DifferingObjectSize1(p);
+
+  // CHECK-NOT: @llvm.objectsize
+  DifferingObjectSize2(p);
+
+  // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
+  DifferingObjectSize3(p);
+}
+
+// CHECK-LABEL: define void @test12
+void test12(void *const p __attribute__((pass_object_size(3)))) {
+  // CHECK: @llvm.objectsize
+  DifferingObjectSize0(p);
+  // CHECK: @llvm.objectsize
+  DifferingObjectSize1(p);
+
+  // CHECK-NOT: @llvm.objectsize
+  DifferingObjectSize2(p);
+  DifferingObjectSize3(p);
+}
+
+// CHECK-LABEL: define void @test13
+void test13() {
+  // Ensuring that we don't lower objectsize if the expression has side-effects
+  char c[10];
+  char *p = c;
+
+  // CHECK: @llvm.objectsize
+  ObjectSize0(p);
+
+  // CHECK-NOT: @llvm.objectsize
+  ObjectSize0(++p);
+  ObjectSize0(p++);
+}
diff --git a/clang/test/CodeGenCXX/pass-object-size.cpp b/clang/test/CodeGenCXX/pass-object-size.cpp
new file mode 100644 (file)
index 0000000..254669b
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 -std=c++11 | FileCheck %s
+
+int gi;
+
+namespace lambdas {
+// CHECK-LABEL: define void @_ZN7lambdas7LambdasEPc
+void Lambdas(char *ptr) {
+  auto L1 = [](void *const p __attribute__((pass_object_size(0)))) {
+    return __builtin_object_size(p, 0);
+  };
+
+  int i = 0;
+  auto L2 = [&i](void *const p __attribute__((pass_object_size(0)))) {
+    return __builtin_object_size(p, 0) + i;
+  };
+
+  // CHECK: @llvm.objectsize
+  gi = L1(ptr);
+  // CHECK: @llvm.objectsize
+  gi = L2(ptr);
+}
+
+// CHECK-DAG: define internal i64 @"_ZZN7lambdas7LambdasEPcENK3$_0clEPvU17pass_object_size0"
+// CHECK-NOT: call i64 @llvm.objectsize
+// CHECK-DAG: define internal i64 @"_ZZN7lambdas7LambdasEPcENK3$_1clEPvU17pass_object_size0"
+// CHECK-NOT: call i64 @llvm.objectsize
+}
diff --git a/clang/test/Sema/pass-object-size.c b/clang/test/Sema/pass-object-size.c
new file mode 100644 (file)
index 0000000..e4f460b
--- /dev/null
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -triple x86_64-linux-gnu -Wincompatible-pointer-types
+//
+// Tests for the pass_object_size attribute
+// Non-failure cases are covered in test/CodeGen/pass-object-size.c
+
+void a(void *p __attribute__((pass_object_size))); //expected-error{{'pass_object_size' attribute takes one argument}}
+void b(void *p __attribute__((pass_object_size(1.0)))); //expected-error{{'pass_object_size' attribute requires parameter 1 to be an integer constant}}
+
+void c(void *p __attribute__((pass_object_size(4)))); //expected-error{{'pass_object_size' attribute requires integer constant between 0 and 3 inclusive}}
+void d(void *p __attribute__((pass_object_size(-1)))); //expected-error{{'pass_object_size' attribute requires integer constant between 0 and 3 inclusive}}
+
+void e(void *p __attribute__((pass_object_size(1ULL<<32)))); //expected-error{{integer constant expression evaluates to value 4294967296 that cannot be represented in a 32-bit unsigned integer type}}
+
+void f(char p __attribute__((pass_object_size(0)))); //expected-error{{'pass_object_size' attribute only applies to constant pointer arguments}}
+void g(const char p __attribute__((pass_object_size(0)))); //expected-error{{'pass_object_size' attribute only applies to constant pointer arguments}}
+void h(char *p __attribute__((pass_object_size(0)))) {} //expected-error{{pass_object_size attribute only applies to constant pointer arguments}}
+void i(char *p __attribute__((pass_object_size(0)))); // OK -- const is only necessary on definitions, not decls.
+void j(char *p __attribute__((pass_object_size(0), pass_object_size(1)))); //expected-error{{'pass_object_size' attribute can only be applied once per parameter}}
+
+#define PS(N) __attribute__((pass_object_size(N)))
+#define overloaded __attribute__((overloadable))
+void Overloaded(void *p PS(0)) overloaded; //expected-note{{previous declaration is here}}
+void Overloaded(void *p PS(1)) overloaded; //expected-error{{conflicting pass_object_size attributes on parameters}}
+void Overloaded2(void *p PS(1), void *p2 PS(0)) overloaded; //expected-note{{previous declaration is here}}
+void Overloaded2(void *p PS(0), void *p2 PS(1)) overloaded; //expected-error{{conflicting pass_object_size attributes on parameters}}
+
+void Overloaded3(void *p PS(0), void *p2) overloaded; //expected-note{{previous declaration is here}}
+void Overloaded3(void *p, void *p2 PS(0)) overloaded; //expected-error{{conflicting pass_object_size attributes on parameters}}
+
+void TakeFn(void (*)(void *));
+void TakeFnOvl(void (*)(void *)) overloaded;
+void TakeFnOvl(void (*)(int *)) overloaded;
+
+void NotOverloaded(void *p PS(0));
+void IsOverloaded(void *p PS(0)) overloaded;
+void IsOverloaded(char *p) overloaded;
+void FunctionPtrs() {
+  void (*p)(void *) = NotOverloaded; //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
+  void (*p2)(void *) = &NotOverloaded; //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
+
+  void (*p3)(void *) = IsOverloaded; //expected-error{{initializing 'void (*)(void *)' with an expression of incompatible type '<overloaded function type>'}} expected-note@-6{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@-5{{type mismatch}}
+  void (*p4)(void *) = &IsOverloaded; //expected-error{{initializing 'void (*)(void *)' with an expression of incompatible type '<overloaded function type>'}} expected-note@-7{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@-6{{type mismatch}}
+
+  void (*p5)(char *) = IsOverloaded;
+  void (*p6)(char *) = &IsOverloaded;
+
+  TakeFn(NotOverloaded); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
+  TakeFn(&NotOverloaded); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
+
+  TakeFnOvl(NotOverloaded); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
+  TakeFnOvl(&NotOverloaded); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
+}
diff --git a/clang/test/SemaCXX/pass-object-size.cpp b/clang/test/SemaCXX/pass-object-size.cpp
new file mode 100644 (file)
index 0000000..a604053
--- /dev/null
@@ -0,0 +1,122 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+
+namespace simple {
+int Foo(void *const p __attribute__((pass_object_size(0))));
+
+int OvlFoo(void *const p __attribute__((pass_object_size(0))));
+int OvlFoo(void *const p, int);
+
+struct Statics {
+  static int Foo(void *const p __attribute__((pass_object_size(0))));
+  static int OvlFoo(void *const p __attribute__((pass_object_size(0))));
+  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}}
+  static int OvlFoo(double *p);
+};
+
+struct Members {
+  int Foo(void *const p __attribute__((pass_object_size(0))));
+  int OvlFoo(void *const p __attribute__((pass_object_size(0))));
+  int OvlFoo(void *const p, int);
+};
+
+void Decls() {
+  int (*A)(void *) = &Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
+  int (*B)(void *) = Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
+
+  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)}}
+  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)}}
+
+  int (*E)(void *) = &Statics::Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
+  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 *')}}
+
+  int (*G)(void *) = &Members::Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
+  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)}}
+}
+
+void Assigns() {
+  int (*A)(void *);
+  A = &Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
+  A = Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
+
+  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)}}
+  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)}}
+
+  A = &Statics::Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
+  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 *')}}
+
+  int (Members::*M)(void *);
+  M = &Members::Foo; //expected-error{{cannot take address of function 'Foo' because parameter 1 has pass_object_size attribute}}
+  M = &Members::OvlFoo; //expected-error{{assigning to 'int (simple::Members::*)(void *)' 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)}}
+}
+
+} // namespace simple
+
+namespace templates {
+template <typename T>
+int Foo(void *const __attribute__((pass_object_size(0)))) {
+  return 0;
+}
+
+template <typename T> struct Bar {
+  template <typename U>
+  int Foo(void *const __attribute__((pass_object_size(0)))) {
+    return 0;
+  }
+};
+
+void Decls() {
+  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}}
+  int (Bar<int>::*B)(void *) = &Bar<int>::Foo<double>; //expected-error{{address of overloaded function 'Foo' does not match required type 'int (void *)'}} expected-note@62{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}}
+}
+
+void Assigns() {
+  int (*A)(void *);
+  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}}
+  int (Bar<int>::*B)(void *) = &Bar<int>::Foo<double>; //expected-error{{address of overloaded function 'Foo' does not match required type 'int (void *)'}} expected-note@62{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}}
+}
+} // namespace templates
+
+namespace virt {
+struct Foo {
+  virtual void DoIt(void *const p __attribute__((pass_object_size(0))));
+};
+
+struct Bar : public Foo {
+  void DoIt(void *const p __attribute__((pass_object_size(0)))) override; // OK
+};
+
+struct Baz : public Foo {
+  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}}
+};
+}
+
+namespace why {
+void TakeFn(void (*)(int, void *));
+void ObjSize(int, void *const __attribute__((pass_object_size(0))));
+
+void Check() {
+  TakeFn(ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+  TakeFn(&ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+  TakeFn(*ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+  TakeFn(*****ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+  TakeFn(*****&ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+
+  void (*P)(int, void *) = ****ObjSize; //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+  P = ****ObjSize; //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+
+  TakeFn((ObjSize)); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+  TakeFn((void*)ObjSize); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+  TakeFn((decltype(P))((void*)ObjSize)); //expected-error{{cannot take address of function 'ObjSize' because parameter 2 has pass_object_size attribute}}
+}
+}
+
+namespace constexpr_support {
+constexpr int getObjSizeType() { return 0; }
+void Foo(void *p __attribute__((pass_object_size(getObjSizeType()))));
+}
+
+namespace lambdas {
+void Bar() {
+  (void)+[](void *const p __attribute__((pass_object_size(0)))) {}; //expected-error-re{{invalid argument type '(lambda at {{.*}})' to unary expression}}
+}
+}