The cleanup attribute no longer uses an unresolved, simple identifier as its argument.  Instead, it takes an expression that is fully resolved.

llvm-svn: 190476
diff --git a/clang/test/CodeGenCXX/attr-cleanup.cpp b/clang/test/CodeGenCXX/attr-cleanup.cpp
new file mode 100644
index 0000000..03f9481
--- /dev/null
+++ b/clang/test/CodeGenCXX/attr-cleanup.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s

+

+namespace N {

+  void free(void *i) {}

+}

+

+int main(void) {

+  // CHECK: call void @_ZN1N4freeEPv(i8* %0)

+  void *fp __attribute__((cleanup(N::free)));

+  return 0;

+}

diff --git a/clang/test/Sema/attr-cleanup.c b/clang/test/Sema/attr-cleanup.c
index c063529..f5cbc38 100644
--- a/clang/test/Sema/attr-cleanup.c
+++ b/clang/test/Sema/attr-cleanup.c
@@ -2,18 +2,18 @@
 
 void c1(int *a);
 
-extern int g1 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}}
-int g2 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}}
-static int g3 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}}
+extern int g1 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute ignored}}
+int g2 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute ignored}}
+static int g3 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute ignored}}
 
 void t1()
 {
     int v1 __attribute((cleanup)); // expected-error {{'cleanup' attribute takes one argument}}
     int v2 __attribute((cleanup(1, 2))); // expected-error {{'cleanup' attribute takes one argument}}
 
-    static int v3 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}}
+    static int v3 __attribute((cleanup(c1))); // expected-warning {{'cleanup' attribute ignored}}
 
-    int v4 __attribute((cleanup(h))); // expected-error {{'cleanup' argument 'h' not found}}
+    int v4 __attribute((cleanup(h))); // expected-error {{use of undeclared identifier 'h'}}
 
     int v5 __attribute((cleanup(c1)));
     int v6 __attribute((cleanup(v3))); // expected-error {{'cleanup' argument 'v3' is not a function}}
@@ -42,3 +42,7 @@
 void t5() {
   int i __attribute__((cleanup(c5)));  // expected-warning {{'c5' is deprecated}}
 }
+
+void t6(void) {
+  int i __attribute__((cleanup((void *)0)));  // expected-error {{'cleanup' argument is not a function}}
+}
diff --git a/clang/test/SemaCXX/attr-cleanup-gcc.cpp b/clang/test/SemaCXX/attr-cleanup-gcc.cpp
new file mode 100644
index 0000000..03001b6
--- /dev/null
+++ b/clang/test/SemaCXX/attr-cleanup-gcc.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -Wgcc-compat

+

+namespace N {

+  void c1(int *a) {}

+}

+

+void c2(int *a) {}

+

+template <typename Ty>

+void c3(Ty *a) {}

+

+void t3() {

+  int v1 __attribute__((cleanup(N::c1)));  // expected-warning  {{GCC does not allow the 'cleanup' attribute argument to be anything other than a simple identifier}}

+  int v2 __attribute__((cleanup(c2)));

+  int v3 __attribute__((cleanup(c3<int>)));  // expected-warning  {{GCC does not allow the 'cleanup' attribute argument to be anything other than a simple identifier}}

+}

diff --git a/clang/test/SemaCXX/attr-cleanup.cpp b/clang/test/SemaCXX/attr-cleanup.cpp
new file mode 100644
index 0000000..3ac8e81
--- /dev/null
+++ b/clang/test/SemaCXX/attr-cleanup.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-gcc-compat

+

+namespace N {

+  void c1(int *a) {}

+}

+

+void t1() {

+  int v1 __attribute__((cleanup(N::c1)));

+  int v2 __attribute__((cleanup(N::c2)));  // expected-error {{no member named 'c2' in namespace 'N'}}

+}