From 3288746035c8699973d9242284606f1aad2465d2 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 30 Jan 2013 19:04:34 +0100 Subject: [PATCH] re PR c++/55742 (__attribute__ in class function declaration cause "prototype does not match" errors.) PR c++/55742 * config/i386/i386.c (ix86_valid_target_attribute_inner_p): Diagnose invalid args instead of ICEing on it. (ix86_valid_target_attribute_tree): Return error_mark_node if ix86_valid_target_attribute_inner_p failed. (ix86_valid_target_attribute_p): Return false only if ix86_valid_target_attribute_tree returned error_mark_node. Allow target("default") attribute. (sorted_attr_string): Change argument from const char * to tree, merge in all target attribute arguments rather than just one. Formatting fix. Use XNEWVEC instead of xmalloc and XDELETEVEC instead of free. Avoid using strcat. (ix86_mangle_function_version_assembler_name): Mangle target("default") as if no target attribute is present. Adjust sorted_attr_string caller. Avoid leaking memory. Use XNEWVEC instead of xmalloc and XDELETEVEC instead of free. (ix86_function_versions): Don't return true if one of the decls doesn't have target attribute. If they don't and one of the decls is DECL_FUNCTION_VERSIONED, report an error. Adjust sorted_attr_string caller. Use XDELETEVEC instead of free. (ix86_supports_function_versions): Remove. (make_name): Fix up formatting. (make_dispatcher_decl): Remove resolver_name and its initialization. Avoid leaking memory. (is_function_default_version): Return true if there is target("default") attribute rather than no target attribute at all. (make_resolver_func): Avoid leaking memory. (ix86_generate_version_dispatcher_body): Likewise. (TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS): Remove. * target.def (supports_function_versions): Remove. * doc/tm.texi.in (SUPPORTS_FUNCTION_VERSIONS): Remove. * doc/tm.texi: Regenerated. * c-common.c (handle_target_attribute): Revert 2012-12-26 change. * g++.dg/mv1.C: Moved to... * g++.dg/ext/mv1.C: ... here. Adjust test. * g++.dg/mv2.C: Moved to... * g++.dg/ext/mv2.C: ... here. Adjust test. * g++.dg/mv3.C: Moved to... * g++.dg/ext/mv3.C: ... here. * g++.dg/mv4.C: Moved to... * g++.dg/ext/mv4.C: ... here. * g++.dg/mv5.C: Moved to... * g++.dg/ext/mv5.C: ... here. Adjust test. * g++.dg/mv6.C: Moved to... * g++.dg/ext/mv6.C: ... here. Adjust test. * g++.dg/ext/mv7.C: New test. * g++.dg/ext/mv8.C: New test. * g++.dg/ext/mv9.C: New test. * g++.dg/ext/mv10.C: New test. * g++.dg/ext/mv11.C: New test. From-SVN: r195584 --- gcc/ChangeLog | 35 ++++++++ gcc/c-family/ChangeLog | 5 ++ gcc/c-family/c-common.c | 6 +- gcc/config/i386/i386.c | 165 +++++++++++++++++++++++------------ gcc/doc/tm.texi | 5 -- gcc/doc/tm.texi.in | 5 -- gcc/target.def | 8 -- gcc/testsuite/ChangeLog | 21 +++++ gcc/testsuite/g++.dg/{ => ext}/mv1.C | 6 +- gcc/testsuite/g++.dg/ext/mv10.C | 12 +++ gcc/testsuite/g++.dg/ext/mv11.C | 23 +++++ gcc/testsuite/g++.dg/{ => ext}/mv2.C | 4 +- gcc/testsuite/g++.dg/{ => ext}/mv3.C | 0 gcc/testsuite/g++.dg/{ => ext}/mv4.C | 0 gcc/testsuite/g++.dg/{ => ext}/mv5.C | 2 +- gcc/testsuite/g++.dg/{ => ext}/mv6.C | 1 + gcc/testsuite/g++.dg/ext/mv7.C | 12 +++ gcc/testsuite/g++.dg/ext/mv8.C | 7 ++ gcc/testsuite/g++.dg/ext/mv9.C | 9 ++ 19 files changed, 240 insertions(+), 86 deletions(-) rename gcc/testsuite/g++.dg/{ => ext}/mv1.C (94%) create mode 100644 gcc/testsuite/g++.dg/ext/mv10.C create mode 100644 gcc/testsuite/g++.dg/ext/mv11.C rename gcc/testsuite/g++.dg/{ => ext}/mv2.C (96%) rename gcc/testsuite/g++.dg/{ => ext}/mv3.C (100%) rename gcc/testsuite/g++.dg/{ => ext}/mv4.C (100%) rename gcc/testsuite/g++.dg/{ => ext}/mv5.C (88%) rename gcc/testsuite/g++.dg/{ => ext}/mv6.C (92%) create mode 100644 gcc/testsuite/g++.dg/ext/mv7.C create mode 100644 gcc/testsuite/g++.dg/ext/mv8.C create mode 100644 gcc/testsuite/g++.dg/ext/mv9.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0eb5f7c..dd0b294 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2013-01-30 Jakub Jelinek + + PR c++/55742 + * config/i386/i386.c (ix86_valid_target_attribute_inner_p): Diagnose + invalid args instead of ICEing on it. + (ix86_valid_target_attribute_tree): Return error_mark_node if + ix86_valid_target_attribute_inner_p failed. + (ix86_valid_target_attribute_p): Return false only if + ix86_valid_target_attribute_tree returned error_mark_node. Allow + target("default") attribute. + (sorted_attr_string): Change argument from const char * to tree, + merge in all target attribute arguments rather than just one. + Formatting fix. Use XNEWVEC instead of xmalloc and XDELETEVEC + instead of free. Avoid using strcat. + (ix86_mangle_function_version_assembler_name): Mangle + target("default") as if no target attribute is present. Adjust + sorted_attr_string caller. Avoid leaking memory. Use XNEWVEC + instead of xmalloc and XDELETEVEC instead of free. + (ix86_function_versions): Don't return true if one of the decls + doesn't have target attribute. If they don't and one of the decls + is DECL_FUNCTION_VERSIONED, report an error. Adjust + sorted_attr_string caller. Use XDELETEVEC instead of free. + (ix86_supports_function_versions): Remove. + (make_name): Fix up formatting. + (make_dispatcher_decl): Remove resolver_name and its initialization. + Avoid leaking memory. + (is_function_default_version): Return true if there is + target("default") attribute rather than no target attribute at all. + (make_resolver_func): Avoid leaking memory. + (ix86_generate_version_dispatcher_body): Likewise. + (TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS): Remove. + * target.def (supports_function_versions): Remove. + * doc/tm.texi.in (SUPPORTS_FUNCTION_VERSIONS): Remove. + * doc/tm.texi: Regenerated. + 2013-01-30 Vladimir Makarov PR rtl-optimization/56144 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d4f989b..2fbc8f4 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2013-01-30 Jakub Jelinek + + PR c++/55742 + * c-common.c (handle_target_attribute): Revert 2012-12-26 change. + 2013-01-18 Jason Merrill PR target/54908 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index a50aae1..b3699dc 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -8759,12 +8759,8 @@ handle_target_attribute (tree *node, tree name, tree args, int flags, warning (OPT_Wattributes, "%qE attribute ignored", name); *no_add_attrs = true; } - /* Do not strip invalid target attributes for targets which support function - multiversioning as the target string is used to determine versioned - functions. */ else if (! targetm.target_option.valid_attribute_p (*node, name, args, - flags) - && ! targetm.target_option.supports_function_versions ()) + flags)) *no_add_attrs = true; return NULL_TREE; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 19a495d..acdfa6c 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -4225,7 +4225,10 @@ ix86_valid_target_attribute_inner_p (tree args, char *p_strings[], } else if (TREE_CODE (args) != STRING_CST) - gcc_unreachable (); + { + error ("attribute % argument not a string"); + return false; + } /* Handle multiple arguments separated by commas. */ next_optstr = ASTRDUP (TREE_STRING_POINTER (args)); @@ -4370,7 +4373,7 @@ ix86_valid_target_attribute_tree (tree args) /* Process each of the options on the chain. */ if (! ix86_valid_target_attribute_inner_p (args, option_strings, &enum_opts_set)) - return NULL_TREE; + return error_mark_node; /* If the changed options are different from the default, rerun ix86_option_override_internal, and then save the options away. @@ -4435,6 +4438,15 @@ ix86_valid_target_attribute_p (tree fndecl, { struct cl_target_option cur_target; bool ret = true; + + /* attribute((target("default"))) does nothing, beyond + affecting multi-versioning. */ + if (TREE_VALUE (args) + && TREE_CODE (TREE_VALUE (args)) == STRING_CST + && TREE_CHAIN (args) == NULL_TREE + && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0) + return true; + tree old_optimize = build_optimization_node (); tree new_target, new_optimize; tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); @@ -4451,10 +4463,10 @@ ix86_valid_target_attribute_p (tree fndecl, new_target = ix86_valid_target_attribute_tree (args); new_optimize = build_optimization_node (); - if (!new_target) + if (new_target == error_mark_node) ret = false; - else if (fndecl) + else if (fndecl && new_target) { DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target; @@ -28948,26 +28960,44 @@ attr_strcmp (const void *v1, const void *v2) return strcmp (c1, c2); } -/* STR is the argument to target attribute. This function tokenizes +/* ARGLIST is the argument to target attribute. This function tokenizes the comma separated arguments, sorts them and returns a string which is a unique identifier for the comma separated arguments. It also replaces non-identifier characters "=,-" with "_". */ static char * -sorted_attr_string (const char *str) +sorted_attr_string (tree arglist) { + tree arg; + size_t str_len_sum = 0; char **args = NULL; char *attr_str, *ret_str; char *attr = NULL; unsigned int argnum = 1; unsigned int i; - for (i = 0; i < strlen (str); i++) - if (str[i] == ',') - argnum++; + for (arg = arglist; arg; arg = TREE_CHAIN (arg)) + { + const char *str = TREE_STRING_POINTER (TREE_VALUE (arg)); + size_t len = strlen (str); + str_len_sum += len + 1; + if (arg != arglist) + argnum++; + for (i = 0; i < strlen (str); i++) + if (str[i] == ',') + argnum++; + } - attr_str = (char *)xmalloc (strlen (str) + 1); - strcpy (attr_str, str); + attr_str = XNEWVEC (char, str_len_sum); + str_len_sum = 0; + for (arg = arglist; arg; arg = TREE_CHAIN (arg)) + { + const char *str = TREE_STRING_POINTER (TREE_VALUE (arg)); + size_t len = strlen (str); + memcpy (attr_str + str_len_sum, str, len); + attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0'; + str_len_sum += len + 1; + } /* Replace "=,-" with "_". */ for (i = 0; i < strlen (attr_str); i++) @@ -28988,18 +29018,20 @@ sorted_attr_string (const char *str) attr = strtok (NULL, ","); } - qsort (args, argnum, sizeof (char*), attr_strcmp); + qsort (args, argnum, sizeof (char *), attr_strcmp); - ret_str = (char *)xmalloc (strlen (str) + 1); - strcpy (ret_str, args[0]); - for (i = 1; i < argnum; i++) + ret_str = XNEWVEC (char, str_len_sum); + str_len_sum = 0; + for (i = 0; i < argnum; i++) { - strcat (ret_str, "_"); - strcat (ret_str, args[i]); + size_t len = strlen (args[i]); + memcpy (ret_str + str_len_sum, args[i], len); + ret_str[str_len_sum + len] = i < argnum - 1 ? '_' : '\0'; + str_len_sum += len + 1; } - free (args); - free (attr_str); + XDELETEVEC (args); + XDELETEVEC (attr_str); return ret_str; } @@ -29011,8 +29043,8 @@ static tree ix86_mangle_function_version_assembler_name (tree decl, tree id) { tree version_attr; - const char *orig_name, *version_string, *attr_str; - char *assembler_name; + const char *orig_name, *version_string; + char *attr_str, *assembler_name; if (DECL_DECLARED_INLINE_P (decl) && lookup_attribute ("gnu_inline", @@ -29036,9 +29068,11 @@ ix86_mangle_function_version_assembler_name (tree decl, tree id) version_string = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (version_attr))); - attr_str = sorted_attr_string (version_string); - assembler_name = (char *) xmalloc (strlen (orig_name) - + strlen (attr_str) + 2); + if (strcmp (version_string, "default") == 0) + return id; + + attr_str = sorted_attr_string (TREE_VALUE (version_attr)); + assembler_name = XNEWVEC (char, strlen (orig_name) + strlen (attr_str) + 2); sprintf (assembler_name, "%s.%s", orig_name, attr_str); @@ -29046,7 +29080,10 @@ ix86_mangle_function_version_assembler_name (tree decl, tree id) if (DECL_ASSEMBLER_NAME_SET_P (decl)) SET_DECL_RTL (decl, NULL); - return get_identifier (assembler_name); + tree ret = get_identifier (assembler_name); + XDELETEVEC (attr_str); + XDELETEVEC (assembler_name); + return ret; } /* This function returns true if FN1 and FN2 are versions of the same function, @@ -29057,10 +29094,9 @@ static bool ix86_function_versions (tree fn1, tree fn2) { tree attr1, attr2; - const char *attr_str1, *attr_str2; char *target1, *target2; bool result; - + if (TREE_CODE (fn1) != FUNCTION_DECL || TREE_CODE (fn2) != FUNCTION_DECL) return false; @@ -29072,15 +29108,35 @@ ix86_function_versions (tree fn1, tree fn2) if (attr1 == NULL_TREE && attr2 == NULL_TREE) return false; - /* If one function does not have a target attribute, these are versions. */ + /* Diagnose missing target attribute if one of the decls is already + multi-versioned. */ if (attr1 == NULL_TREE || attr2 == NULL_TREE) - return true; - - attr_str1 = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr1))); - attr_str2 = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr2))); + { + if (DECL_FUNCTION_VERSIONED (fn1) || DECL_FUNCTION_VERSIONED (fn2)) + { + if (attr2 != NULL_TREE) + { + tree tem = fn1; + fn1 = fn2; + fn2 = tem; + attr1 = attr2; + } + error_at (DECL_SOURCE_LOCATION (fn2), + "missing % attribute for multi-versioned %D", + fn2); + error_at (DECL_SOURCE_LOCATION (fn1), + "previous declaration of %D", fn1); + /* Prevent diagnosing of the same error multiple times. */ + DECL_ATTRIBUTES (fn2) + = tree_cons (get_identifier ("target"), + copy_node (TREE_VALUE (attr1)), + DECL_ATTRIBUTES (fn2)); + } + return false; + } - target1 = sorted_attr_string (attr_str1); - target2 = sorted_attr_string (attr_str2); + target1 = sorted_attr_string (TREE_VALUE (attr1)); + target2 = sorted_attr_string (TREE_VALUE (attr2)); /* The sorted target strings must be different for fn1 and fn2 to be versions. */ @@ -29089,20 +29145,12 @@ ix86_function_versions (tree fn1, tree fn2) else result = true; - free (target1); - free (target2); + XDELETEVEC (target1); + XDELETEVEC (target2); return result; } -/* This target supports function multiversioning. */ - -static bool -ix86_supports_function_versions (void) -{ - return true; -} - static tree ix86_mangle_decl_assembler_name (tree decl, tree id) { @@ -29143,10 +29191,10 @@ make_name (tree decl, const char *suffix, bool make_unique) /* Use '.' to concatenate names as it is demangler friendly. */ if (make_unique) - snprintf (global_var_name, name_len, "%s.%s.%s", name, - unique_name, suffix); + snprintf (global_var_name, name_len, "%s.%s.%s", name, unique_name, + suffix); else - snprintf (global_var_name, name_len, "%s.%s", name, suffix); + snprintf (global_var_name, name_len, "%s.%s", name, suffix); return global_var_name; } @@ -29161,7 +29209,7 @@ static tree make_dispatcher_decl (const tree decl) { tree func_decl; - char *func_name, *resolver_name; + char *func_name; tree fn_type, func_type; bool is_uniq = false; @@ -29169,14 +29217,13 @@ make_dispatcher_decl (const tree decl) is_uniq = true; func_name = make_name (decl, "ifunc", is_uniq); - resolver_name = make_name (decl, "resolver", is_uniq); - gcc_assert (resolver_name); fn_type = TREE_TYPE (decl); func_type = build_function_type (TREE_TYPE (fn_type), TYPE_ARG_TYPES (fn_type)); func_decl = build_fn_decl (func_name, func_type); + XDELETEVEC (func_name); TREE_USED (func_decl) = 1; DECL_CONTEXT (func_decl) = NULL_TREE; DECL_INITIAL (func_decl) = error_mark_node; @@ -29198,9 +29245,14 @@ make_dispatcher_decl (const tree decl) static bool is_function_default_version (const tree decl) { - return (TREE_CODE (decl) == FUNCTION_DECL - && DECL_FUNCTION_VERSIONED (decl) - && lookup_attribute ("target", DECL_ATTRIBUTES (decl)) == NULL_TREE); + if (TREE_CODE (decl) != FUNCTION_DECL + || !DECL_FUNCTION_VERSIONED (decl)) + return false; + tree attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl)); + gcc_assert (attr); + attr = TREE_VALUE (TREE_VALUE (attr)); + return (TREE_CODE (attr) == STRING_CST + && strcmp (TREE_STRING_POINTER (attr), "default") == 0); } /* Make a dispatcher declaration for the multi-versioned function DECL. @@ -29394,6 +29446,7 @@ make_resolver_func (const tree default_decl, /* Create the alias for dispatch to resolver here. */ /*cgraph_create_function_alias (dispatch_decl, decl);*/ cgraph_same_body_alias (NULL, dispatch_decl, decl); + XDELETEVEC (resolver_name); return decl; } @@ -29455,7 +29508,7 @@ ix86_generate_version_dispatcher_body (void *node_p) } dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb); - + fn_ver_vec.release (); rebuild_cgraph_edges (); pop_cfun (); return resolver_decl; @@ -42443,10 +42496,6 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val) #undef TARGET_OPTION_FUNCTION_VERSIONS #define TARGET_OPTION_FUNCTION_VERSIONS ix86_function_versions -#undef TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS -#define TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS \ - ix86_supports_function_versions - #undef TARGET_CAN_INLINE_P #define TARGET_CAN_INLINE_P ix86_can_inline_p diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 9d6f6bc..ce2b44d 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -9907,11 +9907,6 @@ different target specific attributes, that is, they are compiled for different target machines. @end deftypefn -@deftypefn {Target Hook} bool TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS (void) -This target hook returns @code{true} if the target supports function -multiversioning. -@end deftypefn - @deftypefn {Target Hook} bool TARGET_CAN_INLINE_P (tree @var{caller}, tree @var{callee}) This target hook returns @code{false} if the @var{caller} function cannot inline @var{callee}, based on target specific information. By diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 3668882..d6e7ce7 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -9768,11 +9768,6 @@ different target specific attributes, that is, they are compiled for different target machines. @end deftypefn -@hook TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS -This target hook returns @code{true} if the target supports function -multiversioning. -@end deftypefn - @hook TARGET_CAN_INLINE_P This target hook returns @code{false} if the @var{caller} function cannot inline @var{callee}, based on target specific information. By diff --git a/gcc/target.def b/gcc/target.def index 8627923..63ba55e 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2831,14 +2831,6 @@ DEFHOOK bool, (tree decl1, tree decl2), hook_bool_tree_tree_false) -/* This function returns true if the target supports function - multiversioning. */ -DEFHOOK -(supports_function_versions, - "", - bool, (void), - hook_bool_void_false) - /* Function to determine if one function can inline another function. */ #undef HOOK_PREFIX #define HOOK_PREFIX "TARGET_" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 17c91ee..215ab43 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,24 @@ +2013-01-30 Jakub Jelinek + + PR c++/55742 + * g++.dg/mv1.C: Moved to... + * g++.dg/ext/mv1.C: ... here. Adjust test. + * g++.dg/mv2.C: Moved to... + * g++.dg/ext/mv2.C: ... here. Adjust test. + * g++.dg/mv3.C: Moved to... + * g++.dg/ext/mv3.C: ... here. + * g++.dg/mv4.C: Moved to... + * g++.dg/ext/mv4.C: ... here. + * g++.dg/mv5.C: Moved to... + * g++.dg/ext/mv5.C: ... here. Adjust test. + * g++.dg/mv6.C: Moved to... + * g++.dg/ext/mv6.C: ... here. Adjust test. + * g++.dg/ext/mv7.C: New test. + * g++.dg/ext/mv8.C: New test. + * g++.dg/ext/mv9.C: New test. + * g++.dg/ext/mv10.C: New test. + * g++.dg/ext/mv11.C: New test. + 2013-01-30 Vladimir Makarov PR rtl-optimization/56144 diff --git a/gcc/testsuite/g++.dg/mv1.C b/gcc/testsuite/g++.dg/ext/mv1.C similarity index 94% rename from gcc/testsuite/g++.dg/mv1.C rename to gcc/testsuite/g++.dg/ext/mv1.C index bad0c44..4eedbff 100644 --- a/gcc/testsuite/g++.dg/mv1.C +++ b/gcc/testsuite/g++.dg/ext/mv1.C @@ -6,7 +6,8 @@ #include /* Default version. */ -int foo (); +int foo (); // Extra declaration that is merged with the second one. +int foo () __attribute__ ((target("default"))); /* The other versions of foo. Mix up the ordering and check if the dispatching does it in the order of priority. */ /* Check combination of target attributes. */ @@ -65,7 +66,8 @@ int main () return 0; } -int foo () +int __attribute__ ((target("default"))) +foo () { return 0; } diff --git a/gcc/testsuite/g++.dg/ext/mv10.C b/gcc/testsuite/g++.dg/ext/mv10.C new file mode 100644 index 0000000..5dfe363 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv10.C @@ -0,0 +1,12 @@ +// { dg-do assemble { target i?86-*-* x86_64-*-* } } +// { dg-options "" } + +__attribute__((target ("popcnt"), used)) +void foo (void) +{ +} + +__attribute__((target ("popcnt","avx"), used)) +void foo (void) +{ +} diff --git a/gcc/testsuite/g++.dg/ext/mv11.C b/gcc/testsuite/g++.dg/ext/mv11.C new file mode 100644 index 0000000..1f5c576 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv11.C @@ -0,0 +1,23 @@ +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-options "-msse2" } + +int foo () __attribute__ ((target("default"))); +int foo () __attribute__ ((target("sse2"))); + +int +main () +{ + return foo (); +} + +int __attribute__ ((target("default"))) +foo () +{ + return 0; +} + +int __attribute__ ((target("sse2"))) +foo () +{ + return 0; +} diff --git a/gcc/testsuite/g++.dg/mv2.C b/gcc/testsuite/g++.dg/ext/mv2.C similarity index 96% rename from gcc/testsuite/g++.dg/mv2.C rename to gcc/testsuite/g++.dg/ext/mv2.C index baaa5da..869e99b 100644 --- a/gcc/testsuite/g++.dg/mv2.C +++ b/gcc/testsuite/g++.dg/ext/mv2.C @@ -7,7 +7,7 @@ #include /* Default version. */ -int foo (); +int foo () __attribute__ ((target ("default"))); /* The dispatch checks should be in the exact reverse order of the declarations below. */ int foo () __attribute__ ((target ("mmx"))); @@ -51,7 +51,7 @@ int main () return 0; } -int +int __attribute__ ((target("default"))) foo () { return 0; diff --git a/gcc/testsuite/g++.dg/mv3.C b/gcc/testsuite/g++.dg/ext/mv3.C similarity index 100% rename from gcc/testsuite/g++.dg/mv3.C rename to gcc/testsuite/g++.dg/ext/mv3.C diff --git a/gcc/testsuite/g++.dg/mv4.C b/gcc/testsuite/g++.dg/ext/mv4.C similarity index 100% rename from gcc/testsuite/g++.dg/mv4.C rename to gcc/testsuite/g++.dg/ext/mv4.C diff --git a/gcc/testsuite/g++.dg/mv5.C b/gcc/testsuite/g++.dg/ext/mv5.C similarity index 88% rename from gcc/testsuite/g++.dg/mv5.C rename to gcc/testsuite/g++.dg/ext/mv5.C index 93daab6..fd62eee 100644 --- a/gcc/testsuite/g++.dg/mv5.C +++ b/gcc/testsuite/g++.dg/ext/mv5.C @@ -7,7 +7,7 @@ /* Default version. */ -inline int +inline int __attribute__ ((target ("default"))) foo () { return 0; diff --git a/gcc/testsuite/g++.dg/mv6.C b/gcc/testsuite/g++.dg/ext/mv6.C similarity index 92% rename from gcc/testsuite/g++.dg/mv6.C rename to gcc/testsuite/g++.dg/ext/mv6.C index c0323f6..2273065 100644 --- a/gcc/testsuite/g++.dg/mv6.C +++ b/gcc/testsuite/g++.dg/ext/mv6.C @@ -8,6 +8,7 @@ class Foo { public: /* Default version of foo. */ + __attribute__ ((target("default"))) int foo () { return 0; diff --git a/gcc/testsuite/g++.dg/ext/mv7.C b/gcc/testsuite/g++.dg/ext/mv7.C new file mode 100644 index 0000000..d378402 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv7.C @@ -0,0 +1,12 @@ +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-options "" } + +__attribute__((target ("default"))) +void foo (void) // { dg-error "previously defined here" } +{ +} + +__attribute__((target (128))) +void foo (void) // { dg-error "(not a string|redefinition)" } +{ +} diff --git a/gcc/testsuite/g++.dg/ext/mv8.C b/gcc/testsuite/g++.dg/ext/mv8.C new file mode 100644 index 0000000..2e98dd7 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv8.C @@ -0,0 +1,7 @@ +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-options "" } + +__attribute__((target (11,12))) +void foo (void) // { dg-error "not a string" } +{ +} diff --git a/gcc/testsuite/g++.dg/ext/mv9.C b/gcc/testsuite/g++.dg/ext/mv9.C new file mode 100644 index 0000000..53ee995 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/mv9.C @@ -0,0 +1,9 @@ +// { dg-do compile { target i?86-*-* x86_64-*-* } } +// { dg-options "" } + +void foo (); +void foo () __attribute__((target ("sse4"))); +void foo () __attribute__((target ("default"))); // { dg-error "previous declaration" } +void foo () // { dg-error "attribute for multi-versioned" } +{ +} -- 2.7.4