From: Patrick Palka Date: Fri, 1 May 2020 20:18:19 +0000 (-0400) Subject: c++: Missing SFINAE with inaccessible static data member [PR90880] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4f6c1ca287d2c64856ef67fa50bc462633d5b8cf;p=gcc.git c++: Missing SFINAE with inaccessible static data member [PR90880] This is a missing SFINAE issue when verifying the accessibility of a static data member. The cause is that check_accessibility_of_qualified_id unconditionally passes tf_warning_or_error to perform_or_defer_access_check, even when called from tsubst_qualified_id(..., complain=tf_none). This patch fixes this by plumbing 'complain' from tsubst_qualified_id through check_accessibility_of_qualified_id to reach perform_or_defer_access_check, and by giving check_accessibility_of_qualified_id the appropriate return value. gcc/cp/ChangeLog: PR c++/90880 * cp-tree.h (check_accessibility_of_qualified_id): Add tsubst_flags_t parameter and change return type to bool. * parser.c (cp_parser_lookup_name): Pass tf_warning_to_error to check_accessibility_of_qualified_id. * pt.c (tsubst_qualified_id): Return error_mark_node if check_accessibility_of_qualified_id returns false. * semantics.c (check_accessibility_of_qualified_id): Add complain parameter. Pass complain instead of tf_warning_or_error to perform_or_defer_access_check. Return true unless perform_or_defer_access_check returns false. gcc/testsuite/ChangeLog: PR c++/90880 * g++.dg/template/sfinae29.C: New test. --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0b6b0ee2f5f..5f2db010cb2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2020-05-01 Patrick Palka + + PR c++/90880 + * cp-tree.h (check_accessibility_of_qualified_id): Add + tsubst_flags_t parameter and change return type to bool. + * parser.c (cp_parser_lookup_name): Pass tf_warning_to_error to + check_accessibility_of_qualified_id. + * pt.c (tsubst_qualified_id): Return error_mark_node if + check_accessibility_of_qualified_id returns false. + * semantics.c (check_accessibility_of_qualified_id): Add + complain parameter. Pass complain instead of + tf_warning_or_error to perform_or_defer_access_check. Return + true unless perform_or_defer_access_check returns false. + 2020-05-01 Marek Polacek PR c++/94885 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e115a8a1d25..c4b81428e14 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7258,7 +7258,7 @@ extern bool expand_or_defer_fn_1 (tree); extern void expand_or_defer_fn (tree); extern void add_typedef_to_current_template_for_access_check (tree, tree, location_t); -extern void check_accessibility_of_qualified_id (tree, tree, tree); +extern bool check_accessibility_of_qualified_id (tree, tree, tree, tsubst_flags_t); extern tree finish_qualified_id_expr (tree, tree, bool, bool, bool, bool, tsubst_flags_t); extern void simplify_aggr_init_expr (tree *); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e1f9786893a..337f22d2784 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -28394,7 +28394,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name, During an explicit instantiation, access is not checked at all, as per [temp.explicit]. */ if (DECL_P (decl)) - check_accessibility_of_qualified_id (decl, object_type, parser->scope); + check_accessibility_of_qualified_id (decl, object_type, parser->scope, + tf_warning_or_error); maybe_record_typedef_use (decl); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9332865cf46..8106c25a2d9 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16180,8 +16180,9 @@ tsubst_qualified_id (tree qualified_id, tree args, if (DECL_P (expr)) { - check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE, - scope); + if (!check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE, + scope, complain)) + return error_mark_node; /* Remember that there was a reference to this entity. */ if (!mark_used (expr, complain) && !(complain & tf_error)) return error_mark_node; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 64a7b76d437..4d1592ab0d2 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2028,12 +2028,14 @@ add_typedef_to_current_template_for_access_check (tree typedef_decl, an error message if it is not accessible. If OBJECT_TYPE is non-NULL, we have just seen `x->' or `x.' and OBJECT_TYPE is the type of `*x', or `x', respectively. If the DECL was named as - `A::B' then NESTED_NAME_SPECIFIER is `A'. */ + `A::B' then NESTED_NAME_SPECIFIER is `A'. Return value is like + perform_access_checks above. */ -void +bool check_accessibility_of_qualified_id (tree decl, tree object_type, - tree nested_name_specifier) + tree nested_name_specifier, + tsubst_flags_t complain) { tree scope; tree qualifying_type = NULL_TREE; @@ -2050,13 +2052,13 @@ check_accessibility_of_qualified_id (tree decl, /* If we're not checking, return immediately. */ if (deferred_access_no_check) - return; + return true; /* Determine the SCOPE of DECL. */ scope = context_for_name_lookup (decl); /* If the SCOPE is not a type, then DECL is not a member. */ if (!TYPE_P (scope)) - return; + return true; /* Compute the scope through which DECL is being accessed. */ if (object_type /* OBJECT_TYPE might not be a class type; consider: @@ -2097,8 +2099,10 @@ check_accessibility_of_qualified_id (tree decl, or similar in a default argument value. */ && CLASS_TYPE_P (qualifying_type) && !dependent_type_p (qualifying_type)) - perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl, - decl, tf_warning_or_error); + return perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl, + decl, complain); + + return true; } /* EXPR is the result of a qualified-id. The QUALIFYING_CLASS was the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 997ef8d091c..176aa117904 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-05-01 Patrick Palka + + PR c++/90880 + * g++.dg/template/sfinae29.C: New test. + 2020-05-01 Marek Polacek PR c++/94885 diff --git a/gcc/testsuite/g++.dg/template/sfinae29.C b/gcc/testsuite/g++.dg/template/sfinae29.C new file mode 100644 index 00000000000..0ccaea8593d --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae29.C @@ -0,0 +1,25 @@ +// PR c++/90880 +// { dg-do compile { target c++11 } } + +template +struct status +{ static const bool value = false; }; + +template +struct status +{ static const bool value = true; }; + +struct s1{int member;}; +struct s2{int _member;}; + +class c1{int member;}; +class c2{int _member;}; + +void +foo() +{ + static_assert(status::value, "has member"); + static_assert(!status::value, "has no member"); + static_assert(!status::value, "has inaccessible member"); + static_assert(!status::value, "has no member"); +}