From: Alexandre Oliva Date: Wed, 13 Feb 2019 19:08:52 +0000 (+0000) Subject: [PR86379] do not use TREE_TYPE for USING_DECL_SCOPE X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=10839133ce6c196c9f338086ede5b3b192fc1944;p=gcc.git [PR86379] do not use TREE_TYPE for USING_DECL_SCOPE It's too risky to reuse the type field for USING_DECL_SCOPE. Language-independent parts of the compiler, such as location and non-lvalue wrappers, happily take the TREE_TYPE of a USING_DECL as if it was a type rather than an unrelated scope. For better or worse, USING_DECLs use the non-common struct so we can use the otherwise unused result field. Adjust fallout, from uses of TREE_TYPE that were supposed to be USING_DECL_SCOPE, to other accidental uses of TREE_TYPE of a USING_DECL. for gcc/cp/ChangeLog PR c++/86379 * cp-tree.h (USING_DECL_SCOPE): Use result rather than type. * name-lookup.c (strip_using_decl): Use USING_DECL_SCOPE. * search.c (protected_accessible_p): Follow USING_DECL_DECLS. (shared_member_p): Likewise. (lookup_member): Likewise. * decl.c (grok_special_member_properties): Skip USING_DECLs. * semantics.c (finish_omp_declare_simd_methods): Likewise. (finish_qualified_id_expr): Do not call shared_member_p with a dependent expr. for gcc/testsuite/ChangeLog PR c++/86379 * g++.dg/cpp0x/pr86379.C: New. From-SVN: r268851 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9627f3b1444..ef51d9a46e6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,16 @@ 2019-02-13 Alexandre Oliva + PR c++/86379 + * cp-tree.h (USING_DECL_SCOPE): Use result rather than type. + * name-lookup.c (strip_using_decl): Use USING_DECL_SCOPE. + * search.c (protected_accessible_p): Follow USING_DECL_DECLS. + (shared_member_p): Likewise. + (lookup_member): Likewise. + * decl.c (grok_special_member_properties): Skip USING_DECLs. + * semantics.c (finish_omp_declare_simd_methods): Likewise. + (finish_qualified_id_expr): Do not call shared_member_p with + a dependent expr. + PR c++/87322 * pt.c (tsubst_lambda_expr): Avoid duplicate tsubsting. Move cp_evaluated resetting before signature tsubsting. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index dada3a6aa41..44a3620a539 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3293,7 +3293,7 @@ struct GTY(()) lang_decl { #define DECL_DEPENDENT_P(NODE) DECL_LANG_FLAG_0 (USING_DECL_CHECK (NODE)) /* The scope named in a using decl. */ -#define USING_DECL_SCOPE(NODE) TREE_TYPE (USING_DECL_CHECK (NODE)) +#define USING_DECL_SCOPE(NODE) DECL_RESULT_FLD (USING_DECL_CHECK (NODE)) /* The decls named by a using decl. */ #define USING_DECL_DECLS(NODE) DECL_INITIAL (USING_DECL_CHECK (NODE)) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 31d7dc5be1e..8fe547c3ac5 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13317,7 +13317,8 @@ grok_special_member_properties (tree decl) { tree class_type; - if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) + if (TREE_CODE (decl) == USING_DECL + || !DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) return; class_type = DECL_CONTEXT (decl); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index d7b9029b0a3..959f43b0238 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2100,7 +2100,7 @@ strip_using_decl (tree decl) using typename :: [opt] nested-name-specifier unqualified-id ; */ - decl = make_typename_type (TREE_TYPE (decl), + decl = make_typename_type (USING_DECL_SCOPE (decl), DECL_NAME (decl), typename_type, tf_error); if (decl != error_mark_node) diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 0367e495213..4c3fffda717 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -623,6 +623,11 @@ protected_accessible_p (tree decl, tree derived, tree type, tree otype) if (!DERIVED_FROM_P (type, derived)) return 0; + /* DECL_NONSTATIC_MEMBER_P won't work for USING_DECLs. */ + decl = strip_using_decl (decl); + /* We don't expect or support dependent decls. */ + gcc_assert (TREE_CODE (decl) != USING_DECL); + /* [class.protected] When a friend or a member function of a derived class references @@ -928,8 +933,13 @@ shared_member_p (tree t) if (is_overloaded_fn (t)) { for (ovl_iterator iter (get_fns (t)); iter; ++iter) - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (*iter)) - return 0; + { + tree decl = strip_using_decl (*iter); + /* We don't expect or support dependent decls. */ + gcc_assert (TREE_CODE (decl) != USING_DECL); + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) + return 0; + } return 1; } return 0; @@ -1177,7 +1187,10 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type, && !really_overloaded_fn (rval)) { tree decl = is_overloaded_fn (rval) ? get_first_fn (rval) : rval; - if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl) + decl = strip_using_decl (decl); + /* A dependent USING_DECL will be checked after tsubsting. */ + if (TREE_CODE (decl) != USING_DECL + && !DECL_NONSTATIC_MEMBER_FUNCTION_P (decl) && !perform_or_defer_access_check (basetype_path, decl, decl, complain, afi)) rval = error_mark_node; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 786f18ab0c8..89ea438ebee 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2096,7 +2096,8 @@ finish_qualified_id_expr (tree qualifying_class, { /* See if any of the functions are non-static members. */ /* If so, the expression may be relative to 'this'. */ - if (!shared_member_p (expr) + if ((type_dependent_expression_p (expr) + || !shared_member_p (expr)) && current_class_ptr && DERIVED_FROM_P (qualifying_class, current_nonlambda_class_type ())) @@ -5867,7 +5868,8 @@ finish_omp_declare_simd_methods (tree t) for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x)) { - if (TREE_CODE (TREE_TYPE (x)) != METHOD_TYPE) + if (TREE_CODE (x) == USING_DECL + || !DECL_NONSTATIC_MEMBER_FUNCTION_P (x)) continue; tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x)); if (!ods || !TREE_VALUE (ods)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ad25ccb7dc5..74d0ad3e0e6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2019-02-13 Alexandre Oliva + PR c++/86379 + * g++.dg/cpp0x/pr86379.C: New. + PR c++/87322 * g++.dg/cpp1y/pr87322.C: New. * g++.dg/cpp0x/lambda/lambda-variadic5.C: Test that we diff --git a/gcc/testsuite/g++.dg/cpp0x/pr86379.C b/gcc/testsuite/g++.dg/cpp0x/pr86379.C new file mode 100644 index 00000000000..82282eae8e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr86379.C @@ -0,0 +1,207 @@ +// { dg-do compile { target c++11 } } + +// Reduced from Mozilla SpiderMonkey, licensed under MPL-2.0. + +template +class Vector +{ + public: + Vector() {} + unsigned length() const { return 0; } +}; + +class TokenStreamShared +{ +}; + +template +class TokenStreamSpecific; + +class TokenStreamAnyChars + : public TokenStreamShared +{ + public: + TokenStreamAnyChars() {} +}; + +template +class SourceUnits +{ + public: + SourceUnits() {} + + bool atEnd() const { return true; } + unsigned offset() const { return 0; } + bool matchCodeUnit(CharT c) { return true; } +}; + +class TokenStreamCharsShared +{ + using CharBuffer = Vector; + + protected: + CharBuffer charBuffer; + + protected: + explicit TokenStreamCharsShared() {} +}; + +template +class TokenStreamCharsBase + : public TokenStreamCharsShared +{ + public: + TokenStreamCharsBase() + : TokenStreamCharsShared(), sourceUnits() + {} + + using SourceUnits = ::SourceUnits; + + bool matchCodeUnit(int expect) { return true; } + + protected: + SourceUnits sourceUnits; +}; + +template +class GeneralTokenStreamChars + : public TokenStreamCharsBase +{ + using CharsBase = TokenStreamCharsBase; + + protected: + using CharsBase::CharsBase; + + TokenStreamAnyChars& anyCharsAccess(); + const TokenStreamAnyChars& anyCharsAccess() const; +}; + +template class TokenStreamChars; + +template +class TokenStreamChars + : public GeneralTokenStreamChars +{ + private: + using CharsBase = TokenStreamCharsBase; + using GeneralCharsBase = GeneralTokenStreamChars; + using Self = TokenStreamChars; + + protected: + using GeneralCharsBase::anyCharsAccess; + using CharsBase::sourceUnits; + + using typename GeneralCharsBase::SourceUnits; + + protected: + using GeneralCharsBase::GeneralCharsBase; + + bool getFullAsciiCodePoint(int lead, int* codePoint) { + if (lead == '\r') { + bool isAtEnd = sourceUnits.atEnd(); + if (!isAtEnd) + sourceUnits.matchCodeUnit('\n'); + } else if (lead != '\n') { + *codePoint = lead; + return true; + } + + *codePoint = '\n'; + return true; + } +}; + +template +class TokenStreamSpecific + : public TokenStreamChars, + public TokenStreamShared +{ + public: + using CharsBase = TokenStreamCharsBase; + using GeneralCharsBase = GeneralTokenStreamChars; + using SpecializedCharsBase = TokenStreamChars; + + public: + using GeneralCharsBase::anyCharsAccess; + + private: + using typename CharsBase::SourceUnits; + + private: + using TokenStreamCharsShared::charBuffer; + using CharsBase::sourceUnits; + + public: + TokenStreamSpecific() + : SpecializedCharsBase() + {} + + public: + bool advance(unsigned position) { + bool t = charBuffer.length() + 1 > 0; + auto offs = sourceUnits.offset(); + return t && offs > 0; + } +}; + +class TokenStreamAnyCharsAccess +{ +}; + +class TokenStream final + : public TokenStreamAnyChars, + public TokenStreamSpecific +{ + using CharT = char16_t; + + public: + TokenStream() + : TokenStreamAnyChars(), + TokenStreamSpecific() + {} +}; + +class SyntaxParseHandler {}; + +class ParserBase +{ + public: + TokenStreamAnyChars anyChars; +}; + +template class GeneralParser; + +template +class PerHandlerParser : public ParserBase +{ +}; + +template +class ParserAnyCharsAccess +{ +}; + +template +class Parser; + +template +class GeneralParser + : public PerHandlerParser +{ + public: + TokenStreamSpecific> tokenStream; + + public: + GeneralParser(); +}; + + +template class TokenStreamCharsBase; + +template class TokenStreamChars; + +template class +TokenStreamChars>>; + +template class +TokenStreamSpecific>>;