public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-6380] c++: non-dependent variable template-id [PR108848]
@ 2023-02-28 20:05 Patrick Palka
0 siblings, 0 replies; only message in thread
From: Patrick Palka @ 2023-02-28 20:05 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:d3d205ab440886164b6de2be2a2efa10cac95b66
commit r13-6380-gd3d205ab440886164b6de2be2a2efa10cac95b66
Author: Patrick Palka <ppalka@redhat.com>
Date: Tue Feb 28 15:05:30 2023 -0500
c++: non-dependent variable template-id [PR108848]
Here we're treating deeming the non-dependent variable template-id
tag<int> as dependent ever since r226642 gave variable TEMPLATE_ID_EXPR
an empty type, which causes the call to finish_template_variable from
finish_id_expression_1 to be unreachable at template parse time. Thus
we're led into thinking tag<int>.var<void> refers to a dependent name.
This patch fixes this by making finish_id_expression_1 instantiate a
variable template-id as long as it's not dependent according to the
dependence test in lookup_and_finish_template_variable rather than
according to type_dependent_expression_p.
PR c++/108848
gcc/cp/ChangeLog:
* pt.cc (finish_template_variable): Move dependence check
to here from ...
(lookup_and_finish_template_variable): ... here.
* semantics.cc (finish_id_expression_1): Call
finish_template_variable sooner, before (and regardless of) the
type_dependent_expression_p test.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1y/noexcept1.C: Don't expect a bogus "different
exception specifier" error. Expect a separate "not usable
in a constant expression" error.
* g++.dg/cpp1y/var-templ75.C: New test.
* g++.dg/cpp1y/var-templ76.C: New test.
Diff:
---
gcc/cp/pt.cc | 30 ++++++++++++++++--------------
gcc/cp/semantics.cc | 19 ++++++++++---------
gcc/testsuite/g++.dg/cpp1y/noexcept1.C | 4 ++--
gcc/testsuite/g++.dg/cpp1y/var-templ75.C | 20 ++++++++++++++++++++
gcc/testsuite/g++.dg/cpp1y/var-templ76.C | 13 +++++++++++++
5 files changed, 61 insertions(+), 25 deletions(-)
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f636bac5413..03958da1fea 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10317,7 +10317,8 @@ lookup_template_variable (tree templ, tree arglist)
return build2 (TEMPLATE_ID_EXPR, NULL_TREE, templ, arglist);
}
-/* Instantiate a variable declaration from a TEMPLATE_ID_EXPR for use. */
+/* Instantiate a variable declaration from a TEMPLATE_ID_EXPR if it's
+ not dependent. */
tree
finish_template_variable (tree var, tsubst_flags_t complain)
@@ -10325,6 +10326,12 @@ finish_template_variable (tree var, tsubst_flags_t complain)
tree templ = TREE_OPERAND (var, 0);
tree arglist = TREE_OPERAND (var, 1);
+ /* If the template or arguments are dependent, then we
+ can't resolve the TEMPLATE_ID_EXPR yet. */
+ if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (templ)) != 1
+ || any_dependent_template_arguments_p (arglist))
+ return var;
+
tree parms = DECL_TEMPLATE_PARMS (templ);
arglist = coerce_template_parms (parms, arglist, templ, complain);
if (arglist == error_mark_node)
@@ -10352,19 +10359,14 @@ lookup_and_finish_template_variable (tree templ, tree targs,
tsubst_flags_t complain)
{
tree var = lookup_template_variable (templ, targs);
- if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (templ)) == 1
- && !any_dependent_template_arguments_p (targs))
- {
- /* We may be called while doing a partial substitution, but the
- type of the variable template may be auto, in which case we
- will call do_auto_deduction in mark_used (which clears tf_partial)
- and the auto must be properly reduced at that time for the
- deduction to work. */
- complain &= ~tf_partial;
- var = finish_template_variable (var, complain);
- mark_used (var);
- }
-
+ /* We may be called while doing a partial substitution, but the
+ type of the variable template may be auto, in which case we
+ will call do_auto_deduction in mark_used (which clears tf_partial)
+ and the auto must be properly reduced at that time for the
+ deduction to work. */
+ complain &= ~tf_partial;
+ var = finish_template_variable (var, complain);
+ mark_used (var);
return convert_from_reference (var);
}
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 79b7cc72f21..db982d594e6 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4208,6 +4208,16 @@ finish_id_expression_1 (tree id_expression,
}
else
{
+ if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
+ && variable_template_p (TREE_OPERAND (decl, 0))
+ && !concept_check_p (decl))
+ /* Try resolving this variable TEMPLATE_ID_EXPR (which is always
+ considered type-dependent) now, so that the dependence test that
+ follows gives us the right answer: if it represents a non-dependent
+ variable template-id then finish_template_variable will yield the
+ corresponding non-dependent VAR_DECL. */
+ decl = finish_template_variable (decl);
+
bool dependent_p = type_dependent_expression_p (decl);
/* If the declaration was explicitly qualified indicate
@@ -4275,15 +4285,6 @@ finish_id_expression_1 (tree id_expression,
/* Replace an evaluated use of the thread_local variable with
a call to its wrapper. */
decl = wrap;
- else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
- && !dependent_p
- && variable_template_p (TREE_OPERAND (decl, 0))
- && !concept_check_p (decl))
- {
- decl = finish_template_variable (decl);
- mark_used (decl);
- decl = convert_from_reference (decl);
- }
else if (concept_check_p (decl))
{
/* Nothing more to do. All of the analysis for concept checks
diff --git a/gcc/testsuite/g++.dg/cpp1y/noexcept1.C b/gcc/testsuite/g++.dg/cpp1y/noexcept1.C
index 86e46c96148..caa4a056a2e 100644
--- a/gcc/testsuite/g++.dg/cpp1y/noexcept1.C
+++ b/gcc/testsuite/g++.dg/cpp1y/noexcept1.C
@@ -5,9 +5,9 @@ template <int> bool b;
template <typename>
struct C {
- template <typename> friend int foo() noexcept(b<1>); // { dg-error "not usable in a constant expression|different exception specifier" }
+ template <typename> friend int foo() noexcept(b<1>); // { dg-error "not usable in a constant expression" }
};
-template <typename> int foo() noexcept(b<1>);
+template <typename> int foo() noexcept(b<1>); // { dg-error "not usable in a constant expression" }
auto a = C<int>();
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ75.C b/gcc/testsuite/g++.dg/cpp1y/var-templ75.C
new file mode 100644
index 00000000000..d2ab807ab9a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ75.C
@@ -0,0 +1,20 @@
+// PR c++/108848
+// { dg-do compile { target c++14 } }
+
+template<class T>
+struct tag_t {
+ template<class Sig>
+ static constexpr const Sig* var = nullptr;
+
+ template<class Sig>
+ static const Sig* fun();
+};
+
+template<class T>
+constexpr tag_t<T> tag;
+
+template<class T>
+void f() {
+ tag<int>.var<void>; // { dg-bogus "expected 'template' keyword" }
+ tag<int>.fun<void>(); // { dg-bogus "expected 'template' keyword" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ76.C b/gcc/testsuite/g++.dg/cpp1y/var-templ76.C
new file mode 100644
index 00000000000..2acb8150953
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ76.C
@@ -0,0 +1,13 @@
+// Verify we can evaluate a non-dependent variable template-id ahead of time.
+// { dg-do compile { target c++14 } }
+
+template<int N>
+constexpr int var = N;
+
+template<int N> void f(int) = delete;
+template<int N> void f(...);
+
+template<class T>
+void g() {
+ f<var<42>>(0); // { dg-error "deleted" }
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-02-28 20:05 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-28 20:05 [gcc r13-6380] c++: non-dependent variable template-id [PR108848] Patrick Palka
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).