[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:
parent
60378a964a
commit
10839133ce
@ -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.
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
207
gcc/testsuite/g++.dg/cpp0x/pr86379.C
Normal file
207
gcc/testsuite/g++.dg/cpp0x/pr86379.C
Normal 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>>>;
|
Loading…
Reference in New Issue
Block a user