summaryrefslogtreecommitdiff
path: root/gcc/cp/decl2.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl2.cc')
-rw-r--r--gcc/cp/decl2.cc44
1 files changed, 40 insertions, 4 deletions
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index dc2c924c472..d2b29208ed5 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -734,11 +734,15 @@ check_classfn (tree ctype, tree function, tree template_parms)
tree pushed_scope = push_scope (ctype);
tree matched = NULL_TREE;
tree fns = get_class_binding (ctype, DECL_NAME (function));
-
+ bool saw_template = false;
+
for (ovl_iterator iter (fns); !matched && iter; ++iter)
{
tree fndecl = *iter;
+ if (TREE_CODE (fndecl) == TEMPLATE_DECL)
+ saw_template = true;
+
/* A member template definition only matches a member template
declaration. */
if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
@@ -788,6 +792,23 @@ check_classfn (tree ctype, tree function, tree template_parms)
matched = fndecl;
}
+ if (!matched && !is_template && saw_template
+ && !processing_template_decl && DECL_UNIQUE_FRIEND_P (function))
+ {
+ /* "[if no non-template match is found,] each remaining function template
+ is replaced with the specialization chosen by deduction from the
+ friend declaration or discarded if deduction fails."
+
+ So ask check_explicit_specialization to find a matching template. */
+ SET_DECL_IMPLICIT_INSTANTIATION (function);
+ tree spec = check_explicit_specialization (DECL_NAME (function),
+ function, /* tcount */0,
+ /* friend flag */4,
+ /* attrlist */NULL_TREE);
+ if (spec != error_mark_node)
+ matched = spec;
+ }
+
if (!matched)
{
if (!COMPLETE_TYPE_P (ctype))
@@ -1513,12 +1534,19 @@ cp_check_const_attributes (tree attributes)
for (attr = attributes; attr; attr = TREE_CHAIN (attr))
{
tree arg;
+ /* As we implement alignas using gnu::aligned attribute and
+ alignas argument is a constant expression, force manifestly
+ constant evaluation of aligned attribute argument. */
+ bool manifestly_const_eval
+ = is_attribute_p ("aligned", get_attribute_name (attr));
for (arg = TREE_VALUE (attr); arg && TREE_CODE (arg) == TREE_LIST;
arg = TREE_CHAIN (arg))
{
tree expr = TREE_VALUE (arg);
if (EXPR_P (expr))
- TREE_VALUE (arg) = fold_non_dependent_expr (expr);
+ TREE_VALUE (arg)
+ = fold_non_dependent_expr (expr, tf_warning_or_error,
+ manifestly_const_eval);
}
}
}
@@ -1616,8 +1644,16 @@ find_last_decl (tree decl)
if (TREE_CODE (*iter) == OVERLOAD)
continue;
- if (decls_match (decl, *iter, /*record_decls=*/false))
- return *iter;
+ tree d = *iter;
+
+ /* We can't compare versions in the middle of processing the
+ attribute that has the version. */
+ if (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_FUNCTION_VERSIONED (d))
+ return NULL_TREE;
+
+ if (decls_match (decl, d, /*record_decls=*/false))
+ return d;
}
return NULL_TREE;
}