aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-28 15:28:33 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-28 15:28:33 +0200
commit619d9b5e6848a72350126ea9c1e413fd133181e3 (patch)
tree1fe4ab734bd3b917ec4e9ef35d2c1e700a850605
parent46f3f16b587ce781ab43a7b17698e1e565b2acf7 (diff)
downloadbusybox-w32-619d9b5e6848a72350126ea9c1e413fd133181e3.tar.gz
busybox-w32-619d9b5e6848a72350126ea9c1e413fd133181e3.tar.bz2
busybox-w32-619d9b5e6848a72350126ea9c1e413fd133181e3.zip
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>
-rw-r--r--include/platform.h7
-rw-r--r--shell/ash.c20
2 files changed, 21 insertions, 6 deletions
diff --git a/include/platform.h b/include/platform.h
index 8210e5c49..ea49c7e92 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -45,6 +45,13 @@
45 45
46#define UNUSED_PARAM __attribute__ ((__unused__)) 46#define UNUSED_PARAM __attribute__ ((__unused__))
47#define NORETURN __attribute__ ((__noreturn__)) 47#define NORETURN __attribute__ ((__noreturn__))
48
49#if __GNUC_PREREQ(4,5)
50# define bb_unreachable(altcode) __builtin_unreachable()
51#else
52# define bb_unreachable(altcode) altcode
53#endif
54
48/* "The malloc attribute is used to tell the compiler that a function 55/* "The malloc attribute is used to tell the compiler that a function
49 * may be treated as if any non-NULL pointer it returns cannot alias 56 * may be treated as if any non-NULL pointer it returns cannot alias
50 * any other pointer valid when the function returns. This will often 57 * any other pointer valid when the function returns. This will often
diff --git a/shell/ash.c b/shell/ash.c
index f74fbd72f..1f5a8dae0 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -6137,6 +6137,19 @@ struct backcmd { /* result of evalbackcmd */
6137#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ 6137#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
6138static int evaltree(union node *, int); 6138static int evaltree(union node *, int);
6139 6139
6140/* An evaltree() which is known to never return.
6141 * Used to use an alias:
6142 * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6143 * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6144 */
6145static ALWAYS_INLINE NORETURN void
6146evaltreenr(union node *n, int flags)
6147{
6148 evaltree(n, flags);
6149 bb_unreachable(abort());
6150 /* NOTREACHED */
6151}
6152
6140static void FAST_FUNC 6153static void FAST_FUNC
6141evalbackcmd(union node *n, struct backcmd *result) 6154evalbackcmd(union node *n, struct backcmd *result)
6142{ 6155{
@@ -6173,7 +6186,7 @@ evalbackcmd(union node *n, struct backcmd *result)
6173 */ 6186 */
6174 eflag = 0; 6187 eflag = 0;
6175 ifsfree(); 6188 ifsfree();
6176 evaltree(n, EV_EXIT); /* actually evaltreenr... */ 6189 evaltreenr(n, EV_EXIT);
6177 /* NOTREACHED */ 6190 /* NOTREACHED */
6178 } 6191 }
6179 /* parent */ 6192 /* parent */
@@ -8796,11 +8809,6 @@ evaltree(union node *n, int flags)
8796 return exitstatus; 8809 return exitstatus;
8797} 8810}
8798 8811
8799#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8800static
8801#endif
8802int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8803
8804static int 8812static int
8805skiploop(void) 8813skiploop(void)
8806{ 8814{