aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/pt.c41
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr84630.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-uneval13.C11
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-expr1.C9
4 files changed, 48 insertions, 14 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c5b0a92..af7c67a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11571,6 +11571,8 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
val = tsubst_expr (val, args, complain, in_decl,
/*integral_constant_expression_p=*/false);
+ if (val == error_mark_node)
+ return error_mark_node;
if (val != TREE_VALUE (t))
return build_tree_list (TREE_PURPOSE (t), val);
return t;
@@ -11617,9 +11619,10 @@ tsubst_attributes (tree attributes, tree args,
/* Apply any attributes which had to be deferred until instantiation
time. DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes;
- ARGS, COMPLAIN, IN_DECL are as tsubst. */
+ ARGS, COMPLAIN, IN_DECL are as tsubst. Returns true normally,
+ false on error. */
-static void
+static bool
apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
tree args, tsubst_flags_t complain, tree in_decl)
{
@@ -11628,12 +11631,12 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
tree *p;
if (attributes == NULL_TREE)
- return;
+ return true;
if (DECL_P (*decl_p))
{
if (TREE_TYPE (*decl_p) == error_mark_node)
- return;
+ return false;
p = &DECL_ATTRIBUTES (*decl_p);
/* DECL_ATTRIBUTES comes from copy_node in tsubst_decl, and is identical
to our attributes parameter. */
@@ -11668,9 +11671,11 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
t = *p;
if (ATTR_IS_DEPENDENT (t))
{
+ *q = tsubst_attribute (t, decl_p, args, complain, in_decl);
+ if (*q == error_mark_node)
+ return false;
*p = TREE_CHAIN (t);
TREE_CHAIN (t) = NULL_TREE;
- *q = tsubst_attribute (t, decl_p, args, complain, in_decl);
while (*q)
q = &TREE_CHAIN (*q);
}
@@ -11680,6 +11685,7 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
cplus_decl_attributes (decl_p, late_attrs, attr_flags);
}
+ return true;
}
/* The template TMPL is being instantiated with the template arguments TARGS.
@@ -14048,6 +14054,10 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
tsubst (DECL_FRIEND_CONTEXT (t),
args, complain, in_decl));
+ if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl))
+ return error_mark_node;
+
/* Set up the DECL_TEMPLATE_INFO for R. There's no need to do
this in the special friend case mentioned above where
GEN_TMPL is NULL. */
@@ -14127,8 +14137,6 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
&& !processing_template_decl)
defaulted_late_check (r);
- apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
- args, complain, in_decl);
if (flag_openmp)
if (tree attr = lookup_attribute ("omp declare variant base",
DECL_ATTRIBUTES (r)))
@@ -14228,7 +14236,9 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
+ auto tparm_guard = make_temp_override (current_template_parms);
DECL_TEMPLATE_PARMS (r)
+ = current_template_parms
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
complain);
@@ -14491,8 +14501,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (!DECL_TEMPLATE_PARM_P (r))
DECL_ARG_TYPE (r) = type_passed_as (type);
- apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
- args, complain, in_decl);
+ if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl))
+ return error_mark_node;
/* Keep track of the first new parameter we
generate. That's what will be returned to the
@@ -14581,8 +14592,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
finish_member_declaration. */
DECL_CHAIN (r) = NULL_TREE;
- apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
- args, complain, in_decl);
+ if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl))
+ return error_mark_node;
if (vec)
TREE_VEC_ELT (vec, i) = r;
@@ -14901,9 +14913,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
DECL_CHAIN (r) = NULL_TREE;
- apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
- /*flags=*/0,
- args, complain, in_decl);
+ if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
+ /*flags=*/0,
+ args, complain, in_decl))
+ return error_mark_node;
/* Preserve a typedef that names a type. */
if (is_typedef_decl (r) && type != error_mark_node)
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr84630.C b/gcc/testsuite/g++.dg/cpp0x/pr84630.C
index 3c2b4e4..7d6361b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr84630.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr84630.C
@@ -5,3 +5,4 @@ template <typename...> struct c {
template <int> __attribute__((noinline([] {}))) int b(); // { dg-error "wrong number of arguments" }
};
c<> a;
+int i = a.b<42>();
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval13.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval13.C
new file mode 100644
index 0000000..df908f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval13.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++20 } }
+
+template <class U> struct A
+{
+ template <class T> void spam(decltype([]{}) *s = nullptr) { }
+};
+
+void foo()
+{
+ A<int>().spam<int>();
+}
diff --git a/gcc/testsuite/g++.dg/ext/attr-expr1.C b/gcc/testsuite/g++.dg/ext/attr-expr1.C
new file mode 100644
index 0000000..990e710
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attr-expr1.C
@@ -0,0 +1,9 @@
+// PR c++/95192
+
+template<typename T>
+__attribute__((assume_aligned(sizeof(int(T()))))) // { dg-message "function type" }
+T *f();
+
+void test21() {
+ void *p = f<void>() // { dg-error "no match" }
+}