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;