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
This commit is contained in:
Andrew Sutton 2019-11-19 15:18:50 +00:00 committed by Andrew Sutton
parent 7aabd67f18
commit cce3c9db9e
5 changed files with 93 additions and 41 deletions

View file

@ -1,3 +1,9 @@
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

View file

@ -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;
}

View file

@ -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.

View file

@ -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>
{ };
};

View file

@ -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));
}