Index: libitm/alloc.cc =================================================================== --- libitm/alloc.cc (revision 182769) +++ libitm/alloc.cc (working copy) @@ -27,7 +27,7 @@ namespace GTM HIDDEN { void -gtm_thread::record_allocation (void *ptr, void (*free_fn)(void *)) +gtm_thread::record_allocation (void *ptr, __freet free_fn) { uintptr_t iptr = (uintptr_t) ptr; @@ -40,7 +40,7 @@ } void -gtm_thread::forget_allocation (void *ptr, void (*free_fn)(void *)) +gtm_thread::forget_allocation (void *ptr, __freet free_fn) { uintptr_t iptr = (uintptr_t) ptr; Index: libitm/beginend.cc =================================================================== --- libitm/beginend.cc (revision 182769) +++ libitm/beginend.cc (working copy) @@ -77,6 +77,7 @@ free(tx); } +extern "C" { static void thread_exit_handler(void *) { @@ -92,6 +93,7 @@ if (pthread_key_create(&thr_release_key, thread_exit_handler)) GTM_fatal("Creating thread release TLS key failed."); } +} GTM::gtm_thread::~gtm_thread() Index: libitm/libitm_i.h =================================================================== --- libitm/libitm_i.h (revision 182769) +++ libitm/libitm_i.h (working copy) @@ -33,7 +33,7 @@ #include "config.h" #include -#include +#include #include #include #include "local_type_traits" @@ -41,6 +41,7 @@ #include "common.h" +extern "C" typedef void(*__freet)(void*); namespace GTM HIDDEN { using namespace std; @@ -89,7 +90,7 @@ // the template used inside gtm_thread can instantiate. struct gtm_alloc_action { - void (*free_fn)(void *); + __freet free_fn; bool allocated; }; @@ -221,8 +222,8 @@ // In alloc.cc void commit_allocations (bool, aa_tree*); - void record_allocation (void *, void (*)(void *)); - void forget_allocation (void *, void (*)(void *)); + void record_allocation (void *, __freet); + void forget_allocation (void *, __freet); void drop_references_allocations (const void *ptr) { this->alloc_actions.erase((uintptr_t) ptr); Index: libstdc++-v3/src/mt_allocator.cc =================================================================== --- libstdc++-v3/src/mt_allocator.cc (revision 182769) +++ libstdc++-v3/src/mt_allocator.cc (working copy) @@ -66,6 +66,7 @@ return freelist_mutex; } + extern "C" { static void _M_destroy_thread_key(void* __id) { @@ -81,6 +82,7 @@ freelist._M_thread_freelist = __tr; } } + } #endif } // anonymous namespace Index: libstdc++-v3/src/locale_init.cc =================================================================== --- libstdc++-v3/src/locale_init.cc (revision 182769) +++ libstdc++-v3/src/locale_init.cc (working copy) @@ -269,13 +269,13 @@ _S_classic = new (&c_locale_impl) _Impl(2); _S_global = _S_classic; } - +extern "C" typedef void (*__initot)(); void locale::_S_initialize() { #ifdef __GTHREADS if (__gthread_active_p()) - __gthread_once(&_S_once, _S_initialize_once); + __gthread_once(&_S_once, (__initot)_S_initialize_once); #endif if (!_S_classic) _S_initialize_once(); Index: libstdc++-v3/include/std/type_traits =================================================================== --- libstdc++-v3/include/std/type_traits (revision 182769) +++ libstdc++-v3/include/std/type_traits (working copy) @@ -363,11 +363,21 @@ { }; /// is_function + extern "C" template using _CFun2=_Ret(_Args...); + extern "C" template using _CFun3=_Ret(_Args......); template struct is_function : public false_type { }; template + struct is_function<_CFun2<_Res,_ArgTypes...>> + : public true_type { }; + + template + struct is_function<_CFun3<_Res,_ArgTypes...>> + : public true_type { }; + + template struct is_function<_Res(_ArgTypes...)> : public true_type { }; @@ -375,6 +385,8 @@ struct is_function<_Res(_ArgTypes......)> : public true_type { }; + /* const/volatile functions only make sense for member functions and thus + cannot be extern "C" */ template struct is_function<_Res(_ArgTypes...) const> : public true_type { }; Index: libstdc++-v3/include/std/functional =================================================================== --- libstdc++-v3/include/std/functional (revision 182769) +++ libstdc++-v3/include/std/functional (working copy) @@ -89,7 +89,17 @@ { }; /// Retrieve the result type for a function type. + extern "C" template using _CFun4=_Ret(_Args...); + extern "C" template using _CFun5=_Ret(_Args......); template + struct _Weak_result_type_impl<_CFun4<_Res,_ArgTypes...>> + { typedef _Res result_type; }; + + template + struct _Weak_result_type_impl<_CFun5<_Res,_ArgTypes...>> + { typedef _Res result_type; }; + + template struct _Weak_result_type_impl<_Res(_ArgTypes...)> { typedef _Res result_type; }; @@ -123,6 +133,14 @@ /// Retrieve the result type for a function reference. template + struct _Weak_result_type_impl<_CFun4<_Res,_ArgTypes...>&> + { typedef _Res result_type; }; + + template + struct _Weak_result_type_impl<_CFun5<_Res,_ArgTypes...>&> + { typedef _Res result_type; }; + + template struct _Weak_result_type_impl<_Res(&)(_ArgTypes...)> { typedef _Res result_type; }; @@ -132,6 +150,14 @@ /// Retrieve the result type for a function pointer. template + struct _Weak_result_type_impl<_CFun4<_Res,_ArgTypes...>*> + { typedef _Res result_type; }; + + template + struct _Weak_result_type_impl<_CFun5<_Res,_ArgTypes...>*> + { typedef _Res result_type; }; + + template struct _Weak_result_type_impl<_Res(*)(_ArgTypes...)> { typedef _Res result_type; }; Index: libstdc++-v3/include/ext/string_conversions.h =================================================================== --- libstdc++-v3/include/ext/string_conversions.h (revision 182769) +++ libstdc++-v3/include/ext/string_conversions.h (working copy) @@ -38,7 +38,7 @@ #include #include #include - +extern "C" template using _CFun=Ret(Args...); namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -47,7 +47,7 @@ template _Ret - __stoa(_TRet (*__convf) (const _CharT*, _CharT**, _Base...), + __stoa(_CFun<_TRet, const _CharT*, _CharT**, _Base...>*__convf, const char* __name, const _CharT* __str, std::size_t* __idx, _Base... __base) { @@ -76,8 +76,8 @@ // Helper for the to_string / to_wstring functions. template _String - __to_xstring(int (*__convf) (_CharT*, std::size_t, const _CharT*, - __builtin_va_list), std::size_t __n, + __to_xstring(_CFun*__convf, std::size_t __n, const _CharT* __fmt, ...) { // XXX Eventually the result will be constructed in place in Index: libstdc++-v3/include/ext/codecvt_specializations.h =================================================================== --- libstdc++-v3/include/ext/codecvt_specializations.h (revision 182769) +++ libstdc++-v3/include/ext/codecvt_specializations.h (working copy) @@ -37,6 +37,8 @@ #ifndef _EXT_CODECVT_SPECIALIZATIONS_H #define _EXT_CODECVT_SPECIALIZATIONS_H 1 +#pragma GCC system_header + #include #include #include @@ -218,7 +220,7 @@ _GLIBCXX_END_NAMESPACE_VERSION } // namespace - +extern "C" template using _CFun18=Ret(Args...); namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -297,7 +299,7 @@ // Using this adaptor, g++ will do the work for us. template inline size_t - __iconv_adaptor(size_t(*__func)(iconv_t, _Tp, size_t*, char**, size_t*), + __iconv_adaptor(_CFun18*__func, iconv_t __cd, char** __inbuf, size_t* __inbytes, char** __outbuf, size_t* __outbytes) { return __func(__cd, (_Tp)__inbuf, __inbytes, __outbuf, __outbytes); } Index: libstdc++-v3/include/ext/mt_allocator.h =================================================================== --- libstdc++-v3/include/ext/mt_allocator.h (revision 182769) +++ libstdc++-v3/include/ext/mt_allocator.h (working copy) @@ -35,7 +35,7 @@ #include #include #include - +extern "C" typedef void (*__initt)(); namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -440,7 +440,7 @@ { // On some platforms, __gthread_once_t is an aggregate. static __gthread_once_t __once = __GTHREAD_ONCE_INIT; - __gthread_once(&__once, _S_initialize); + __gthread_once(&__once, (__initt)_S_initialize); } // Double check initialization. May be necessary on some @@ -535,7 +535,7 @@ { // On some platforms, __gthread_once_t is an aggregate. static __gthread_once_t __once = __GTHREAD_ONCE_INIT; - __gthread_once(&__once, _S_initialize); + __gthread_once(&__once, (__initt)_S_initialize); } // Double check initialization. May be necessary on some Index: libstdc++-v3/include/c_global/cstdlib =================================================================== --- libstdc++-v3/include/c_global/cstdlib (revision 182769) +++ libstdc++-v3/include/c_global/cstdlib (working copy) @@ -95,6 +95,25 @@ #undef wcstombs #undef wctomb +extern "C" typedef int (*c_cmp_fun_t)(const void*, const void*); + +// libc could declare it with __asm("bsearch"), but it may not be safe to do +// that here +inline void * +bsearch(const void *__key, const void *__base, size_t __nmemb, size_t __size, + int (*__compar)(const void *, const void *)) +{ + return bsearch(__key, __base, __nmemb, __size, (c_cmp_fun_t)__compar); +} + +inline void +qsort(void* __base, size_t __nmemb, size_t __size, + int (*__compar)(const void*, const void*)) +{ + return qsort(__base, __nmemb, __size, (c_cmp_fun_t)__compar); +} + + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION Index: libstdc++-v3/include/tr1/type_traits =================================================================== --- libstdc++-v3/include/tr1/type_traits (revision 182769) +++ libstdc++-v3/include/tr1/type_traits (working copy) @@ -221,10 +221,21 @@ { }; /// is_function + extern "C" template using _CFun6=_Ret(_Args...); + extern "C" template using _CFun7=_Ret(_Args......); + template struct is_function : public false_type { }; +/* See about that later template + struct is_function<_CFun6<_Res,_ArgTypes...> > + : public true_type { }; + template + struct is_function<_CFun7<_Res,_ArgTypes...> > + : public true_type { }; +*/ + template struct is_function<_Res(_ArgTypes...)> : public true_type { }; template Index: libstdc++-v3/libsupc++/unwind-cxx.h =================================================================== --- libstdc++-v3/libsupc++/unwind-cxx.h (revision 182769) +++ libstdc++-v3/libsupc++/unwind-cxx.h (working copy) @@ -51,7 +51,7 @@ { // Manage the exception object itself. std::type_info *exceptionType; - void (_GLIBCXX_CDTOR_CALLABI *exceptionDestructor)(void *); + __cxa_dtor_type exceptionDestructor; // The C++ standard has entertaining rules wrt calling set_terminate // and set_unexpected in the middle of the exception cleanup process. Index: libstdc++-v3/libsupc++/eh_throw.cc =================================================================== --- libstdc++-v3/libsupc++/eh_throw.cc (revision 182769) +++ libstdc++-v3/libsupc++/eh_throw.cc (working copy) @@ -29,6 +29,7 @@ using namespace __cxxabiv1; +extern "C" { static void __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc) { @@ -55,11 +56,12 @@ } #endif } +} extern "C" void __cxxabiv1::__cxa_throw (void *obj, std::type_info *tinfo, - void (_GLIBCXX_CDTOR_CALLABI *dest) (void *)) + __cxa_dtor_type dest) { // Definitely a primary. __cxa_refcounted_exception *header Index: libstdc++-v3/libsupc++/eh_ptr.cc =================================================================== --- libstdc++-v3/libsupc++/eh_ptr.cc (revision 182769) +++ libstdc++-v3/libsupc++/eh_ptr.cc (working copy) @@ -173,6 +173,7 @@ } +extern "C" { static void __gxx_dependent_exception_cleanup(_Unwind_Reason_Code code, _Unwind_Exception *exc) @@ -199,6 +200,7 @@ __cxa_free_exception (header + 1); } } +} void Index: libstdc++-v3/libsupc++/vec.cc =================================================================== --- libstdc++-v3/libsupc++/vec.cc (revision 182769) +++ libstdc++-v3/libsupc++/vec.cc (working copy) @@ -31,7 +31,10 @@ #include #include #include "unwind-cxx.h" - +extern "C" typedef void* (*__mynewt)(std::size_t); +extern "C" typedef void (*__mydelt)(void*); +inline __mynewt castnewt(void*(*f)(std::size_t)){ return (__mynewt)f; } +inline __mydelt castdelt(void (*f)(void*)){ return (__mydelt)f; } namespace __cxxabiv1 { namespace @@ -71,9 +74,12 @@ { return __cxa_vec_new2(element_count, element_size, padding_size, constructor, destructor, - &operator new[], &operator delete []); + castnewt(&operator new[]), + castdelt(&operator delete [])); } + /* Strangely enough, the cxx abi seems to imply that operator new[] has C + linkage (or there is an implicit cast going on). */ extern "C" void * __cxa_vec_new2(std::size_t element_count, std::size_t element_size, @@ -286,7 +292,7 @@ { __cxa_vec_delete2(array_address, element_size, padding_size, destructor, - &operator delete []); + castdelt(&operator delete [])); } extern "C" void Index: libstdc++-v3/libsupc++/cxxabi.h =================================================================== --- libstdc++-v3/libsupc++/cxxabi.h (revision 182769) +++ libstdc++-v3/libsupc++/cxxabi.h (working copy) @@ -63,7 +63,7 @@ #endif typedef __cxa_cdtor_return_type (*__cxa_cdtor_type)(void *); - + typedef void (_GLIBCXX_CDTOR_CALLABI *__cxa_dtor_type) (void *); // Allocate array. void* __cxa_vec_new(size_t __element_count, size_t __element_size, @@ -600,7 +600,7 @@ // Throw the exception. void - __cxa_throw(void*, std::type_info*, void (_GLIBCXX_CDTOR_CALLABI *) (void *)) + __cxa_throw(void*, std::type_info*, __cxa_dtor_type) __attribute__((__noreturn__)); // Used to implement exception handlers. Index: include/demangle.h =================================================================== --- include/demangle.h (revision 182769) +++ include/demangle.h (working copy) @@ -290,6 +290,9 @@ /* The const qualifier. The one subtree is the type which is being qualified. */ DEMANGLE_COMPONENT_CONST, + /* extern "C" linkage. The one subtree is the function type which + is being qualified. */ + DEMANGLE_COMPONENT_EXTERN_C, /* The restrict qualifier modifying a member function. The one subtree is the type which is being qualified. */ DEMANGLE_COMPONENT_RESTRICT_THIS, Index: libiberty/cp-demangle.c =================================================================== --- libiberty/cp-demangle.c (revision 182769) +++ libiberty/cp-demangle.c (working copy) @@ -600,6 +600,9 @@ case DEMANGLE_COMPONENT_CONST: printf ("const\n"); break; + case DEMANGLE_COMPONENT_EXTERN_C: + printf ("extern \"C\"\n"); + break; case DEMANGLE_COMPONENT_RESTRICT_THIS: printf ("restrict this\n"); break; @@ -817,6 +820,7 @@ break; /* These types only require one parameter. */ + case DEMANGLE_COMPONENT_EXTERN_C: case DEMANGLE_COMPONENT_VTABLE: case DEMANGLE_COMPONENT_VTT: case DEMANGLE_COMPONENT_TYPEINFO: @@ -2401,18 +2405,22 @@ d_function_type (struct d_info *di) { struct demangle_component *ret; + int is_extern_c = 0; if (! d_check_char (di, 'F')) return NULL; if (d_peek_char (di) == 'Y') { - /* Function has C linkage. We don't print this information. - FIXME: We should print it in verbose mode. */ + /* Function has C linkage. */ + is_extern_c = 1; d_advance (di, 1); + di->expansion += sizeof "extern \"C\""; } ret = d_bare_function_type (di, 1); if (! d_check_char (di, 'E')) return NULL; + if (is_extern_c) + ret = d_make_comp (di, DEMANGLE_COMPONENT_EXTERN_C, ret, NULL); return ret; } @@ -4041,6 +4049,7 @@ case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: + case DEMANGLE_COMPONENT_EXTERN_C: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_COMPLEX: @@ -4660,7 +4669,8 @@ || (! suffix && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS))) + || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS + || mods->mod->type == DEMANGLE_COMPONENT_EXTERN_C))) { d_print_mod_list (dpi, options, mods->next, suffix); return; @@ -4751,6 +4761,9 @@ case DEMANGLE_COMPONENT_CONST_THIS: d_append_string (dpi, " const"); return; + case DEMANGLE_COMPONENT_EXTERN_C: + d_append_string (dpi, " extern \"C\""); + return; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: d_append_char (dpi, ' '); d_print_comp (dpi, options, d_right (mod)); @@ -4834,6 +4847,7 @@ case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: + case DEMANGLE_COMPONENT_EXTERN_C: break; default: break; Index: libgcc/gthr-posix.h =================================================================== --- libgcc/gthr-posix.h (revision 182769) +++ libgcc/gthr-posix.h (working copy) @@ -319,6 +319,10 @@ # include #endif +#ifdef __cplusplus +extern "C" { +#endif + /* Key structure for maintaining thread specific storage */ static pthread_key_t _objc_thread_storage; static pthread_attr_t _objc_thread_attribs; @@ -660,6 +664,10 @@ #else /* _LIBOBJC */ +#ifdef __cplusplus +extern "C" { +#endif + static inline int __gthread_create (__gthread_t *__threadid, void *(*__func) (void*), void *__args) @@ -874,6 +882,10 @@ return __gthrw_(pthread_cond_destroy) (__cond); } +#ifdef __cplusplus +} +#endif + #endif /* _LIBOBJC */ #endif /* ! GCC_GTHR_POSIX_H */ Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 182769) +++ gcc/tree.c (working copy) @@ -7516,13 +7516,14 @@ If such a type has already been constructed, reuse it. */ tree -build_function_type (tree value_type, tree arg_types) +build_function_type2 (tree value_type, tree arg_types, int extern_c) { tree t; hashval_t hashcode = 0; bool any_structural_p, any_noncanonical_p; tree canon_argtypes; + if (extern_c != 0) extern_c = 1; if (TREE_CODE (value_type) == FUNCTION_TYPE) { error ("function return type cannot be function"); @@ -7533,10 +7534,15 @@ t = make_node (FUNCTION_TYPE); TREE_TYPE (t) = value_type; TYPE_ARG_TYPES (t) = arg_types; + if(extern_c) + { + TYPE_MINVAL (t) = integer_one_node; + } /* If we already have such a type, use the old one. */ hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode); hashcode = type_hash_list (arg_types, hashcode); + hashcode = iterative_hash_object (extern_c, hashcode); t = type_hash_canon (hashcode, t); /* Set up the canonical type. */ @@ -7548,13 +7554,18 @@ if (any_structural_p) SET_TYPE_STRUCTURAL_EQUALITY (t); else if (any_noncanonical_p) - TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type), - canon_argtypes); + TYPE_CANONICAL (t) = build_function_type2 (TYPE_CANONICAL (value_type), + canon_argtypes, extern_c); if (!COMPLETE_TYPE_P (t)) layout_type (t); return t; } +tree +build_function_type (tree value_type, tree arg_types) +{ + return build_function_type2 (value_type, arg_types, 0); +} /* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP. */ @@ -9694,7 +9705,7 @@ else if (TREE_CODE (type) == FUNCTION_TYPE) { inner = reconstruct_complex_type (TREE_TYPE (type), bottom); - outer = build_function_type (inner, TYPE_ARG_TYPES (type)); + outer = build_function_type2 (inner, TYPE_ARG_TYPES (type), TYPE_MINVAL(type)!=0); } else if (TREE_CODE (type) == METHOD_TYPE) { Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 182769) +++ gcc/tree.h (working copy) @@ -4385,6 +4385,7 @@ extern tree build_nonshared_array_type (tree, tree); extern tree build_array_type_nelts (tree, unsigned HOST_WIDE_INT); extern tree build_function_type (tree, tree); +extern tree build_function_type2 (tree, tree, int); extern tree build_function_type_list (tree, ...); extern tree build_function_type_skip_args (tree, bitmap); extern tree build_function_decl_skip_args (tree, bitmap); Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 182769) +++ gcc/cp/typeck.c (working copy) @@ -506,6 +506,12 @@ types. */ if (same_type_ignoring_top_level_qualifiers_p (pointee1, pointee2)) result_type = pointee1; + else if (comptypes (TYPE_MAIN_VARIANT (pointee1), TYPE_MAIN_VARIANT (pointee2), COMPARE_IGNOREEXTC)) + { + result_type = pointee1; + if (complain & tf_warning) + warning_at (input_location, OPT_Wall, "invalid composition of %qT and %qT", t1, t2); + } else if ((TREE_CODE (pointee1) == POINTER_TYPE && TREE_CODE (pointee2) == POINTER_TYPE) || (TYPE_PTR_TO_MEMBER_P (pointee1) @@ -830,7 +836,7 @@ else parms = commonparms (p1, p2); - rval = build_function_type (valtype, parms); + rval = build_function_type2 (valtype, parms, TYPE_MINVAL (t1) != 0); gcc_assert (type_memfn_quals (t1) == type_memfn_quals (t2)); rval = apply_memfn_quals (rval, type_memfn_quals (t1)); raises = merge_exception_specifiers (TYPE_RAISES_EXCEPTIONS (t1), @@ -1275,16 +1281,18 @@ case POINTER_TYPE: if (TYPE_MODE (t1) != TYPE_MODE (t2) || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2) - || !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) + || !comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict & COMPARE_IGNOREEXTC)) return false; break; case METHOD_TYPE: case FUNCTION_TYPE: - if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))) + if (!comptypes (TREE_TYPE (t1), TREE_TYPE (t2), strict & COMPARE_IGNOREEXTC)) return false; - if (!compparms (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2))) + if (!compparms2 (TYPE_ARG_TYPES (t1), TYPE_ARG_TYPES (t2), strict & COMPARE_IGNOREEXTC)) return false; + if (!(strict & COMPARE_IGNOREEXTC) && (TYPE_MINVAL (t1) != TYPE_MINVAL (t2))) + return false; break; case ARRAY_TYPE: @@ -1385,12 +1393,14 @@ bool result = structural_comptypes (t1, t2, strict); if (result && TYPE_CANONICAL (t1) != TYPE_CANONICAL (t2)) + { /* The two types are structurally equivalent, but their canonical types were different. This is a failure of the canonical type propagation code.*/ internal_error ("canonical types differ for identical types %T and %T", t1, t2); + } else if (!result && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2)) /* Two types are structurally different, but the canonical types are the same. This means we were over-eager in @@ -1481,7 +1491,7 @@ element by element. */ bool -compparms (const_tree parms1, const_tree parms2) +compparms2 (const_tree parms1, const_tree parms2, int strict) { const_tree t1, t2; @@ -1496,11 +1506,16 @@ they fail to match. */ if (!t1 || !t2) return false; - if (!same_type_p (TREE_VALUE (t1), TREE_VALUE (t2))) + if (!comptypes (TREE_VALUE (t1), TREE_VALUE (t2), strict)) return false; } return true; } +bool +compparms (const_tree parms1, const_tree parms2) +{ + return compparms2 (parms1, parms2, COMPARE_STRICT); +} /* Process a sizeof or alignof expression where the operand is a Index: gcc/cp/class.c =================================================================== --- gcc/cp/class.c (revision 182769) +++ gcc/cp/class.c (working copy) @@ -6766,6 +6766,8 @@ are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy interoperability with most_specialized_instantiation. */ tree matches = NULL_TREE; + tree matches2 = NULL_TREE; + bool hasmatch2 = 0; tree fn; tree target_fn_type; @@ -6835,12 +6837,16 @@ /* See if there's a match. */ if (same_type_p (target_fn_type, static_fn_type (fn))) matches = tree_cons (fn, NULL_TREE, matches); + /* See if there's a match. */ + if (comptypes (target_fn_type, static_fn_type (fn), COMPARE_IGNOREEXTC)) + matches2 = tree_cons (fn, NULL_TREE, matches2); } } /* Now, if we've already got a match (or matches), there's no need to proceed to the template functions. But, if we don't have a match we need to look at them, too. */ + hasmatch2 = !matches2; if (!matches) { tree target_arg_types; @@ -6894,6 +6900,9 @@ /* See if there's a match. */ if (same_type_p (target_fn_type, static_fn_type (instantiation))) matches = tree_cons (instantiation, fn, matches); + /* See if there's a match. */ + if (!hasmatch2 && comptypes (target_fn_type, static_fn_type (instantiation), COMPARE_IGNOREEXTC)) + matches2 = tree_cons (instantiation, fn, matches2); } /* Now, remove all but the most specialized of the matches. */ @@ -6909,6 +6918,7 @@ } /* Now we should have exactly one function in MATCHES. */ + if (matches == NULL_TREE) matches = matches2; if (matches == NULL_TREE) { /* There were *no* matches. */ Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 182769) +++ gcc/cp/decl.c (working copy) @@ -9290,7 +9290,7 @@ parms = NULL_TREE; } - type = build_function_type (type, arg_types); + type = build_function_type2 (type, arg_types, current_lang_name == lang_name_c); } break; Index: gcc/cp/error.c =================================================================== --- gcc/cp/error.c (revision 182769) +++ gcc/cp/error.c (working copy) @@ -834,6 +834,8 @@ pp_cxx_cv_qualifier_seq (cxx_pp, class_of_this_parm (t)); else pp_cxx_cv_qualifier_seq (cxx_pp, t); + if (TREE_CODE (t) == FUNCTION_TYPE && TYPE_MINVAL (t)) + pp_string (cxx_pp, " extern \"C\""); dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags); dump_type_suffix (TREE_TYPE (t), flags); break; Index: gcc/cp/tree.c =================================================================== --- gcc/cp/tree.c (revision 182769) +++ gcc/cp/tree.c (working copy) @@ -1154,8 +1154,8 @@ } else { - result = build_function_type (type, - arg_types); + result = build_function_type2 (type, arg_types, + TYPE_MINVAL (t) != 0); result = apply_memfn_quals (result, type_memfn_quals (t)); } Index: gcc/cp/pt.c =================================================================== --- gcc/cp/pt.c (revision 182769) +++ gcc/cp/pt.c (working copy) @@ -10947,7 +10947,7 @@ /* Construct a new type node and return it. */ if (TREE_CODE (t) == FUNCTION_TYPE) { - fntype = build_function_type (return_type, arg_types); + fntype = build_function_type2 (return_type, arg_types, TYPE_MINVAL (t)!=0); fntype = apply_memfn_quals (fntype, type_memfn_quals (t)); } else Index: gcc/cp/decl2.c =================================================================== --- gcc/cp/decl2.c (revision 182769) +++ gcc/cp/decl2.c (working copy) @@ -157,7 +157,7 @@ if (TREE_CODE (fntype) == FUNCTION_TYPE) { - newtype = build_function_type (new_ret, args); + newtype = build_function_type2 (new_ret, args, TYPE_MINVAL (fntype) != 0); newtype = apply_memfn_quals (newtype, type_memfn_quals (fntype)); } else @@ -1252,7 +1252,7 @@ else if (TREE_CODE (type) == FUNCTION_TYPE) { inner = cp_reconstruct_complex_type (TREE_TYPE (type), bottom); - outer = build_function_type (inner, TYPE_ARG_TYPES (type)); + outer = build_function_type2 (inner, TYPE_ARG_TYPES (type), TYPE_MINVAL (type) != 0); outer = apply_memfn_quals (outer, type_memfn_quals (type)); } else if (TREE_CODE (type) == METHOD_TYPE) Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 182769) +++ gcc/cp/parser.c (working copy) @@ -13754,7 +13754,7 @@ /* If it's not a class-name, keep looking. */ if (!cp_parser_parse_definitely (parser)) { - if (cxx_dialect < cxx0x) + if ((cxx_dialect < cxx0x) && !in_system_header) /* It must be a typedef-name or an enum-name. */ return cp_parser_nonclass_name (parser); @@ -21179,6 +21179,7 @@ VEC (deferred_access_check,gc) *checks; tree parameter_list; bool friend_p = false; + location_t loc_c_linkage_error; bool need_lang_pop; cp_token *token; @@ -21205,7 +21206,7 @@ A template ... shall not have C linkage. */ if (current_lang_name == lang_name_c) { - error_at (token->location, "template with C linkage"); + loc_c_linkage_error = token->location; /* Give it C++ linkage to avoid confusing other parts of the front end. */ push_lang_context (lang_name_cplusplus); @@ -21250,9 +21251,18 @@ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) cp_parser_template_declaration_after_export (parser, member_p); - else if (cxx_dialect >= cxx0x + else if ((cxx_dialect >= cxx0x || in_system_header) && cp_lexer_next_token_is_keyword (parser->lexer, RID_USING)) - decl = cp_parser_alias_declaration (parser); + { + /* For a template alias, C linkage should be OK, although it is possible + that the standard officially forbids it currently */ + if (need_lang_pop) + { + need_lang_pop = false; + pop_lang_context (); + } + decl = cp_parser_alias_declaration (parser); + } else { /* There are no access checks when parsing a template, as we do not @@ -21320,7 +21330,10 @@ /* For the erroneous case of a template with C linkage, we pushed an implicit C++ linkage scope; exit that scope now. */ if (need_lang_pop) - pop_lang_context (); + { + error_at (loc_c_linkage_error, "template with C linkage"); + pop_lang_context (); + } /* If DECL is a function template, we must return to parse it later. (Even though there is no definition, there might be default arguments that need handling.) */ Index: gcc/cp/call.c =================================================================== --- gcc/cp/call.c (revision 182769) +++ gcc/cp/call.c (working copy) @@ -71,6 +71,7 @@ cr_pbool, cr_user, cr_ellipsis, + cr_extc, cr_bad } conversion_rank; @@ -1256,6 +1257,12 @@ else if (c_dialect_objc () && objc_compare_types (to, from, -4, NULL_TREE)) conv = build_conv (ck_ptr, to, conv); + else if (comptypes (from, to, COMPARE_IGNOREEXTC)) + { + conv = build_conv (ck_ptr, to, conv); + if (conv->rank < cr_extc) + conv->rank = cr_extc; + } else if (ptr_reasonably_similar (to_pointee, from_pointee)) { conv = build_conv (ck_ptr, to, conv); @@ -5671,6 +5678,15 @@ if (issue_conversion_warnings && (complain & tf_warning)) conversion_null_warnings (totype, expr, fn, argnum); + if (issue_conversion_warnings && (complain & tf_warning) && convs->rank == cr_extc) + { + warning_at (input_location, OPT_Wall, "invalid conversion from %qT to %qT", + TREE_TYPE (expr), totype); + if (fn) + warning_at (DECL_SOURCE_LOCATION (fn), OPT_Wall, + " initializing argument %P of %qD", argnum, fn); + } + switch (convs->kind) { case ck_user: Index: gcc/cp/mangle.c =================================================================== --- gcc/cp/mangle.c (revision 182769) +++ gcc/cp/mangle.c (working copy) @@ -2285,6 +2285,8 @@ } write_char ('F'); + if(TYPE_MINVAL (type)) + write_char ('Y'); /* We don't track whether or not a type is `extern "C"'. Note that you can have an `extern "C"' function that does not have `extern "C"' type, and vice versa: Index: gcc/cp/cp-tree.h =================================================================== --- gcc/cp/cp-tree.h (revision 182769) +++ gcc/cp/cp-tree.h (working copy) @@ -4471,6 +4471,8 @@ structural. The actual comparison will be identical to COMPARE_STRICT. */ +#define COMPARE_IGNOREEXTC 16 /* The comparison should ignore + extern "C" on function types. */ /* Used with push_overloaded_decl. */ #define PUSH_GLOBAL 0 /* Push the DECL into namespace scope, @@ -5755,6 +5757,7 @@ extern bool comptypes (tree, tree, int); extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree); extern bool compparms (const_tree, const_tree); +extern bool compparms2 (const_tree, const_tree, int); extern int comp_cv_qualification (const_tree, const_tree); extern int comp_cv_qual_signature (tree, tree); extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code, bool);