aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2be7d2f..eff5281 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -230,6 +230,7 @@ struct GTY((for_user)) named_label_entry {
bool in_try_scope;
bool in_catch_scope;
bool in_omp_scope;
+ bool in_transaction_scope;
};
#define named_labels cp_function_chain->x_named_labels
@@ -498,6 +499,9 @@ poplevel_named_label_1 (named_label_entry **slot, cp_binding_level *bl)
case sk_omp:
ent->in_omp_scope = true;
break;
+ case sk_transaction:
+ ent->in_transaction_scope = true;
+ break;
default:
break;
}
@@ -2049,6 +2053,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
}
}
+ /* An explicit specialization of a function template or of a member
+ function of a class template can be declared transaction_safe
+ independently of whether the corresponding template entity is declared
+ transaction_safe. */
+ if (flag_tm && TREE_CODE (newdecl) == FUNCTION_DECL
+ && DECL_TEMPLATE_INSTANTIATION (olddecl)
+ && DECL_TEMPLATE_SPECIALIZATION (newdecl)
+ && tx_safe_fn_type_p (newtype)
+ && !tx_safe_fn_type_p (TREE_TYPE (newdecl)))
+ newtype = tx_unsafe_fn_variant (newtype);
+
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -2975,7 +2990,7 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
{
cp_binding_level *b;
bool identified = false, complained = false;
- bool saw_eh = false, saw_omp = false;
+ bool saw_eh = false, saw_omp = false, saw_tm = false;
if (exited_omp)
{
@@ -3043,6 +3058,18 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
inform (input_location, " enters OpenMP structured block");
saw_omp = true;
}
+ if (b->kind == sk_transaction && !saw_tm)
+ {
+ if (!identified)
+ {
+ complained = identify_goto (decl, locus);
+ identified = true;
+ }
+ if (complained)
+ inform (input_location,
+ " enters synchronized or atomic statement");
+ saw_tm = true;
+ }
}
return !identified;
@@ -3109,7 +3136,7 @@ check_goto (tree decl)
return;
}
- if (ent->in_try_scope || ent->in_catch_scope
+ if (ent->in_try_scope || ent->in_catch_scope || ent->in_transaction_scope
|| ent->in_omp_scope || !vec_safe_is_empty (ent->bad_decls))
{
complained = permerror (DECL_SOURCE_LOCATION (decl),
@@ -3148,6 +3175,8 @@ check_goto (tree decl)
inform (input_location, " enters try block");
else if (ent->in_catch_scope && !saw_catch)
inform (input_location, " enters catch block");
+ else if (ent->in_transaction_scope)
+ inform (input_location, " enters synchronized or atomic statement");
}
if (ent->in_omp_scope)
@@ -9976,6 +10005,8 @@ grokdeclarator (const cp_declarator *declarator,
virt_specifiers = declarator->u.function.virt_specifiers;
/* And ref-qualifier, too */
rqual = declarator->u.function.ref_qualifier;
+ /* And tx-qualifier. */
+ tree tx_qual = declarator->u.function.tx_qualifier;
/* Pick up the exception specifications. */
raises = declarator->u.function.exception_specification;
/* If the exception-specification is ill-formed, let's pretend
@@ -10153,13 +10184,24 @@ grokdeclarator (const cp_declarator *declarator,
}
type = build_function_type (type, arg_types);
- if (declarator->std_attributes)
+
+ tree attrs = declarator->std_attributes;
+ if (tx_qual)
+ {
+ tree att = build_tree_list (tx_qual, NULL_TREE);
+ /* transaction_safe applies to the type, but
+ transaction_safe_dynamic applies to the function. */
+ if (is_attribute_p ("transaction_safe", tx_qual))
+ attrs = chainon (attrs, att);
+ else
+ returned_attrs = chainon (returned_attrs, att);
+ }
+ if (attrs)
/* [dcl.fct]/2:
The optional attribute-specifier-seq appertains to
the function type. */
- decl_attributes (&type, declarator->std_attributes,
- 0);
+ decl_attributes (&type, attrs, 0);
}
break;