Merge "Unhide EH helper needed by libgcc.a"
diff --git a/sources/cxx-stl/gabi++/src/new.cc b/sources/cxx-stl/gabi++/src/new.cc
index de9cf7d..8148556 100644
--- a/sources/cxx-stl/gabi++/src/new.cc
+++ b/sources/cxx-stl/gabi++/src/new.cc
@@ -69,5 +69,5 @@
 
 __attribute__ ((weak))
 void* operator new[](std::size_t size, const std::nothrow_t& no) throw() {
-  return ::operator new[](size, no);
+  return ::operator new(size, no);
 }
diff --git a/tests/build/b8247455-hidden-cxa/jni/Android.mk b/tests/build/b8247455-hidden-cxa/jni/Android.mk
new file mode 100644
index 0000000..e3ffba4
--- /dev/null
+++ b/tests/build/b8247455-hidden-cxa/jni/Android.mk
@@ -0,0 +1,30 @@
+# This test is to demostrate the issue:
+#
+#  hidden symbol '__cxa_begin_cleanup' in ./obj/local/armeabi/libgnustl_static.a(eh_arm.o)
+#    is referenced by DSO ./obj/local/armeabi/libidiv.so
+#  hidden symbol '__cxa_type_match' in ./obj/local/armeabi/libgnustl_static.a(eh_arm.o)
+#    is referenced by DSO ./obj/local/armeabi/libidiv.so
+#
+#  File idiv.cpp contains code potentially causes divide-by-zero exception. libidiv.so
+#  is built with libgnustl_static.a which provides __cxa_begin_cleanup and
+#  __cxa_type_match needed by unwinder in libgcc.a.  Unfortunately both are built
+#  with hidden visibility, and causes warnings as the above when libidiv.so is used
+#  to link other binaries.
+#
+# The fix is to unhide both __cxa_begin_cleanup and __cxa_type_match
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libidiv
+LOCAL_SRC_FILES:= idiv.cpp
+LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libthrow
+LOCAL_SRC_FILES:= throw.cpp
+LOCAL_CFLAGS := -Wall -Werror -frtti -fexceptions
+LOCAL_SHARED_LIBRARIES = libidiv
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/tests/build/b8247455-hidden-cxa/jni/Application.mk b/tests/build/b8247455-hidden-cxa/jni/Application.mk
new file mode 100644
index 0000000..3563119
--- /dev/null
+++ b/tests/build/b8247455-hidden-cxa/jni/Application.mk
@@ -0,0 +1,2 @@
+APP_ABI := all
+APP_STL := gnustl_static
diff --git a/tests/build/b8247455-hidden-cxa/jni/idiv.cpp b/tests/build/b8247455-hidden-cxa/jni/idiv.cpp
new file mode 100644
index 0000000..b80920d
--- /dev/null
+++ b/tests/build/b8247455-hidden-cxa/jni/idiv.cpp
@@ -0,0 +1,4 @@
+int my_idiv (int a, int b)
+{
+    return a / b;
+}
diff --git a/tests/build/b8247455-hidden-cxa/jni/throw.cpp b/tests/build/b8247455-hidden-cxa/jni/throw.cpp
new file mode 100644
index 0000000..ac61371
--- /dev/null
+++ b/tests/build/b8247455-hidden-cxa/jni/throw.cpp
@@ -0,0 +1,6 @@
+extern int my_idiv(int a, int b);
+int my_thorw()
+{
+    my_idiv(3, 5);
+    throw 20;
+}
diff --git a/tests/device/test-stlport_shared-exception/jni/new1_3.cpp b/tests/device/test-stlport_shared-exception/jni/new1_3.cpp
index 502c4f4..9ae9336 100644
--- a/tests/device/test-stlport_shared-exception/jni/new1_3.cpp
+++ b/tests/device/test-stlport_shared-exception/jni/new1_3.cpp
@@ -1,7 +1,25 @@
 // { dg-do run  }
-//Lifetime of temporaries: 
-//egcs 2.92 performs cleanup for temporaries inside new expressions
-//after the new is complete, not at the end of the full expression.
+//
+// Purpose: Check the lifetime of the temporaries.
+//
+// Lifetime of temporaries:
+// egcs 2.92 performs cleanup for temporaries inside new expressions
+// after the new is complete, not at the end of the full expression.
+//
+// In GCC, the operands are computed first.  If no exception is raised, then
+// the result should be "ctor, new, func, dtor".  If the new operator throws
+// the exception, then the result should be "ctor, new, dtor".  If the
+// constructor of the temporary throws the exception, then the result should
+// be "ctor".
+//
+// In Clang, the new operator is called first.  If no exception is raised,
+// then the result should be "new, ctor, func, dtor".  If the new operator
+// throws the exception, then the result should be "new".  If the constructor
+// of the temporary throws the exception, then the result should be
+// "new, ctor, delete".
+//
+// Both of them are allowed by the C++ language specification, so we are using
+// #ifdef for different compilers.
 
 #include <new>
 #include <cstdlib>
@@ -71,11 +89,21 @@
     func(new B(A(10).addr()));
   }catch(int){
   }
+#if defined(__clang__)
+  CHECK(new_done==1);
+  CHECK(ctor_done==2);
+  CHECK(func_done==3);
+  CHECK(dtor_done==4);
+  CHECK(delete_done==0);
+#elif defined(__GNUC__)
   CHECK(ctor_done==1);
   CHECK(new_done==2);
   CHECK(func_done==3);
   CHECK(dtor_done==4);
   CHECK(delete_done==0);
+#else
+#error "Unknown compiler"
+#endif
 }
 
 void test2()
@@ -86,11 +114,21 @@
     func(new B(A(10).addr()));
   }catch(int){
   }
+#if defined(__clang__)
+  CHECK(new_done==1);
+  CHECK(ctor_done==0);
+  CHECK(func_done==0);
+  CHECK(dtor_done==0);
+  CHECK(delete_done==0);
+#elif defined(__GNUC__)
   CHECK(ctor_done==1);
   CHECK(new_done==2);
   CHECK(func_done==0);
   CHECK(dtor_done==3);
   CHECK(delete_done==0);
+#else
+#error "Unknown compiler"
+#endif
 }
 
 void test3()
@@ -101,11 +139,21 @@
     func(new B(A(10).addr()));
   }catch(int){
   }
+#if defined(__clang__)
+  CHECK(new_done==1);
+  CHECK(ctor_done==2);
+  CHECK(func_done==0);
+  CHECK(dtor_done==0);
+  CHECK(delete_done==3);
+#elif defined(__GNUC__)
   CHECK(new_done==0);
   CHECK(ctor_done==1);
   CHECK(func_done==0);
   CHECK(dtor_done==0);
   CHECK(delete_done==0);
+#else
+#error "Unknown compiler"
+#endif
 }
 
 int main()
diff --git a/tests/device/test-stlport_shared-exception/jni/pr23299.cpp b/tests/device/test-stlport_shared-exception/jni/pr23299.cpp
index 94a414a..844d68c 100644
--- a/tests/device/test-stlport_shared-exception/jni/pr23299.cpp
+++ b/tests/device/test-stlport_shared-exception/jni/pr23299.cpp
@@ -6,16 +6,19 @@
 
 struct A
 {
-  virtual int a () {}
+  virtual int a () { return 0; }
 };
+
 struct B : public A
 {
-  virtual int b () {}
+  virtual int b () { return 0; }
 };
+
 struct C : public A
 {
-  virtual int c () {}
+  virtual int c () { return 0; }
 };
+
 struct D
 {
   D () { d = 64; }
@@ -24,6 +27,7 @@
 };
 
 int x;
+
 D::~D ()
 {
   x |= 1;
@@ -44,16 +48,15 @@
   int r = c ();
 }
 
-int
-E::c ()
+int E::c ()
 {
   if (x > 10)
     throw 1;
   x |= 2;
+  return 0;
 }
 
