summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko2017-07-28 15:28:33 +0200
committerDenys Vlasenko2017-07-28 15:28:33 +0200
commit619d9b5e6848a72350126ea9c1e413fd133181e3 (patch)
tree1fe4ab734bd3b917ec4e9ef35d2c1e700a850605 /shell
parent46f3f16b587ce781ab43a7b17698e1e565b2acf7 (diff)
downloadbusybox-619d9b5e6848a72350126ea9c1e413fd133181e3.zip
busybox-619d9b5e6848a72350126ea9c1e413fd133181e3.tar.gz
ash: less hackish implementation of evaltreenr()
Defining a function alias with __attribute__ ((alias("evaltree"),__noreturn__)) is not that usual, and clang had a bug which made it misunderstand this construct. Switch to: ALWAYS_INLINE NORETURN evaltreenr() { evaltree(); unreachable(); } Older gcc's do not know unreachable(), on them we pay the price of having a few extra calls to abort(): function old new delta evalsubshell 151 156 +5 evalpipe 357 362 +5 argstr 1141 1144 +3 On newer gcc, code size does not change. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/shell/ash.c b/shell/ash.c
index f74fbd7..1f5a8da 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -6137,6 +6137,19 @@ struct backcmd { /* result of evalbackcmd */
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
static int evaltree(union node *, int);
+/* An evaltree() which is known to never return.
+ * Used to use an alias:
+ * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
+ * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
+ */
+static ALWAYS_INLINE NORETURN void
+evaltreenr(union node *n, int flags)
+{
+ evaltree(n, flags);
+ bb_unreachable(abort());
+ /* NOTREACHED */
+}
+
static void FAST_FUNC
evalbackcmd(union node *n, struct backcmd *result)
{
@@ -6173,7 +6186,7 @@ evalbackcmd(union node *n, struct backcmd *result)
*/
eflag = 0;
ifsfree();
- evaltree(n, EV_EXIT); /* actually evaltreenr... */
+ evaltreenr(n, EV_EXIT);
/* NOTREACHED */
}
/* parent */
@@ -8796,11 +8809,6 @@ evaltree(union node *n, int flags)
return exitstatus;
}
-#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
-static
-#endif
-int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
-
static int
skiploop(void)
{