summaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c152
1 files changed, 129 insertions, 23 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d4855d5bc35..7eeb27ddd1c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -772,28 +772,29 @@ check_specialization_namespace (tree tmpl)
/* [tmpl.expl.spec]
- An explicit specialization shall be declared in the namespace of
- which the template is a member, or, for member templates, in the
- namespace of which the enclosing class or enclosing class
- template is a member. An explicit specialization of a member
- function, member class or static data member of a class template
- shall be declared in the namespace of which the class template is
- a member. */
+ An explicit specialization shall be declared in a namespace enclosing the
+ specialized template. An explicit specialization whose declarator-id is
+ not qualified shall be declared in the nearest enclosing namespace of the
+ template, or, if the namespace is inline (7.3.1), any namespace from its
+ enclosing namespace set. */
if (current_scope() != DECL_CONTEXT (tmpl)
&& !at_namespace_scope_p ())
{
error ("specialization of %qD must appear at namespace scope", tmpl);
return false;
}
- if (is_associated_namespace (current_namespace, tpl_ns))
- /* Same or super-using namespace. */
+
+ if (cxx_dialect < cxx11
+ ? is_associated_namespace (current_namespace, tpl_ns)
+ : is_ancestor (current_namespace, tpl_ns))
+ /* Same or enclosing namespace. */
return true;
else
{
permerror (input_location,
"specialization of %qD in different namespace", tmpl);
- permerror (DECL_SOURCE_LOCATION (tmpl),
- " from definition of %q#D", tmpl);
+ inform (DECL_SOURCE_LOCATION (tmpl),
+ " from definition of %q#D", tmpl);
return false;
}
}
@@ -2586,6 +2587,36 @@ check_template_variable (tree decl)
}
}
+/* An explicit specialization whose declarator-id or class-head-name is not
+ qualified shall be declared in the nearest enclosing namespace of the
+ template, or, if the namespace is inline (7.3.1), any namespace from its
+ enclosing namespace set.
+
+ If the name declared in the explicit instantiation is an unqualified name,
+ the explicit instantiation shall appear in the namespace where its template
+ is declared or, if that namespace is inline (7.3.1), any namespace from its
+ enclosing namespace set. */
+
+void
+check_unqualified_spec_or_inst (tree t, location_t loc)
+{
+ tree tmpl = most_general_template (t);
+ if (DECL_NAMESPACE_SCOPE_P (tmpl)
+ && !is_associated_namespace (current_namespace,
+ CP_DECL_CONTEXT (tmpl)))
+ {
+ if (processing_specialization)
+ permerror (loc, "explicit specialization of %qD outside its "
+ "namespace must use a nested-name-specifier", tmpl);
+ else if (processing_explicit_instantiation
+ && cxx_dialect >= cxx11)
+ /* This was allowed in C++98, so only pedwarn. */
+ pedwarn (loc, OPT_Wpedantic, "explicit instantiation of %qD "
+ "outside its namespace must use a nested-name-"
+ "specifier", tmpl);
+ }
+}
+
/* Check to see if the function just declared, as indicated in
DECLARATOR, and in DECL, is a specialization of a function
template. We may also discover that the declaration is an explicit
@@ -2949,15 +2980,8 @@ check_explicit_specialization (tree declarator,
return error_mark_node;
else
{
- if (!ctype && !was_template_id
- && (specialization || member_specialization
- || explicit_instantiation)
- && !is_associated_namespace (CP_DECL_CONTEXT (decl),
- CP_DECL_CONTEXT (tmpl)))
- error ("%qD is not declared in %qD",
- tmpl, current_namespace);
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_HIDDEN_FRIEND_P (tmpl))
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_HIDDEN_FRIEND_P (tmpl))
{
if (pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"friend declaration %qD is not visible to "
@@ -2965,6 +2989,9 @@ check_explicit_specialization (tree declarator,
inform (DECL_SOURCE_LOCATION (tmpl),
"friend declaration here");
}
+ else if (!ctype && !is_friend
+ && CP_DECL_CONTEXT (decl) == current_namespace)
+ check_unqualified_spec_or_inst (tmpl, DECL_SOURCE_LOCATION (decl));
tree gen_tmpl = most_general_template (tmpl);
@@ -15284,6 +15311,55 @@ tsubst_find_omp_teams (tree *tp, int *walk_subtrees, void *)
return NULL_TREE;
}
+/* Helper function for tsubst_expr. For decomposition declaration
+ artificial base DECL, which is tsubsted PATTERN_DECL, tsubst
+ also the corresponding decls representing the identifiers
+ of the decomposition declaration. Return DECL if successful
+ or error_mark_node otherwise, set *FIRST to the first decl
+ in the list chained through DECL_CHAIN and *CNT to the number
+ of such decls. */
+
+static tree
+tsubst_decomp_names (tree decl, tree pattern_decl, tree args,
+ tsubst_flags_t complain, tree in_decl, tree *first,
+ unsigned int *cnt)
+{
+ tree decl2, decl3, prev = decl;
+ *cnt = 0;
+ gcc_assert (DECL_NAME (decl) == NULL_TREE);
+ for (decl2 = DECL_CHAIN (pattern_decl);
+ decl2
+ && VAR_P (decl2)
+ && DECL_DECOMPOSITION_P (decl2)
+ && DECL_NAME (decl2);
+ decl2 = DECL_CHAIN (decl2))
+ {
+ (*cnt)++;
+ gcc_assert (DECL_HAS_VALUE_EXPR_P (decl2));
+ tree v = DECL_VALUE_EXPR (decl2);
+ DECL_HAS_VALUE_EXPR_P (decl2) = 0;
+ SET_DECL_VALUE_EXPR (decl2, NULL_TREE);
+ decl3 = tsubst (decl2, args, complain, in_decl);
+ SET_DECL_VALUE_EXPR (decl2, v);
+ DECL_HAS_VALUE_EXPR_P (decl2) = 1;
+ if (VAR_P (decl3))
+ DECL_TEMPLATE_INSTANTIATED (decl3) = 1;
+ maybe_push_decl (decl3);
+ if (error_operand_p (decl3))
+ decl = error_mark_node;
+ else if (decl != error_mark_node
+ && DECL_CHAIN (decl3) != prev)
+ {
+ gcc_assert (errorcount);
+ decl = error_mark_node;
+ }
+ else
+ prev = decl3;
+ }
+ *first = prev;
+ return decl;
+}
+
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
@@ -15427,6 +15503,16 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
(pattern_decl));
cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+ if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+ {
+ unsigned int cnt;
+ tree first;
+ decl = tsubst_decomp_names (decl, pattern_decl, args,
+ complain, in_decl, &first,
+ &cnt);
+ if (decl != error_mark_node)
+ cp_finish_decomp (decl, first, cnt);
+ }
}
}
}
@@ -15454,7 +15540,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
decl = tsubst (decl, args, complain, in_decl);
maybe_push_decl (decl);
expr = RECUR (RANGE_FOR_EXPR (t));
- stmt = cp_convert_range_for (stmt, decl, expr, RANGE_FOR_IVDEP (t));
+ if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl))
+ {
+ unsigned int cnt;
+ tree first;
+ decl = tsubst_decomp_names (decl, RANGE_FOR_DECL (t), args,
+ complain, in_decl, &first, &cnt);
+ stmt = cp_convert_range_for (stmt, decl, expr, first, cnt,
+ RANGE_FOR_IVDEP (t));
+ }
+ else
+ stmt = cp_convert_range_for (stmt, decl, expr, NULL_TREE, 0,
+ RANGE_FOR_IVDEP (t));
RECUR (RANGE_FOR_BODY (t));
finish_for_stmt (stmt);
}
@@ -24773,7 +24870,15 @@ do_auto_deduction (tree type, tree init, tree auto_node,
init = resolve_nondeduced_context (init, complain);
- if (AUTO_IS_DECLTYPE (auto_node))
+ if (context == adc_decomp_type
+ && auto_node == type
+ && init != error_mark_node
+ && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
+ /* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers
+ and initializer has array type, deduce cv-qualified array type. */
+ return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type),
+ complain);
+ else if (AUTO_IS_DECLTYPE (auto_node))
{
bool id = (DECL_P (init)
|| ((TREE_CODE (init) == COMPONENT_REF
@@ -24858,6 +24963,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
error("placeholder constraints not satisfied");
break;
case adc_variable_type:
+ case adc_decomp_type:
error ("deduced initializer does not satisfy "
"placeholder constraints");
break;
@@ -24866,7 +24972,7 @@ do_auto_deduction (tree type, tree init, tree auto_node,
"placeholder constraints");
break;
case adc_requirement:
- error ("deduced expression type does not saatisy "
+ error ("deduced expression type does not satisfy "
"placeholder constraints");
break;
}