[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
This commit is contained in:
Alexandre Oliva 2019-02-13 19:08:52 +00:00 committed by Alexandre Oliva
parent 60378a964a
commit 10839133ce
8 changed files with 245 additions and 8 deletions

View File

@ -1,5 +1,16 @@
2019-02-13 Alexandre Oliva <aoliva@redhat.com>
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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,8 @@
2019-02-13 Alexandre Oliva <aoliva@redhat.com>
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

View File

@ -0,0 +1,207 @@
// { dg-do compile { target c++11 } }
// Reduced from Mozilla SpiderMonkey, licensed under MPL-2.0.
template<typename T, unsigned N>
class Vector
{
public:
Vector() {}
unsigned length() const { return 0; }
};
class TokenStreamShared
{
};
template<typename CharT, class AnyCharsAccess>
class TokenStreamSpecific;
class TokenStreamAnyChars
: public TokenStreamShared
{
public:
TokenStreamAnyChars() {}
};
template<typename CharT>
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<char16_t, 32>;
protected:
CharBuffer charBuffer;
protected:
explicit TokenStreamCharsShared() {}
};
template<typename CharT>
class TokenStreamCharsBase
: public TokenStreamCharsShared
{
public:
TokenStreamCharsBase()
: TokenStreamCharsShared(), sourceUnits()
{}
using SourceUnits = ::SourceUnits<CharT>;
bool matchCodeUnit(int expect) { return true; }
protected:
SourceUnits sourceUnits;
};
template<typename CharT, class AnyCharsAccess>
class GeneralTokenStreamChars
: public TokenStreamCharsBase<CharT>
{
using CharsBase = TokenStreamCharsBase<CharT>;
protected:
using CharsBase::CharsBase;
TokenStreamAnyChars& anyCharsAccess();
const TokenStreamAnyChars& anyCharsAccess() const;
};
template<typename CharT, class AnyCharsAccess> class TokenStreamChars;
template<class AnyCharsAccess>
class TokenStreamChars<char16_t, AnyCharsAccess>
: public GeneralTokenStreamChars<char16_t, AnyCharsAccess>
{
private:
using CharsBase = TokenStreamCharsBase<char16_t>;
using GeneralCharsBase = GeneralTokenStreamChars<char16_t, AnyCharsAccess>;
using Self = TokenStreamChars<char16_t, AnyCharsAccess>;
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<typename CharT, class AnyCharsAccess>
class TokenStreamSpecific
: public TokenStreamChars<CharT, AnyCharsAccess>,
public TokenStreamShared
{
public:
using CharsBase = TokenStreamCharsBase<CharT>;
using GeneralCharsBase = GeneralTokenStreamChars<CharT, AnyCharsAccess>;
using SpecializedCharsBase = TokenStreamChars<CharT, AnyCharsAccess>;
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<char16_t, TokenStreamAnyCharsAccess>
{
using CharT = char16_t;
public:
TokenStream()
: TokenStreamAnyChars(),
TokenStreamSpecific<CharT, TokenStreamAnyCharsAccess>()
{}
};
class SyntaxParseHandler {};
class ParserBase
{
public:
TokenStreamAnyChars anyChars;
};
template<class ParseHandler, typename CharT> class GeneralParser;
template <class ParseHandler>
class PerHandlerParser : public ParserBase
{
};
template<class Parser>
class ParserAnyCharsAccess
{
};
template <class ParseHandler, typename CharT>
class Parser;
template <class ParseHandler, typename CharT>
class GeneralParser
: public PerHandlerParser<ParseHandler>
{
public:
TokenStreamSpecific<CharT, ParserAnyCharsAccess<GeneralParser>> tokenStream;
public:
GeneralParser();
};
template class TokenStreamCharsBase<char16_t>;
template class TokenStreamChars<char16_t, TokenStreamAnyCharsAccess>;
template class
TokenStreamChars<char16_t, ParserAnyCharsAccess<GeneralParser<SyntaxParseHandler, char16_t>>>;
template class
TokenStreamSpecific<char16_t, ParserAnyCharsAccess<GeneralParser<SyntaxParseHandler, char16_t>>>;