From cce3c9db9e6ffad764504134336c714a90416e8d Mon Sep 17 00:00:00 2001 From: Andrew Sutton Date: Tue, 19 Nov 2019 15:18:50 +0000 Subject: [PATCH] re PR c++/92078 (error: 'struct std::ptr' redeclared with different access) PR c++/92078 gcc/cp/ * pt.c (maybe_new_partial_specialization): Apply access to newly created partial specializations. Update comment style. gcc/testsuite/ * g++.dg/cpp2a/concepts-pr92078.C: New. * g++.dg/cpp2a/concepts-requires18.C: Update diagnostics. From-SVN: r278450 --- gcc/cp/ChangeLog | 6 ++ gcc/cp/pt.c | 83 ++++++++++++------------ gcc/testsuite/ChangeLog | 6 ++ gcc/testsuite/g++.dg/cpp2a/concepts-pr92078.C | 20 ++++++ gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C | 19 +++++- 5 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr92078.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 819de73..08b44c5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2019-11-19 Andrew Sutton + PR c++/92078 + * pt.c (maybe_new_partial_specialization): Apply access to newly + created partial specializations. Update comment style. + +2019-11-19 Andrew Sutton + PR c++/92403 Suppress diagnostics substituting into a requires-expression. * pt.c (tsubst_copy_and_build): Perform the first substitution without diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 424098a..59f9d03 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -848,58 +848,59 @@ check_explicit_instantiation_namespace (tree spec) spec, current_namespace, ns); } -// Returns the type of a template specialization only if that -// specialization needs to be defined. Otherwise (e.g., if the type has -// already been defined), the function returns NULL_TREE. +/* Returns the type of a template specialization only if that + specialization needs to be defined. Otherwise (e.g., if the type has + already been defined), the function returns NULL_TREE. */ + static tree maybe_new_partial_specialization (tree type) { - // An implicit instantiation of an incomplete type implies - // the definition of a new class template. - // - // template - // struct S; - // - // template - // struct S; - // - // Here, S is an implicit instantiation of S whose type - // is incomplete. + /* An implicit instantiation of an incomplete type implies + the definition of a new class template. + + template + struct S; + + template + struct S; + + Here, S is an implicit instantiation of S whose type + is incomplete. */ if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type)) return type; - // It can also be the case that TYPE is a completed specialization. - // Continuing the previous example, suppose we also declare: - // - // template - // requires Integral - // struct S; - // - // Here, S refers to the specialization S defined - // above. However, we need to differentiate definitions because - // we intend to define a new partial specialization. In this case, - // we rely on the fact that the constraints are different for - // this declaration than that above. - // - // Note that we also get here for injected class names and - // late-parsed template definitions. We must ensure that we - // do not create new type declarations for those cases. + /* It can also be the case that TYPE is a completed specialization. + Continuing the previous example, suppose we also declare: + + template + requires Integral + struct S; + + Here, S refers to the specialization S defined + above. However, we need to differentiate definitions because + we intend to define a new partial specialization. In this case, + we rely on the fact that the constraints are different for + this declaration than that above. + + Note that we also get here for injected class names and + late-parsed template definitions. We must ensure that we + do not create new type declarations for those cases. */ if (flag_concepts && CLASSTYPE_TEMPLATE_SPECIALIZATION (type)) { tree tmpl = CLASSTYPE_TI_TEMPLATE (type); tree args = CLASSTYPE_TI_ARGS (type); - // If there are no template parameters, this cannot be a new - // partial template specializtion? + /* If there are no template parameters, this cannot be a new + partial template specialization? */ if (!current_template_parms) return NULL_TREE; - // The injected-class-name is not a new partial specialization. + /* The injected-class-name is not a new partial specialization. */ if (DECL_SELF_REFERENCE_P (TYPE_NAME (type))) return NULL_TREE; - // If the constraints are not the same as those of the primary - // then, we can probably create a new specialization. + /* If the constraints are not the same as those of the primary + then, we can probably create a new specialization. */ tree type_constr = current_template_constraints (); if (type == TREE_TYPE (tmpl)) @@ -909,8 +910,8 @@ maybe_new_partial_specialization (tree type) return NULL_TREE; } - // Also, if there's a pre-existing specialization with matching - // constraints, then this also isn't new. + /* Also, if there's a pre-existing specialization with matching + constraints, then this also isn't new. */ tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); while (specs) { @@ -923,8 +924,8 @@ maybe_new_partial_specialization (tree type) specs = TREE_CHAIN (specs); } - // Create a new type node (and corresponding type decl) - // for the newly declared specialization. + /* Create a new type node (and corresponding type decl) + for the newly declared specialization. */ tree t = make_class_type (TREE_CODE (type)); CLASSTYPE_DECLARED_CLASS (t) = CLASSTYPE_DECLARED_CLASS (type); SET_TYPE_TEMPLATE_INFO (t, build_template_info (tmpl, args)); @@ -934,10 +935,12 @@ maybe_new_partial_specialization (tree type) equivalent. So keep TYPE_CANONICAL the same. */ TYPE_CANONICAL (t) = TYPE_CANONICAL (type); - // Build the corresponding type decl. + /* Build the corresponding type decl. */ tree d = create_implicit_typedef (DECL_NAME (tmpl), t); DECL_CONTEXT (d) = TYPE_CONTEXT (t); DECL_SOURCE_LOCATION (d) = input_location; + TREE_PRIVATE (d) = (current_access_specifier == access_private_node); + TREE_PROTECTED (d) = (current_access_specifier == access_protected_node); return t; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 878bc02..edbf126 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-11-19 Andrew Sutton + + PR c++/92078 + * g++.dg/cpp2a/concepts-pr92078.C: New. + * g++.dg/cpp2a/concepts-requires18.C: Update diagnostics. + 2019-11-19 Andrew Stubbs * gcc.dg/tree-ssa/loop-1.c: Change amdgcn assembler scan. diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr92078.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr92078.C new file mode 100644 index 0000000..9bfb896 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr92078.C @@ -0,0 +1,20 @@ +// { dg-do compile { target c++2a } } + +template +struct iterator_traits +{ +private: + template + struct ptr + { }; + + template + requires requires { typename J::X; } + struct ptr + { }; + + template + requires (!requires { typename J::X; } && requires { typename J::Y; }) + struct ptr + { }; +}; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C index 9d9d0d9..c76b12c 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C @@ -44,13 +44,25 @@ struct data template constexpr bool test() { - if constexpr (requires { requires subst; }) // { dg-error "forming reference" } + if constexpr (requires { requires subst; }) return true; else return false; } }; +template +constexpr bool check_for_resize(T &v, unsigned const n) +{ + if constexpr (requires { v.resize(n); }) + return true; + else + return false; +} + +struct array { }; +struct vector { void resize(int n); }; + void test() { f1(); @@ -74,4 +86,9 @@ void test() data t; static_assert(t.test()); static_assert(t.test()); // { dg-error "static assertion failed" } + + vector v; + static_assert(check_for_resize(v, 10)); + array a; + static_assert(!check_for_resize(a, 10)); } -- 2.7.4