Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 154010) +++ gcc/tree.c (working copy) @@ -5307,7 +5307,8 @@ handle_dll_attribute (tree * pnode, tree name, tre if (TREE_CODE (node) != FUNCTION_DECL && TREE_CODE (node) != VAR_DECL - && TREE_CODE (node) != TYPE_DECL) + && TREE_CODE (node) != TYPE_DECL + && TREE_CODE (node) != NAMESPACE_DECL) { *no_add_attrs = true; warning (OPT_Wattributes, "%qE attribute ignored", Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 154010) +++ gcc/cp/parser.c (working copy) @@ -12854,7 +12854,7 @@ cp_parser_namespace_definition (cp_parser* parser) push_namespace (identifier); } - has_visibility = handle_namespace_attrs (current_namespace, attribs); + has_visibility = handle_namespace_attrs (¤t_namespace, attribs); /* Parse the body of the namespace. */ cp_parser_namespace_body (parser); Index: gcc/cp/name-lookup.c =================================================================== --- gcc/cp/name-lookup.c (revision 154010) +++ gcc/cp/name-lookup.c (working copy) @@ -3192,7 +3192,7 @@ current_decl_namespace (void) NAMESPACE_DECL at all. Returns true if attribute visibility is seen. */ bool -handle_namespace_attrs (tree ns, tree attributes) +handle_namespace_attrs (tree *ns, tree attributes) { tree d; bool saw_vis = false; @@ -3214,7 +3214,7 @@ bool continue; } - if (!TREE_PUBLIC (ns)) + if (!TREE_PUBLIC (*ns)) warning (OPT_Wattributes, "%qD attribute is meaningless since members of the " "anonymous namespace get local symbols", name); @@ -3224,7 +3224,12 @@ bool } else #endif + if (is_attribute_p ("dllimport", name) || is_attribute_p ("dllexport", name)) { + cplus_decl_attributes (ns, attributes, 0); + } + else + { warning (OPT_Wattributes, "%qD attribute directive ignored", name); continue; Index: gcc/cp/name-lookup.h =================================================================== --- gcc/cp/name-lookup.h (revision 154010) +++ gcc/cp/name-lookup.h (working copy) @@ -304,7 +304,7 @@ extern void push_namespace (tree); extern void pop_namespace (void); extern void push_nested_namespace (tree); extern void pop_nested_namespace (tree); -extern bool handle_namespace_attrs (tree, tree); +extern bool handle_namespace_attrs (tree *, tree); extern void pushlevel_class (void); extern void poplevel_class (void); extern tree pushdecl_with_scope (tree, cxx_scope *, bool); Index: gcc/config/i386/winnt-stubs.c =================================================================== --- gcc/config/i386/winnt-stubs.c (revision 154010) +++ gcc/config/i386/winnt-stubs.c (working copy) @@ -46,6 +46,11 @@ i386_pe_type_dllexport_p (tree decl ATTRIBUTE_UNUS return false; } +bool +inherit_dllattribute_from_namespace (const char *attrname ATTRIBUTE_UNUSED, tree context ATTRIBUTE_UNUSED) +{ + return false; +} void i386_pe_adjust_class_at_definition (tree t ATTRIBUTE_UNUSED) Index: gcc/config/i386/winnt.c =================================================================== --- gcc/config/i386/winnt.c (revision 154010) +++ gcc/config/i386/winnt.c (working copy) @@ -112,7 +112,7 @@ i386_pe_determine_dllexport_p (tree decl) if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) return true; - return false; + return inherit_dllattribute_from_namespace ("dllexport", /*DECL_CONTEXT*/ (decl)); } /* Return true if DECL should be a dllimport'd object. */ @@ -143,7 +143,7 @@ i386_pe_determine_dllimport_p (tree decl) error ("definition of static data member %q+D of " "dllimport'd class", decl); - return false; + return inherit_dllattribute_from_namespace ("dllimport", /*DECL_CONTEXT*/ (decl)); } /* Handle the -mno-fun-dllimport target switch. */ @@ -603,6 +603,64 @@ i386_pe_maybe_record_exported_symbol (tree decl, c export_head = p; } +#ifdef CXX_WRAP_SPEC_LIST + +/* Hash table equality helper function. */ + +static int +wrapper_strcmp (const void *x, const void *y) +{ + return !strcmp ((const char *) x, (const char *) y); +} + +/* Search for a function named TARGET in the list of library wrappers + we are using, returning a pointer to it if found or NULL if not. + This function might be called on quite a few symbols, and we only + have the list of names of wrapped functions available to us as a + spec string, so first time round we lazily initialise a hash table + to make things quicker. */ + +static const char * +i386_find_on_wrapper_list (const char *target) +{ + static char first_time = 1; + static htab_t wrappers; + + if (first_time) + { + /* Beware that this is not a complicated parser, it assumes + that any sequence of non-whitespace beginning with an + underscore is one of the wrapped symbols. For now that's + adequate to distinguish symbols from spec substitutions + and command-line options. */ + static char wrapper_list_buffer[] = CXX_WRAP_SPEC_LIST; + char *bufptr; + /* Breaks up the char array into separated strings + strings and enter them into the hash table. */ + wrappers = htab_create_alloc (8, htab_hash_string, wrapper_strcmp, + 0, xcalloc, free); + for (bufptr = wrapper_list_buffer; *bufptr; ++bufptr) + { + char *found = NULL; + if (ISSPACE (*bufptr)) + continue; + if (*bufptr == '_') + found = bufptr; + while (*bufptr && !ISSPACE (*bufptr)) + ++bufptr; + if (*bufptr) + *bufptr = 0; + if (found) + *htab_find_slot (wrappers, found, INSERT) = found; + } + first_time = 0; + } + + return (const char *) htab_find (wrappers, target); +} + +#endif /* CXX_WRAP_SPEC_LIST */ + /* This is called at the end of assembly. For each external function which has not been defined, we output a declaration now. We also output the .drectve section. */ @@ -624,6 +682,15 @@ i386_pe_file_end (void) if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) { +#ifdef CXX_WRAP_SPEC_LIST + /* To ensure the DLL that provides the corresponding real + functions is still loaded at runtime, we must reference + the real function so that an (unused) import is created. */ + const char *realsym = i386_find_on_wrapper_list (p->name); + if (realsym) + i386_pe_declare_function_type (asm_out_file, + concat ("__real_", realsym, NULL), TREE_PUBLIC (decl)); +#endif /* CXX_WRAP_SPEC_LIST */ TREE_ASM_WRITTEN (decl) = 1; i386_pe_declare_function_type (asm_out_file, p->name, TREE_PUBLIC (decl)); Index: gcc/config/i386/winnt-cxx.c =================================================================== --- gcc/config/i386/winnt-cxx.c (revision 154010) +++ gcc/config/i386/winnt-cxx.c (working copy) @@ -91,15 +91,115 @@ static inline void maybe_add_dllexport (tree decl) } } +static bool +inherit_dllattribute_from_namespace_1 (const char *attrname, tree context) +{ + if (context == NULL_TREE || context == global_namespace) + return false; + + /*fflush (0); fprintf (stderr, "inherit1: %s\n", attrname); fflush (0); + debug_tree (context);*/ + + if (CLASS_TYPE_P (context)) + { + return lookup_attribute (attrname, TYPE_ATTRIBUTES (context)) != NULL_TREE + || inherit_dllattribute_from_namespace_1 (attrname, CP_TYPE_CONTEXT (context)); + } + else if (TREE_CODE (context) == NAMESPACE_DECL) + { + return lookup_attribute (attrname, DECL_ATTRIBUTES (context)) != NULL_TREE + || (inherit_dllattribute_from_namespace_1 (attrname, CP_DECL_CONTEXT (context))); + } + else if (TREE_CODE (context) == FUNCTION_DECL) + { + /* Types declared in a function don't get exported just because + the function itself is, so we don't call lookup_attribute. */ + /* If the context is a nested function, don't escape. */ + return (TREE_CODE (CP_DECL_CONTEXT (context)) != FUNCTION_DECL + && inherit_dllattribute_from_namespace_1 (attrname, CP_DECL_CONTEXT (context))); + } + + fflush (0); fprintf (stderr, "unknown tree code\n"); fflush (0); + debug_tree (context); + + return false; +} + +/* The only valid inputs T to this function are VAR_DECL and FUNCTION_DECL + nodes passed in from i386_pe_determine_dll{im,ex}port_p, and class type + nodes passed in from i386_pe_adjust_class_at_definition. */ +bool +inherit_dllattribute_from_namespace (const char *attrname, tree t) +{ + tree tinfo = NULL_TREE; + tree context = NULL_TREE; + + /*fflush (0); fprintf (stderr, "inherit: %s\n", attrname); fflush (0); + debug_tree (t);*/ + + if (t == NULL_TREE) + return false; + + if (CLASS_TYPE_P (t)) + context = CP_TYPE_CONTEXT (t); + else if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL) + context = CP_DECL_CONTEXT (t); + + if (inherit_dllattribute_from_namespace_1 (attrname, context)) + return true; + + /*fflush (0); fprintf (stderr, "inherit2: %s\n", attrname); fflush (0); + debug_tree (context);*/ + + /*if (context == NULL_TREE || context == global_namespace) + return false;*/ + + if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL) + && DECL_LANG_SPECIFIC (t) + && DECL_USE_TEMPLATE (t) + && DECL_TEMPLATE_INFO (t)) + { + tinfo = DECL_TEMPLATE_INFO (t); + } + else if (CLASS_TYPE_P (t) + && TYPE_LANG_SPECIFIC (t) + && CLASSTYPE_USE_TEMPLATE (t) + && CLASSTYPE_TEMPLATE_INFO (t)) + { + tinfo = CLASSTYPE_TEMPLATE_INFO (t); + } + + if (tinfo) + { + tree ti_template = TI_TEMPLATE (tinfo); + /*fflush (0); fprintf (stderr, "inherit3: %s\n", attrname); fflush (0); + debug_tree (ti_template);*/ + gcc_assert (TREE_CODE (ti_template) == TEMPLATE_DECL); + return inherit_dllattribute_from_namespace_1 (attrname, CP_DECL_CONTEXT (ti_template)); + } + + return false; +} + void i386_pe_adjust_class_at_definition (tree t) { tree member; + bool is_import, is_export; gcc_assert (CLASS_TYPE_P (t)); + is_export = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (t)) != NULL_TREE; + if (!is_export) + is_export = inherit_dllattribute_from_namespace ("dllexport", /*CP_TYPE_CONTEXT*/ (t)); + if (!is_export) + { + is_import = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) != NULL_TREE; + if (!is_export && !is_import) + is_import = inherit_dllattribute_from_namespace ("dllimport", /*CP_TYPE_CONTEXT*/ (t)); + } - if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (t)) != NULL_TREE) + if (is_export) { /* Check static VAR_DECL's. */ for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) @@ -124,7 +224,7 @@ i386_pe_adjust_class_at_definition (tree t) maybe_add_dllexport (member); } - else if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) != NULL_TREE) + else if (is_import) { /* We don't actually add the attribute to the decl, just set the flag that signals that the address of this symbol is not a compile-time Index: gcc/config/i386/i386-protos.h =================================================================== --- gcc/config/i386/i386-protos.h (revision 154010) +++ gcc/config/i386/i386-protos.h (working copy) @@ -240,6 +240,7 @@ extern void i386_pe_file_end (void); extern tree i386_pe_mangle_decl_assembler_name (tree, tree); /* In winnt-cxx.c and winnt-stubs.c */ +extern bool inherit_dllattribute_from_namespace (const char *, tree); extern void i386_pe_adjust_class_at_definition (tree); extern bool i386_pe_type_dllimport_p (tree); extern bool i386_pe_type_dllexport_p (tree);