Index: libitm/clone.cc =================================================================== --- libitm/clone.cc (revision 182769) +++ libitm/clone.cc (working copy) @@ -96,6 +96,7 @@ return ret; } +extern "C" { // provide the true qsort prototype instead static int clone_entry_compare (const void *a, const void *b) { @@ -109,6 +110,7 @@ else return 0; } +} namespace { 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) @@ -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/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 Fun=Ret(Args...); namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -73,6 +73,35 @@ return __ret; } + template + _Ret + __stoa(Fun<_TRet, const _CharT*, _CharT**, _Base...>*__convf, + const char* __name, const _CharT* __str, std::size_t* __idx, + _Base... __base) + { + _Ret __ret; + + _CharT* __endptr; + errno = 0; + const _TRet __tmp = __convf(__str, &__endptr, __base...); + + if (__endptr == __str) + std::__throw_invalid_argument(__name); + else if (errno == ERANGE + || (std::__are_same<_Ret, int>::__value + && (__tmp < __numeric_traits::__min + || __tmp > __numeric_traits::__max))) + std::__throw_out_of_range(__name); + else + __ret = __tmp; + + if (__idx) + *__idx = __endptr - __str; + + return __ret; + } + // Helper for the to_string / to_wstring functions. template _String @@ -95,6 +124,27 @@ return _String(__s, __s + __len); } + template + _String + __to_xstring(Fun*__convf, std::size_t __n, + const _CharT* __fmt, ...) + { + // XXX Eventually the result will be constructed in place in + // the C++0x string, likely with the help of internal hooks. + _CharT* __s = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) + * __n)); + + __builtin_va_list __args; + __builtin_va_start(__args, __fmt); + + const int __len = __convf(__s, __n, __fmt, __args); + + __builtin_va_end(__args); + + return _String(__s, __s + __len); + } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace 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) @@ -218,7 +218,7 @@ _GLIBCXX_END_NAMESPACE_VERSION } // namespace - +extern "C" template using Fun18=Ret(Args...); namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -297,7 +297,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(Fun18*__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/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)); } 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) @@ -830,7 +830,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), @@ -1281,10 +1281,12 @@ 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 +1387,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 +1485,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 +1500,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)); 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) @@ -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); @@ -21252,7 +21253,16 @@ cp_parser_template_declaration_after_export (parser, member_p); else if (cxx_dialect >= cxx0x && 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/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);