#include "system.h"
#include "coretypes.h"
#include "tm.h"
-#include "input.h"
#include "alias.h"
#include "symtab.h"
#include "tree.h"
tree spec;
};
-struct spec_hasher : ggc_hasher<spec_entry *>
+struct spec_hasher : ggc_ptr_hash<spec_entry>
{
static hashval_t hash (spec_entry *);
static bool equal (spec_entry *, spec_entry *);
&& !DECL_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl)));
}
+/* Make sure ARGS doesn't use any inappropriate typedefs; we should have
+ gone through coerce_template_parms by now. */
+
+static void
+check_unstripped_args (tree args ATTRIBUTE_UNUSED)
+{
+#ifdef ENABLE_CHECKING
+ ++processing_template_decl;
+ if (!any_dependent_template_arguments_p (args))
+ {
+ tree inner = INNERMOST_TEMPLATE_ARGS (args);
+ for (int i = 0; i < TREE_VEC_LENGTH (inner); ++i)
+ {
+ tree arg = TREE_VEC_ELT (inner, i);
+ if (TREE_CODE (arg) == TEMPLATE_DECL)
+ /* OK */;
+ else if (TYPE_P (arg))
+ gcc_assert (strip_typedefs (arg, NULL) == arg);
+ else if (strip_typedefs (TREE_TYPE (arg), NULL) != TREE_TYPE (arg))
+ /* Allow typedefs on the type of a non-type argument, since a
+ parameter can have them. */;
+ else
+ gcc_assert (strip_typedefs_expr (arg, NULL) == arg);
+ }
+ }
+ --processing_template_decl;
+#endif
+}
+
/* Retrieve the specialization (in the sense of [temp.spec] - a
specialization is either an instantiation or an explicit
specialization) of TMPL for the given template ARGS. If there is
? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
: template_class_depth (DECL_CONTEXT (tmpl))));
-#ifdef ENABLE_CHECKING
- /* We should have gone through coerce_template_parms by now. */
- ++processing_template_decl;
- if (!any_dependent_template_arguments_p (args))
- gcc_assert (strip_typedefs_expr (args, NULL) == args);
- --processing_template_decl;
-#endif
+ check_unstripped_args (args);
if (optimize_specialization_lookup_p (tmpl))
{
switch (tsk)
{
case tsk_none:
- if (processing_specialization && TREE_CODE (decl) != VAR_DECL)
+ if (processing_specialization && !VAR_P (decl))
{
specialization = 1;
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
/* A specialization is not necessarily COMDAT. */
DECL_COMDAT (decl) = (TREE_PUBLIC (decl)
&& DECL_DECLARED_INLINE_P (decl));
- else if (TREE_CODE (decl) == VAR_DECL)
+ else if (VAR_P (decl))
DECL_COMDAT (decl) = false;
/* Register this specialization so that we can find it
is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
- || (TREE_CODE (decl) == VAR_DECL
+ || (VAR_P (decl)
&& DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_SPECIALIZATION (decl)
&& TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
if (TREE_CODE (decl) == TYPE_DECL
- && ANON_AGGRNAME_P (DECL_NAME (decl)))
+ && anon_aggrname_p (DECL_NAME (decl)))
{
error ("template class without a name");
return error_mark_node;
it now. */
push_deferring_access_checks (dk_no_deferred);
+ int saved_unevaluated_operand = cp_unevaluated_operand;
+ int saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+
fn_context = decl_function_context (TYPE_MAIN_DECL (type));
/* Also avoid push_to_top_level for a lambda in an NSDMI. */
if (!fn_context && LAMBDA_TYPE_P (type) && TYPE_CLASS_SCOPE_P (type))
fn_context = error_mark_node;
if (!fn_context)
push_to_top_level ();
+ else
+ {
+ cp_unevaluated_operand = 0;
+ c_inhibit_evaluation_warnings = 0;
+ }
/* Use #pragma pack from the template context. */
saved_maximum_field_alignment = maximum_field_alignment;
maximum_field_alignment = TYPE_PRECISION (pattern);
}
}
+ if (fn_context)
+ {
+ /* Restore these before substituting into the lambda capture
+ initializers. */
+ cp_unevaluated_operand = saved_unevaluated_operand;
+ c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
+ }
+
if (tree expr = CLASSTYPE_LAMBDA_EXPR (type))
{
tree decl = lambda_function (type);
if (PRIMARY_TEMPLATE_P (t))
DECL_PRIMARY_TEMPLATE (r) = r;
- if (TREE_CODE (decl) != TYPE_DECL && TREE_CODE (decl) != VAR_DECL)
+ if (TREE_CODE (decl) != TYPE_DECL && !VAR_P (decl))
/* Record this non-type partial instantiation. */
register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
{
/* T is a static data member or namespace-scope entity.
We have to substitute into namespace-scope variables
- (even though such entities are never templates) because
- of cases like:
+ (not just variable templates) because of cases like:
template <class T> void f() { extern T t; }
}
SET_DECL_VALUE_EXPR (r, ve);
}
- if (TREE_STATIC (r) || DECL_EXTERNAL (r))
- set_decl_tls_model (r, decl_tls_model (t));
+ if (CP_DECL_THREAD_LOCAL_P (r)
+ && !processing_template_decl)
+ set_decl_tls_model (r, decl_default_tls_model (r));
}
else if (DECL_SELF_REFERENCE_P (t))
SET_DECL_SELF_REFERENCE_P (r);
initializer is present. We mimic the non-template
processing here. */
DECL_EXTERNAL (r) = 1;
+ if (DECL_NAMESPACE_SCOPE_P (t))
+ DECL_NOT_REALLY_EXTERN (r) = 1;
DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
if (TREE_STATIC (r))
rest_of_decl_compilation (r, toplevel_bindings_p (),
at_eof);
- else if (decl_constant_var_p (r))
- /* A use of a local constant decays to its value.
- FIXME update for core DR 696. */
- r = scalar_constant_value (r);
+ else
+ r = process_outer_var_ref (r, complain);
}
}
/* Remember this for subsequent uses. */
}
}
+/* Helper function for tsubst_omp_clauses, used for instantiation of
+ OMP_CLAUSE_DECL of clauses that handles also OpenMP array sections
+ represented with TREE_LIST. */
+
+static tree
+tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
+ tree in_decl)
+{
+ if (TREE_CODE (decl) == TREE_LIST)
+ {
+ tree low_bound
+ = tsubst_expr (TREE_PURPOSE (decl), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ tree length = tsubst_expr (TREE_VALUE (decl), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ tree chain = tsubst_omp_clause_decl (TREE_CHAIN (decl), args, complain,
+ in_decl);
+ if (TREE_PURPOSE (decl) == low_bound
+ && TREE_VALUE (decl) == length
+ && TREE_CHAIN (decl) == chain)
+ return decl;
+ return tree_cons (low_bound, length, chain);
+ }
+ return tsubst_copy (decl, args, complain, in_decl);
+}
+
/* Like tsubst_copy, but specifically for OpenMP clauses. */
static tree
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_COPYIN:
case OMP_CLAUSE_COPYPRIVATE:
+ case OMP_CLAUSE_UNIFORM:
+ OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args,
+ complain, in_decl);
+ break;
+ case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_FROM:
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_MAP:
+ OMP_CLAUSE_DECL (nc)
+ = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
+ in_decl);
+ break;
case OMP_CLAUSE_IF:
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_SCHEDULE:
case OMP_CLAUSE_COLLAPSE:
case OMP_CLAUSE_FINAL:
- case OMP_CLAUSE_DEPEND:
- case OMP_CLAUSE_FROM:
- case OMP_CLAUSE_TO:
- case OMP_CLAUSE_UNIFORM:
- case OMP_CLAUSE_MAP:
case OMP_CLAUSE_DEVICE:
case OMP_CLAUSE_DIST_SCHEDULE:
case OMP_CLAUSE_NUM_TEAMS:
else
gcc_assert (identifier_p (placeholder));
}
- OMP_CLAUSE_OPERAND (nc, 0)
- = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
- in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args,
+ complain, in_decl);
break;
case OMP_CLAUSE_LINEAR:
case OMP_CLAUSE_ALIGNED:
- OMP_CLAUSE_OPERAND (nc, 0)
- = tsubst_expr (OMP_CLAUSE_OPERAND (oc, 0), args, complain,
- in_decl, /*integral_constant_expression_p=*/false);
+ OMP_CLAUSE_DECL (nc) = tsubst_copy (OMP_CLAUSE_DECL (oc), args,
+ complain, in_decl);
OMP_CLAUSE_OPERAND (nc, 1)
= tsubst_expr (OMP_CLAUSE_OPERAND (oc, 1), args, complain,
in_decl, /*integral_constant_expression_p=*/false);
break;
-
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
&& !processing_template_decl
&& !cp_unevaluated_operand
&& (TREE_STATIC (r) || DECL_EXTERNAL (r))
- && DECL_THREAD_LOCAL_P (r))
+ && CP_DECL_THREAD_LOCAL_P (r))
{
if (tree wrap = get_tls_wrapper_fn (r))
/* Replace an evaluated use of the thread_local variable with
r = build_cxx_call (wrap, 0, NULL, tf_warning_or_error);
}
else if (outer_automatic_var_p (r))
- r = process_outer_var_ref (r, complain);
+ {
+ r = process_outer_var_ref (r, complain);
+ if (is_capture_proxy (r))
+ register_local_specialization (r, t);
+ }
if (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE)
/* If the original type was a reference, we'll be wrapped in
break;
case DEDUCE_CONV:
- {
- /* Swap PARM and ARG throughout the remainder of this
- function; the handling is precisely symmetric since PARM
- will initialize ARG rather than vice versa. */
- tree* temp = parm;
- parm = arg;
- arg = temp;
- break;
- }
+ /* Swap PARM and ARG throughout the remainder of this
+ function; the handling is precisely symmetric since PARM
+ will initialize ARG rather than vice versa. */
+ std::swap (parm, arg);
+ break;
case DEDUCE_EXACT:
/* Core issue #873: Do the DR606 thing (see below) for these cases,
names a dependent type. */
if (TREE_CODE (type) == TYPENAME_TYPE)
return true;
+
+ /* An alias template specialization can be dependent even if the
+ resulting type is not. */
+ if (dependent_alias_template_spec_p (type))
+ return true;
+
/* -- a cv-qualified type where the cv-unqualified type is
dependent.
No code is necessary for this bullet; the code below handles
&& (any_dependent_template_arguments_p
(INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
return true;
- /* For an alias template specialization, check the arguments both to the
- class template and the alias template. */
- else if (dependent_alias_template_spec_p (type))
- return true;
/* All TYPEOF_TYPEs, DECLTYPE_TYPEs, and UNDERLYING_TYPEs are
dependent; if the argument of the `typeof' expression is not