-int
-main (void)
+int main (void)
 {
   {
     E e;
diff --git a/tests/device/test-stlport_static-exception/jni/new1_3.cpp b/tests/device/test-stlport_static-exception/jni/new1_3.cpp
index 502c4f4..9ae9336 100644
--- a/tests/device/test-stlport_static-exception/jni/new1_3.cpp
+++ b/tests/device/test-stlport_static-exception/jni/new1_3.cpp
@@ -1,7 +1,25 @@
 // { dg-do run  }
-//Lifetime of temporaries: 
-//egcs 2.92 performs cleanup for temporaries inside new expressions
-//after the new is complete, not at the end of the full expression.
+//
+// Purpose: Check the lifetime of the temporaries.
+//
+// Lifetime of temporaries:
+// egcs 2.92 performs cleanup for temporaries inside new expressions
+// after the new is complete, not at the end of the full expression.
+//
+// In GCC, the operands are computed first.  If no exception is raised, then
+// the result should be "ctor, new, func, dtor".  If the new operator throws
+// the exception, then the result should be "ctor, new, dtor".  If the
+// constructor of the temporary throws the exception, then the result should
+// be "ctor".
+//
+// In Clang, the new operator is called first.  If no exception is raised,
+// then the result should be "new, ctor, func, dtor".  If the new operator
+// throws the exception, then the result should be "new".  If the constructor
+// of the temporary throws the exception, then the result should be
+// "new, ctor, delete".
+//
+// Both of them are allowed by the C++ language specification, so we are using
+// #ifdef for different compilers.
 
 #include <new>
 #include <cstdlib>
@@ -71,11 +89,21 @@
     func(new B(A(10).addr()));
   }catch(int){
   }
+#if defined(__clang__)
+  CHECK(new_done==1);
+  CHECK(ctor_done==2);
+  CHECK(func_done==3);
+  CHECK(dtor_done==4);
+  CHECK(delete_done==0);
+#elif defined(__GNUC__)
   CHECK(ctor_done==1);
   CHECK(new_done==2);
   CHECK(func_done==3);
   CHECK(dtor_done==4);
   CHECK(delete_done==0);
+#else
+#error "Unknown compiler"
+#endif
 }
 
 void test2()
@@ -86,11 +114,21 @@
     func(new B(A(10).addr()));
   }catch(int){
   }
+#if defined(__clang__)
+  CHECK(new_done==1);
+  CHECK(ctor_done==0);
+  CHECK(func_done==0);
+  CHECK(dtor_done==0);
+  CHECK(delete_done==0);
+#elif defined(__GNUC__)
   CHECK(ctor_done==1);
   CHECK(new_done==2);
   CHECK(func_done==0);
   CHECK(dtor_done==3);
   CHECK(delete_done==0);
+#else
+#error "Unknown compiler"
+#endif
 }
 
 void test3()
@@ -101,11 +139,21 @@
     func(new B(A(10).addr()));
   }catch(int){
   }
+#if defined(__clang__)
+  CHECK(new_done==1);
+  CHECK(ctor_done==2);
+  CHECK(func_done==0);
+  CHECK(dtor_done==0);
+  CHECK(delete_done==3);
+#elif defined(__GNUC__)
   CHECK(new_done==0);
   CHECK(ctor_done==1);
   CHECK(func_done==0);
   CHECK(dtor_done==0);
   CHECK(delete_done==0);
+#else
+#error "Unknown compiler"
+#endif
 }
 
 int main()
diff --git a/tests/device/test-stlport_static-exception/jni/pr23299.cpp b/tests/device/test-stlport_static-exception/jni/pr23299.cpp
index 94a414a..844d68c 100644
--- a/tests/device/test-stlport_static-exception/jni/pr23299.cpp
+++ b/tests/device/test-stlport_static-exception/jni/pr23299.cpp
@@ -6,16 +6,19 @@
 
 struct A
 {
-  virtual int a () {}
+  virtual int a () { return 0; }
 };
+
 struct B : public A
 {
-  virtual int b () {}
+  virtual int b () { return 0; }
 };
+
 struct C : public A
 {
-  virtual int c () {}
+  virtual int c () { return 0; }
 };
+
 struct D
 {
   D () { d = 64; }
@@ -24,6 +27,7 @@
 };
 
 int x;
+
 D::~D ()
 {
   x |= 1;
@@ -44,16 +48,15 @@
   int r = c ();
 }
 
-int
-E::c ()
+int E::c ()
 {
   if (x > 10)
     throw 1;
   x |= 2;
+  return 0;
 }
 
-int
-main (void)
+int main (void)
 {
   {
     E e;