From 9e087993b57ded77dd0c19b1af35d838f468b589 Mon Sep 17 00:00:00 2001
From: Erik Johansson <erik@ejohansson.se>
Date: Fri, 12 Nov 2010 11:08:07 +0100
Subject: [PATCH] Fix error when generated C code is compiled as C++

If a generated hash file in C is included in a C++ file which is compiled with
inlining disabled (e.g. -O0) the process will fail in the link stage due to
missing symbols.

The reason for this is that the attribute __gnu_inline__ has a different
meaning for C and C++. For C code it means "inline where possible and create a
standalone function". For C++ code it means "inline where possible, but don't
create a standalone function". If inlining is disabled the C++ compiler will
not generate any code causing the build to fail in the link stage.

Fix this by not adding the attribute if the code is compiled as C++ code with
inlining disabled.
---
 src/output.cc        |    8 +++++++-
 tests/c-parse.exp    |    2 ++
 tests/charsets.exp   |    2 ++
 tests/chill.exp      |    2 ++
 tests/cplusplus.exp  |    2 ++
 tests/gpc.exp        |    2 ++
 tests/incomplete.exp |    2 ++
 tests/java.exp       |    2 ++
 tests/languages.exp  |    2 ++
 tests/modula2.exp    |    2 ++
 tests/objc.exp       |    2 ++
 tests/permut2.exp    |    2 ++
 tests/permut3.exp    |    2 ++
 tests/permutc2.exp   |    2 ++
 tests/test-4.exp     |    2 ++
 15 files changed, 35 insertions(+), 1 deletions(-)

diff --git a/src/output.cc b/src/output.cc
index 4b0e4c6..77657ea 100644
--- a/src/output.cc
+++ b/src/output.cc
@@ -1891,12 +1891,18 @@ Output::output_lookup_function () const
        semantics but warns, unless -fgnu89-inline is used:
          warning: C99 inline functions are not supported; using GNU89
          warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute
-       It defines a macro __GNUC_GNU_INLINE__ to indicate this situation.  */
+       It defines a macro __GNUC_GNU_INLINE__ to indicate this situation.
+
+       Avoid adding the __gnu_inline__ attribute if the code is compiled as C++
+       code without inlining as the compiler will neither inline the code nor
+       generate a standalone function in this case.  */
     printf ("#ifdef __GNUC__\n"
             "__inline\n"
             "#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__\n"
+            "#if !defined __cplusplus || !defined __NO_INLINE__\n"
             "__attribute__ ((__gnu_inline__))\n"
             "#endif\n"
+            "#endif\n"
             "#endif\n");
 
   printf ("%s%s\n",
diff --git a/tests/c-parse.exp b/tests/c-parse.exp
index d370941..afda17b 100644
--- a/tests/c-parse.exp
+++ b/tests/c-parse.exp
@@ -200,9 +200,11 @@ static struct resword wordlist[] =
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 struct resword *
 is_reserved_word (str, len)
      register const char *str;
diff --git a/tests/charsets.exp b/tests/charsets.exp
index ccbd078..592408c 100644
--- a/tests/charsets.exp
+++ b/tests/charsets.exp
@@ -1804,9 +1804,11 @@ static const struct charset wordlist[] =
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 const struct charset *
 in_word_set (register const char *str, register unsigned int len)
 {
diff --git a/tests/chill.exp b/tests/chill.exp
index 7007f4d..5fced42 100644
--- a/tests/chill.exp
+++ b/tests/chill.exp
@@ -179,9 +179,11 @@ hash (str, len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 struct resword *
 in_word_set (str, len)
      register const char *str;
diff --git a/tests/cplusplus.exp b/tests/cplusplus.exp
index 29bca4d..8b735db 100644
--- a/tests/cplusplus.exp
+++ b/tests/cplusplus.exp
@@ -104,9 +104,11 @@ hash (str, len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 struct resword *
 is_reserved_word (str, len)
      register const char *str;
diff --git a/tests/gpc.exp b/tests/gpc.exp
index b2a77b6..caf9a58 100644
--- a/tests/gpc.exp
+++ b/tests/gpc.exp
@@ -93,9 +93,11 @@ hash (register const char *str, register unsigned int len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 struct resword *
 is_reserved_word (register const char *str, register unsigned int len)
 {
diff --git a/tests/incomplete.exp b/tests/incomplete.exp
index ab4e24f..f91aa2c 100644
--- a/tests/incomplete.exp
+++ b/tests/incomplete.exp
@@ -83,9 +83,11 @@ hash (register const char *str, register unsigned int len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 struct month *
 in_word_set (register const char *str, register unsigned int len)
 {
diff --git a/tests/java.exp b/tests/java.exp
index 90ad5a3..5af6361 100644
--- a/tests/java.exp
+++ b/tests/java.exp
@@ -122,9 +122,11 @@ hash (str, len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 struct java_keyword *
 java_keyword (str, len)
      register const char *str;
diff --git a/tests/languages.exp b/tests/languages.exp
index 3abe0fc..60ecc49 100644
--- a/tests/languages.exp
+++ b/tests/languages.exp
@@ -1461,9 +1461,11 @@ static const struct language wordlist[] =
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 const struct language *
 in_word_set (register const char *str, register unsigned int len)
 {
diff --git a/tests/modula2.exp b/tests/modula2.exp
index 50f1c48..6a204d7 100644
--- a/tests/modula2.exp
+++ b/tests/modula2.exp
@@ -110,9 +110,11 @@ hash (register const char *str, register unsigned int len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 const char *
 in_word_set (register const char *str, register unsigned int len)
 {
diff --git a/tests/objc.exp b/tests/objc.exp
index 21be290..30f6ab6 100644
--- a/tests/objc.exp
+++ b/tests/objc.exp
@@ -96,9 +96,11 @@ hash (register const char *str, register unsigned int len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 struct resword *
 is_reserved_word (register const char *str, register unsigned int len)
 {
diff --git a/tests/permut2.exp b/tests/permut2.exp
index 7db6857..ef58506 100644
--- a/tests/permut2.exp
+++ b/tests/permut2.exp
@@ -83,9 +83,11 @@ hash (register const char *str, register unsigned int len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 const char *
 in_word_set (register const char *str, register unsigned int len)
 {
diff --git a/tests/permut3.exp b/tests/permut3.exp
index 967c084..d805f0d 100644
--- a/tests/permut3.exp
+++ b/tests/permut3.exp
@@ -83,9 +83,11 @@ hash (register const char *str, register unsigned int len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 const char *
 in_word_set (register const char *str, register unsigned int len)
 {
diff --git a/tests/permutc2.exp b/tests/permutc2.exp
index 4a29918..5464509 100644
--- a/tests/permutc2.exp
+++ b/tests/permutc2.exp
@@ -128,9 +128,11 @@ hash (register const char *str, register unsigned int len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 const char *
 in_word_set (register const char *str, register unsigned int len)
 {
diff --git a/tests/test-4.exp b/tests/test-4.exp
index 2b97abc..60beb0a 100644
--- a/tests/test-4.exp
+++ b/tests/test-4.exp
@@ -84,9 +84,11 @@ hash (register const char *str, register unsigned int len)
 #ifdef __GNUC__
 __inline
 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
+#if !defined __cplusplus || !defined __NO_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
+#endif
 struct resword *
 in_word_set (register const char *str, register unsigned int len)
 {
-- 
1.7.2.3

