aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-11-01 11:57:32 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2024-11-01 11:57:32 +0100
commit7fdb66f0db6275118986ed8d77c94d6cfe5155c2 (patch)
treef6b675350783cc5ba06f271808ea92ed3602b206 /gcc
parent7f93910a8b5d606ad742a3594750f0c2b20d8bda (diff)
downloadgcc-7fdb66f0db6275118986ed8d77c94d6cfe5155c2.zip
gcc-7fdb66f0db6275118986ed8d77c94d6cfe5155c2.tar.gz
gcc-7fdb66f0db6275118986ed8d77c94d6cfe5155c2.tar.bz2
openmp: Return error_mark_node from tsubst_attribute for errneous varid
We incorrectly accept some invalid declare variant cases as if declare variant wasn't there, in particular if a function template has some dependent arguments and variant name lookup fails, because that is during fn_type_unification with complain=tf_none, it just sets it to error_mark_node and doesn't complain further, because it doesn't know the substitution failed (we don't return error_mark_node from tsubst_attribute, just create TREE_LIST with error_mark_node TREE_PURPOSE). The following patch fixes it by returning error_mark_node in that case, then fn_type_unification caller can see it failed and can redo it with explain_p so that errors are reported. 2024-11-01 Jakub Jelinek <jakub@redhat.com> * pt.cc (tsubst_attribute): For "omp declare variant base" attribute if varid is error_mark_node, set val to error_mark_node rather than creating a TREE_LIST with error_mark_node TREE_PURPOSE. * g++.dg/gomp/declare-variant-10.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/pt.cc5
-rw-r--r--gcc/testsuite/g++.dg/gomp/declare-variant-10.C56
2 files changed, 60 insertions, 1 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 15d6d82f..334dbb3 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -12163,7 +12163,10 @@ tsubst_attribute (tree t, tree *decl_p, tree args,
}
OMP_TSS_TRAIT_SELECTORS (tss) = nreverse (selectors);
}
- val = tree_cons (varid, ctx, chain);
+ if (varid == error_mark_node)
+ val = error_mark_node;
+ else
+ val = tree_cons (varid, ctx, chain);
}
/* If the first attribute argument is an identifier, don't
pass it through tsubst. Attributes like mode, format,
diff --git a/gcc/testsuite/g++.dg/gomp/declare-variant-10.C b/gcc/testsuite/g++.dg/gomp/declare-variant-10.C
new file mode 100644
index 0000000..282cbc7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/declare-variant-10.C
@@ -0,0 +1,56 @@
+// { dg-do compile }
+
+#pragma omp declare variant (f1) match(user={condition(1)}) // { dg-error "'f1' was not declared in this scope; did you mean 'f2'\\\?" }
+void
+f2 (int)
+{
+}
+
+void f3 (int);
+
+#pragma omp declare variant (f3) match(user={condition(1)}) // { dg-error "variant 'void f3\\\(int\\\)' and base 'void f4\\\(long int\\\)' have incompatible types" }
+void
+f4 (long)
+{
+}
+
+#pragma omp declare variant (f5) match(user={condition(1)}) // { dg-error "there are no arguments to 'f5' that depend on a template parameter, so a declaration of 'f5' must be available" }
+template <int N>
+void
+f6 (int)
+{
+}
+
+template <int N>
+void f7 (int);
+
+#pragma omp declare variant (f7) match(user={condition(1)}) // { dg-error "no matching function for call to 'f7\\\(long int\\\)'" }
+template <int N>
+void
+f8 (long)
+{
+}
+
+#pragma omp declare variant (f9) match(user={condition(1)})
+template <typename T>
+void
+f10 (T) // { dg-error "'f9' was not declared in this scope; did you mean 'f8'\\\?" }
+{
+}
+
+template <typename T>
+void f11 (T, int);
+
+#pragma omp declare variant (f11) match(user={condition(1)}) // { dg-error "variant 'void f11\\\(T, int\\\) \\\[with T = int\\\]' and base 'void f12\\\(T, long int\\\) \\\[with T = int\\\]' have incompatible types" }
+template <typename T>
+void
+f12 (T, long)
+{
+}
+
+void
+test ()
+{
+ f10 (0); // { dg-error "no matching function for call to 'f10\\\(int\\\)'" }
+ f12 (0, 0L);
+}