aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew Sutton <asutton@lock3software.com>2019-11-19 15:18:50 +0000
committerAndrew Sutton <asutton@gcc.gnu.org>2019-11-19 15:18:50 +0000
commitcce3c9db9e6ffad764504134336c714a90416e8d (patch)
tree52263d6890f1c2ba154074c7465dc27b9f8599c0 /gcc
parent7aabd67f18fb1e0ef4c9981667284c2e57816e01 (diff)
downloadgcc-cce3c9db9e6ffad764504134336c714a90416e8d.zip
gcc-cce3c9db9e6ffad764504134336c714a90416e8d.tar.gz
gcc-cce3c9db9e6ffad764504134336c714a90416e8d.tar.bz2
re PR c++/92078 (error: 'struct std::ptr<Iter>' 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c83
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr92078.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires18.C19
5 files changed, 93 insertions, 41 deletions
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 <asutton@lock3software.com>
+ PR c++/92078
+ * pt.c (maybe_new_partial_specialization): Apply access to newly
+ created partial specializations. Update comment style.
+
+2019-11-19 Andrew Sutton <asutton@lock3software.com>
+
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<typename T>
- // struct S;
- //
- // template<typename T>
- // struct S<T*>;
- //
- // Here, S<T*> 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<typename T>
+ struct S;
+
+ template<typename T>
+ struct S<T*>;
+
+ Here, S<T*> 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<typename T>
- // requires Integral<T>
- // struct S<T*>;
- //
- // Here, S<T*> refers to the specialization S<T*> 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<typename T>
+ requires Integral<T>
+ struct S<T*>;
+
+ Here, S<T*> refers to the specialization S<T*> 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 <asutton@lock3software.com>
+
+ PR c++/92078
+ * g++.dg/cpp2a/concepts-pr92078.C: New.
+ * g++.dg/cpp2a/concepts-requires18.C: Update diagnostics.
+
2019-11-19 Andrew Stubbs <ams@codesourcery.com>
* 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<typename I>
+struct iterator_traits
+{
+private:
+ template<typename Iter>
+ struct ptr
+ { };
+
+ template<typename J>
+ requires requires { typename J::X; }
+ struct ptr<J>
+ { };
+
+ template<typename J>
+ requires (!requires { typename J::X; } && requires { typename J::Y; })
+ struct ptr<J>
+ { };
+};
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<typename U>
constexpr bool test()
{
- if constexpr (requires { requires subst<U&>; }) // { dg-error "forming reference" }
+ if constexpr (requires { requires subst<U&>; })
return true;
else
return false;
}
};
+template<typename T>
+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<int>();
@@ -74,4 +86,9 @@ void test()
data<int> t;
static_assert(t.test<int>());
static_assert(t.test<void>()); // { dg-error "static assertion failed" }
+
+ vector v;
+ static_assert(check_for_resize(v, 10));
+ array a;
+ static_assert(!check_for_resize(a, 10));
}