aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-05-28 00:35:56 -0400
committerJason Merrill <jason@redhat.com>2020-05-28 14:58:16 -0400
commit7b599b9f9a1e036ff75a4daa06ac7036c6ebbe01 (patch)
tree32f368ca47633fad4cba5936700a702f83585b9b
parentc83027f32d9cca84959c7d6a1e519a0129731501 (diff)
downloadgcc-7b599b9f9a1e036ff75a4daa06ac7036c6ebbe01.zip
gcc-7b599b9f9a1e036ff75a4daa06ac7036c6ebbe01.tar.gz
gcc-7b599b9f9a1e036ff75a4daa06ac7036c6ebbe01.tar.bz2
c++: Immediately deduce auto member [PR94926].
In r9-297 I was trying to be more flexible and treat static data members of class templates more like variable templates, where the type need not be determined until the variable is instantiated, but I suppose that in a class the types of all the non-template members need to be determined at the time of class instantiation. gcc/cp/ChangeLog: PR c++/94926 * decl.c (cp_finish_decl): Revert r9-297 change. (check_static_variable_definition): Likewise. * constexpr.c (ensure_literal_type_for_constexpr_object): Likewise. * pt.c (instantiate_decl): Return early on type error. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/pr86648.C: Expect error. * g++.dg/cpp1z/static2.C: Expect error. * g++.dg/cpp0x/nsdmi16.C: New test.
-rw-r--r--gcc/cp/constexpr.c2
-rw-r--r--gcc/cp/decl.c21
-rw-r--r--gcc/cp/pt.c1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi16.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/pr86648.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/static2.C2
6 files changed, 29 insertions, 12 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 4e441ac..4b1f92f 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -96,8 +96,6 @@ ensure_literal_type_for_constexpr_object (tree decl)
if (CLASS_TYPE_P (stype) && !COMPLETE_TYPE_P (complete_type (stype)))
/* Don't complain here, we'll complain about incompleteness
when we try to initialize the variable. */;
- else if (type_uses_auto (type))
- /* We don't know the actual type yet. */;
else if (!literal_type_p (type))
{
if (DECL_DECLARED_CONSTEXPR_P (decl))
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 56571e3..b0de906 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7467,18 +7467,24 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
- /* Do auto deduction unless decl is a function or an uninstantiated
- template specialization. */
if (TREE_CODE (decl) != FUNCTION_DECL
- && !(init == NULL_TREE
- && DECL_LANG_SPECIFIC (decl)
- && DECL_TEMPLATE_INSTANTIATION (decl)
- && !DECL_TEMPLATE_INSTANTIATED (decl))
&& (auto_node = type_uses_auto (type)))
{
tree d_init;
if (init == NULL_TREE)
- gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (auto_node));
+ {
+ if (DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INSTANTIATION (decl)
+ && !DECL_TEMPLATE_INSTANTIATED (decl))
+ {
+ /* init is null because we're deferring instantiating the
+ initializer until we need it. Well, we need it now. */
+ instantiate_decl (decl, /*defer_ok*/true, /*expl*/false);
+ return;
+ }
+
+ gcc_assert (CLASS_PLACEHOLDER_TEMPLATE (auto_node));
+ }
d_init = init;
if (d_init)
{
@@ -10171,7 +10177,6 @@ check_static_variable_definition (tree decl, tree type)
in check_initializer. Similarly for inline static data members. */
else if (DECL_P (decl)
&& (DECL_DECLARED_CONSTEXPR_P (decl)
- || undeduced_auto_decl (decl)
|| DECL_VAR_DECLARED_INLINE_P (decl)))
;
else if (cxx_dialect >= cxx11 && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4d9651a..90dafff 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -25293,6 +25293,7 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
d = DECL_CLONED_FUNCTION (d);
if (DECL_TEMPLATE_INSTANTIATED (d)
+ || TREE_TYPE (d) == error_mark_node
|| (TREE_CODE (d) == FUNCTION_DECL
&& DECL_DEFAULTED_FN (d) && DECL_INITIAL (d))
|| DECL_TEMPLATE_SPECIALIZATION (d))
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi16.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi16.C
new file mode 100644
index 0000000..07bc198
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi16.C
@@ -0,0 +1,11 @@
+// PR c++/94926
+// { dg-do compile { target c++11 } }
+
+template<typename>
+struct A {
+ static auto self_reference = A{}; // { dg-error "incomplete" }
+};
+
+int main() {
+ A<void>{};
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/pr86648.C b/gcc/testsuite/g++.dg/cpp1z/pr86648.C
index 20ee4c8..58c611c 100644
--- a/gcc/testsuite/g++.dg/cpp1z/pr86648.C
+++ b/gcc/testsuite/g++.dg/cpp1z/pr86648.C
@@ -1,5 +1,7 @@
// { dg-do compile { target c++17 } }
template <typename> class A;
-template <class T> struct B { static A a{T::a}; };
+template <class T> struct B {
+ static A a{T::a}; // { dg-error "int" }
+};
void foo () { B<int> a; }
diff --git a/gcc/testsuite/g++.dg/cpp1z/static2.C b/gcc/testsuite/g++.dg/cpp1z/static2.C
index 9462e03..5d93a0e7 100644
--- a/gcc/testsuite/g++.dg/cpp1z/static2.C
+++ b/gcc/testsuite/g++.dg/cpp1z/static2.C
@@ -3,7 +3,7 @@
template <class T>
struct A
{
- static constexpr auto x = T::x;
+ static constexpr auto x = T::x; // { dg-error "incomplete" }
};
struct B;