Commit 5e7c7761 by Jakub Jelinek Committed by Jakub Jelinek

re PR middle-end/78419 (ICE with target_clone on invalid target)

	PR middle-end/78419
	* multiple_target.c (get_attr_len): Start with argnum and increment
	argnum on every arg.  Use strchr in a loop instead of counting commas
	manually.
	(get_attr_str): Increment argnum for every comma in the string.
	(separate_attrs): Use for instead of while loop, simplify.
	(expand_target_clones): Rename defenition argument to definition.
	Free attrs and attr_str even when diagnosing errors.  Temporarily
	change input_location around targetm.target_option.valid_attribute_p
	calls.  Don't emit warning or errors if that function fails.

	* gcc.target/i386/pr78419.c: New test.

From-SVN: r242608
parent 6c554a2a
2016-11-18 Jakub Jelinek <jakub@redhat.com> 2016-11-18 Jakub Jelinek <jakub@redhat.com>
PR middle-end/78419
* multiple_target.c (get_attr_len): Start with argnum and increment
argnum on every arg. Use strchr in a loop instead of counting commas
manually.
(get_attr_str): Increment argnum for every comma in the string.
(separate_attrs): Use for instead of while loop, simplify.
(expand_target_clones): Rename defenition argument to definition.
Free attrs and attr_str even when diagnosing errors. Temporarily
change input_location around targetm.target_option.valid_attribute_p
calls. Don't emit warning or errors if that function fails.
* dwarf2out.c (size_of_discr_list): Fix typo in function comment. * dwarf2out.c (size_of_discr_list): Fix typo in function comment.
PR debug/78191 PR debug/78191
...@@ -101,22 +101,18 @@ get_attr_len (tree arglist) ...@@ -101,22 +101,18 @@ get_attr_len (tree arglist)
{ {
tree arg; tree arg;
int str_len_sum = 0; int str_len_sum = 0;
int argnum = 1; int argnum = 0;
for (arg = arglist; arg; arg = TREE_CHAIN (arg)) for (arg = arglist; arg; arg = TREE_CHAIN (arg))
{ {
unsigned int i;
const char *str = TREE_STRING_POINTER (TREE_VALUE (arg)); const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
int len = strlen (str); size_t len = strlen (str);
str_len_sum += len + 1; str_len_sum += len + 1;
if (arg != arglist) for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ','))
argnum++; argnum++;
for (i = 0; i < strlen (str); i++) argnum++;
if (str[i] == ',')
argnum++;
} }
if (argnum == 1) if (argnum <= 1)
return -1; return -1;
return str_len_sum; return str_len_sum;
} }
...@@ -134,8 +130,9 @@ get_attr_str (tree arglist, char *attr_str) ...@@ -134,8 +130,9 @@ get_attr_str (tree arglist, char *attr_str)
for (arg = arglist; arg; arg = TREE_CHAIN (arg)) for (arg = arglist; arg; arg = TREE_CHAIN (arg))
{ {
const char *str = TREE_STRING_POINTER (TREE_VALUE (arg)); const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
size_t len = strlen (str); size_t len = strlen (str);
for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ','))
argnum++;
memcpy (attr_str + str_len_sum, str, len); memcpy (attr_str + str_len_sum, str, len);
attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0'; attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
str_len_sum += len + 1; str_len_sum += len + 1;
...@@ -152,19 +149,16 @@ separate_attrs (char *attr_str, char **attrs) ...@@ -152,19 +149,16 @@ separate_attrs (char *attr_str, char **attrs)
{ {
int i = 0; int i = 0;
bool has_default = false; bool has_default = false;
char *attr = strtok (attr_str, ",");
while (attr != NULL) for (char *attr = strtok (attr_str, ",");
attr != NULL; attr = strtok (NULL, ","))
{ {
if (strcmp (attr, "default") == 0) if (strcmp (attr, "default") == 0)
{ {
has_default = true; has_default = true;
attr = strtok (NULL, ",");
continue; continue;
} }
attrs[i] = attr; attrs[i++] = attr;
attr = strtok (NULL, ",");
i++;
} }
if (!has_default) if (!has_default)
return -1; return -1;
...@@ -235,7 +229,7 @@ create_target_clone (cgraph_node *node, bool definition, char *name) ...@@ -235,7 +229,7 @@ create_target_clone (cgraph_node *node, bool definition, char *name)
create the appropriate clone for each valid target attribute. */ create the appropriate clone for each valid target attribute. */
static bool static bool
expand_target_clones (struct cgraph_node *node, bool defenition) expand_target_clones (struct cgraph_node *node, bool definition)
{ {
int i; int i;
/* Parsing target attributes separated by comma. */ /* Parsing target attributes separated by comma. */
...@@ -266,6 +260,8 @@ expand_target_clones (struct cgraph_node *node, bool defenition) ...@@ -266,6 +260,8 @@ expand_target_clones (struct cgraph_node *node, bool defenition)
{ {
error_at (DECL_SOURCE_LOCATION (node->decl), error_at (DECL_SOURCE_LOCATION (node->decl),
"default target was not set"); "default target was not set");
XDELETEVEC (attrs);
XDELETEVEC (attr_str);
return false; return false;
} }
...@@ -286,22 +282,24 @@ expand_target_clones (struct cgraph_node *node, bool defenition) ...@@ -286,22 +282,24 @@ expand_target_clones (struct cgraph_node *node, bool defenition)
create_new_asm_name (attr, suffix); create_new_asm_name (attr, suffix);
/* Create new target clone. */ /* Create new target clone. */
cgraph_node *new_node = create_target_clone (node, defenition, suffix); cgraph_node *new_node = create_target_clone (node, definition, suffix);
XDELETEVEC (suffix); XDELETEVEC (suffix);
/* Set new attribute for the clone. */ /* Set new attribute for the clone. */
tree attributes = make_attribute ("target", attr, tree attributes = make_attribute ("target", attr,
DECL_ATTRIBUTES (new_node->decl)); DECL_ATTRIBUTES (new_node->decl));
DECL_ATTRIBUTES (new_node->decl) = attributes; DECL_ATTRIBUTES (new_node->decl) = attributes;
location_t saved_loc = input_location;
input_location = DECL_SOURCE_LOCATION (node->decl);
if (!targetm.target_option.valid_attribute_p (new_node->decl, NULL, if (!targetm.target_option.valid_attribute_p (new_node->decl, NULL,
TREE_VALUE (attributes), 0)) TREE_VALUE (attributes),
0))
{ {
warning_at (DECL_SOURCE_LOCATION (node->decl), 0, input_location = saved_loc;
"attribute(target_clones(\"%s\")) is not "
"valid for current target", attr);
continue; continue;
} }
input_location = saved_loc;
decl2_v = new_node->function_version (); decl2_v = new_node->function_version ();
if (decl2_v != NULL) if (decl2_v != NULL)
continue; continue;
...@@ -320,22 +318,20 @@ expand_target_clones (struct cgraph_node *node, bool defenition) ...@@ -320,22 +318,20 @@ expand_target_clones (struct cgraph_node *node, bool defenition)
DECL_FUNCTION_VERSIONED (new_node->decl) = 1; DECL_FUNCTION_VERSIONED (new_node->decl) = 1;
} }
/* Setting new attribute to initial function. */
tree attributes = make_attribute ("target", "default",
DECL_ATTRIBUTES (node->decl));
DECL_ATTRIBUTES (node->decl) = attributes;
if (!targetm.target_option.valid_attribute_p (node->decl, NULL,
TREE_VALUE (attributes), 0))
{
error_at (DECL_SOURCE_LOCATION (node->decl),
"attribute(target_clones(\"default\")) is not "
"valid for current target");
return false;
}
XDELETEVEC (attrs); XDELETEVEC (attrs);
XDELETEVEC (attr_str); XDELETEVEC (attr_str);
return true;
/* Setting new attribute to initial function. */
tree attributes = make_attribute ("target", "default",
DECL_ATTRIBUTES (node->decl));
DECL_ATTRIBUTES (node->decl) = attributes;
location_t saved_loc = input_location;
input_location = DECL_SOURCE_LOCATION (node->decl);
bool ret
= targetm.target_option.valid_attribute_p (node->decl, NULL,
TREE_VALUE (attributes), 0);
input_location = saved_loc;
return ret;
} }
static bool target_clone_pass; static bool target_clone_pass;
......
2016-11-18 Jakub Jelinek <jakub@redhat.com> 2016-11-18 Jakub Jelinek <jakub@redhat.com>
PR middle-end/78419
* gcc.target/i386/pr78419.c: New test.
PR c++/77285 PR c++/77285
* g++.dg/tls/pr77285-1.C: New test. * g++.dg/tls/pr77285-1.C: New test.
* g++.dg/tls/pr77285-2.C: New test. * g++.dg/tls/pr77285-2.C: New test.
......
/* PR middle-end/78419 */
/* { dg-do compile } */
static double bar (double *__restrict, double *__restrict, int)
__attribute__ ((target_clones("avx,foo,avx2,avx512f,default")));
double
foo (double *__restrict a, double *__restrict b, int n)
{
return bar (a,b,n);
}
double
bar (double *__restrict a, double *__restrict b, int n) /* { dg-error "attribute\[^\n\r]*foo\[^\n\r]* is unknown" } */
{
double s;
int i;
s = 0.0;
for (i=0; i<n; i++)
s += a[i] + b[i];
return s;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment