aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/constraint.cc3
-rw-r--r--gcc/cp/cp-trait.def1
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/parser.cc41
-rw-r--r--gcc/cp/semantics.cc4
-rw-r--r--gcc/cp/tree.cc36
6 files changed, 78 insertions, 8 deletions
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 309ebc8..925dc67 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3170,6 +3170,9 @@ diagnose_trait_expr (location_t loc, tree expr, tree args)
case CPTK_IS_FUNCTION:
inform (loc, "%qT is not a function", t1);
break;
+ case CPTK_IS_IMPLICIT_LIFETIME:
+ inform (decl_loc, "%qT is not an implicit-lifetime type", t1);
+ break;
case CPTK_IS_INVOCABLE:
{
if (!TREE_VEC_LENGTH (t2))
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 5e4493a..c820184 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -76,6 +76,7 @@ DEFTRAIT_EXPR (IS_EMPTY, "__is_empty", 1)
DEFTRAIT_EXPR (IS_ENUM, "__is_enum", 1)
DEFTRAIT_EXPR (IS_FINAL, "__is_final", 1)
DEFTRAIT_EXPR (IS_FUNCTION, "__is_function", 1)
+DEFTRAIT_EXPR (IS_IMPLICIT_LIFETIME, "__builtin_is_implicit_lifetime", 1)
DEFTRAIT_EXPR (IS_INVOCABLE, "__is_invocable", -1)
DEFTRAIT_EXPR (IS_LAYOUT_COMPATIBLE, "__is_layout_compatible", 2)
DEFTRAIT_EXPR (IS_LITERAL_TYPE, "__is_literal_type", 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fcba9f5..8c211ab 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8376,6 +8376,7 @@ extern bool std_layout_type_p (const_tree);
extern bool trivial_type_p (const_tree);
extern bool trivially_relocatable_type_p (tree);
extern bool replaceable_type_p (tree);
+extern bool implicit_lifetime_type_p (tree);
extern bool trivially_copyable_p (const_tree);
extern bool type_has_unique_obj_representations (const_tree);
extern bool scalarish_type_p (const_tree);
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9280632..0917a16 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -51233,6 +51233,7 @@ cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok,
directive[1],
directive[2]);
if (dir
+ && dir->id != PRAGMA_OMP_END
&& (dir->kind == C_OMP_DIR_DECLARATIVE
|| dir->kind == C_OMP_DIR_INFORMATIONAL
|| dir->kind == C_OMP_DIR_META))
@@ -51241,9 +51242,9 @@ cp_parser_omp_assumption_clauses (cp_parser *parser, cp_token *pragma_tok,
"informational, and meta directives "
"not permitted", p);
else if (dir == NULL
- || dir->id == PRAGMA_OMP_END
- || (!dir->second && directive[1])
- || (!dir->third && directive[2]))
+ || dir->id == PRAGMA_OMP_END
+ || (!dir->second && directive[1])
+ || (!dir->third && directive[2]))
error_at (dloc, "unknown OpenMP directive name in "
"%qs clause argument", p);
else
@@ -52739,6 +52740,18 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok,
}
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ /* If only one selector matches and it evaluates to 'omp nothing', no need to
+ proceed. */
+ if (ctxs.length () == 1)
+ {
+ tree ctx = ctxs[0];
+ if (ctx == NULL_TREE
+ || (omp_context_selector_matches (ctx, NULL_TREE, false) == 1
+ && cp_parser_pragma_kind (&directive_tokens[0])
+ == PRAGMA_OMP_NOTHING))
+ return;
+ }
+
if (!default_seen)
{
/* Add a default clause that evaluates to 'omp nothing'. */
@@ -53851,6 +53864,14 @@ cp_parser_omp_error (cp_parser *parser, cp_token *pragma_tok,
"may only be used in compound statements");
return true;
}
+ if (parser->omp_for_parse_state
+ && parser->omp_for_parse_state->in_intervening_code)
+ {
+ error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
+ "may not be used in intervening code");
+ parser->omp_for_parse_state->fail = true;
+ return true;
+ }
tree fndecl
= builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR
: BUILT_IN_GOMP_WARNING);
@@ -54768,11 +54789,15 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
id = cp_parser_pragma_kind (pragma_tok);
if (parser->omp_for_parse_state
&& parser->omp_for_parse_state->in_intervening_code
- && id >= PRAGMA_OMP__START_
- && id <= PRAGMA_OMP__LAST_)
- {
- error_at (pragma_tok->location,
- "intervening code must not contain OpenMP directives");
+ && id >= PRAGMA_OMP__START_ && id <= PRAGMA_OMP__LAST_
+ /* Allow a safe subset of non-executable directives. See classification in
+ array c_omp_directives. */
+ && id != PRAGMA_OMP_METADIRECTIVE && id != PRAGMA_OMP_NOTHING
+ && id != PRAGMA_OMP_ASSUME && id != PRAGMA_OMP_ERROR)
+ {
+ error_at (
+ pragma_tok->location,
+ "intervening code must not contain executable OpenMP directives");
parser->omp_for_parse_state->fail = true;
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
return false;
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index c818b73..ad12155 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -13595,6 +13595,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_FUNCTION:
return type_code1 == FUNCTION_TYPE;
+ case CPTK_IS_IMPLICIT_LIFETIME:
+ return implicit_lifetime_type_p (type1);
+
case CPTK_IS_INVOCABLE:
return !error_operand_p (build_invoke (type1, type2, tf_none));
@@ -13914,6 +13917,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
type to know whether an array is an aggregate, so use kind=4 here. */
case CPTK_IS_AGGREGATE:
case CPTK_IS_FINAL:
+ case CPTK_IS_IMPLICIT_LIFETIME:
if (!check_trait_type (type1, /* kind = */ 4))
return error_mark_node;
break;
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 814465c..3edb74a 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5097,6 +5097,42 @@ replaceable_type_p (tree t)
return true;
}
+/* Returns 1 iff type T is an implicit-lifetime type, as defined in
+ [basic.types.general] and [class.prop]. */
+
+bool
+implicit_lifetime_type_p (tree t)
+{
+ if (SCALAR_TYPE_P (t)
+ || (TREE_CODE (t) == ARRAY_TYPE
+ && !(TYPE_SIZE (t) && integer_zerop (TYPE_SIZE (t))))
+ /* GNU extension. */
+ || TREE_CODE (t) == VECTOR_TYPE)
+ return true;
+ if (!CLASS_TYPE_P (t))
+ return false;
+ t = TYPE_MAIN_VARIANT (t);
+ if (CP_AGGREGATE_TYPE_P (t)
+ && (!CLASSTYPE_DESTRUCTOR (t)
+ || !user_provided_p (CLASSTYPE_DESTRUCTOR (t))))
+ return true;
+ if (is_trivially_xible (BIT_NOT_EXPR, t, NULL_TREE))
+ {
+ if (is_trivially_xible (INIT_EXPR, t, make_tree_vec (0)))
+ return true;
+ tree arg = make_tree_vec (1);
+ tree ct
+ = cp_build_qualified_type (t, (cp_type_quals (t) | TYPE_QUAL_CONST));
+ TREE_VEC_ELT (arg, 0) = cp_build_reference_type (ct, /*rval=*/false);
+ if (is_trivially_xible (INIT_EXPR, t, arg))
+ return true;
+ TREE_VEC_ELT (arg, 0) = t;
+ if (is_trivially_xible (INIT_EXPR, t, arg))
+ return true;
+ }
+ return false;
+}
+
/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
bool