re PR c++/37208 (C++0x deleted functions and SFINAE)
PR c++/37208 * call.c (build_over_call): Make =delete work with SFINAE. * class.c (resolve_address_of_overloaded_function): Likewise. * cp-tree.h (struct lang_decl_flags): Rename threadprivate_p to threadprivate_or_deleted_p. (CP_DECL_THREADPRIVATE_P): Adjust. (DECL_DELETED_FN): Likewise. (SD_UNINITIALIZED, SD_INITIALIZED, SD_DEFAULTED): New macros. (SD_DELETED): New macro. * parser.c (cp_parser_init_declarator): Use them. * decl.c (start_decl): Use them. * decl2.c (mark_used): Give =deleted error even in sizeof. * typeck2.c (check_narrowing): Downgrade narrowing error to permerror. From-SVN: r139926
This commit is contained in:
parent
a63068b6dd
commit
4ad610c978
|
@ -1,3 +1,23 @@
|
||||||
|
2008-09-02 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
PR c++/37208
|
||||||
|
* call.c (build_over_call): Make =delete work with SFINAE.
|
||||||
|
* class.c (resolve_address_of_overloaded_function): Likewise.
|
||||||
|
|
||||||
|
* cp-tree.h (struct lang_decl_flags): Rename threadprivate_p to
|
||||||
|
threadprivate_or_deleted_p.
|
||||||
|
(CP_DECL_THREADPRIVATE_P): Adjust.
|
||||||
|
(DECL_DELETED_FN): Likewise.
|
||||||
|
(SD_UNINITIALIZED, SD_INITIALIZED, SD_DEFAULTED): New macros.
|
||||||
|
(SD_DELETED): New macro.
|
||||||
|
* parser.c (cp_parser_init_declarator): Use them.
|
||||||
|
* decl.c (start_decl): Use them.
|
||||||
|
|
||||||
|
* decl2.c (mark_used): Give =deleted error even in sizeof.
|
||||||
|
|
||||||
|
* typeck2.c (check_narrowing): Downgrade narrowing error to
|
||||||
|
permerror.
|
||||||
|
|
||||||
2008-09-02 Aldy Hernandez <aldyh@redhat.com>
|
2008-09-02 Aldy Hernandez <aldyh@redhat.com>
|
||||||
|
|
||||||
* typeck.c (build_array_ref): Use new location argument.
|
* typeck.c (build_array_ref): Use new location argument.
|
||||||
|
|
|
@ -5119,6 +5119,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
||||||
joust (cand, w->loser, 1);
|
joust (cand, w->loser, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make =delete work with SFINAE. */
|
||||||
|
if (DECL_DELETED_FN (fn) && !(complain & tf_error))
|
||||||
|
return error_mark_node;
|
||||||
|
|
||||||
if (DECL_FUNCTION_MEMBER_P (fn))
|
if (DECL_FUNCTION_MEMBER_P (fn))
|
||||||
{
|
{
|
||||||
/* If FN is a template function, two cases must be considered.
|
/* If FN is a template function, two cases must be considered.
|
||||||
|
|
|
@ -6185,6 +6185,10 @@ resolve_address_of_overloaded_function (tree target_type,
|
||||||
function will be marked as used at this point. */
|
function will be marked as used at this point. */
|
||||||
if (!(flags & tf_conv))
|
if (!(flags & tf_conv))
|
||||||
{
|
{
|
||||||
|
/* Make =delete work with SFINAE. */
|
||||||
|
if (DECL_DELETED_FN (fn) && !(flags & tf_error))
|
||||||
|
return error_mark_node;
|
||||||
|
|
||||||
mark_used (fn);
|
mark_used (fn);
|
||||||
/* We could not check access when this expression was originally
|
/* We could not check access when this expression was originally
|
||||||
created since we did not know at that time to which function
|
created since we did not know at that time to which function
|
||||||
|
|
|
@ -1629,7 +1629,7 @@ struct lang_decl_flags GTY(())
|
||||||
unsigned this_thunk_p : 1;
|
unsigned this_thunk_p : 1;
|
||||||
unsigned repo_available_p : 1;
|
unsigned repo_available_p : 1;
|
||||||
unsigned hidden_friend_p : 1;
|
unsigned hidden_friend_p : 1;
|
||||||
unsigned threadprivate_p : 1;
|
unsigned threadprivate_or_deleted_p : 1;
|
||||||
unsigned defaulted_p : 1;
|
unsigned defaulted_p : 1;
|
||||||
|
|
||||||
union lang_decl_u {
|
union lang_decl_u {
|
||||||
|
@ -2645,11 +2645,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
||||||
/* Nonzero if DECL has been declared threadprivate by
|
/* Nonzero if DECL has been declared threadprivate by
|
||||||
#pragma omp threadprivate. */
|
#pragma omp threadprivate. */
|
||||||
#define CP_DECL_THREADPRIVATE_P(DECL) \
|
#define CP_DECL_THREADPRIVATE_P(DECL) \
|
||||||
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (DECL))->decl_flags.threadprivate_p)
|
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (DECL))->decl_flags.threadprivate_or_deleted_p)
|
||||||
|
|
||||||
/* Nonzero if DECL was declared with '= delete'. */
|
/* Nonzero if DECL was declared with '= delete'. */
|
||||||
#define DECL_DELETED_FN(DECL) \
|
#define DECL_DELETED_FN(DECL) \
|
||||||
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.threadprivate_p)
|
(DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.threadprivate_or_deleted_p)
|
||||||
|
|
||||||
/* Nonzero if DECL was declared with '= default'. */
|
/* Nonzero if DECL was declared with '= default'. */
|
||||||
#define DECL_DEFAULTED_FN(DECL) \
|
#define DECL_DEFAULTED_FN(DECL) \
|
||||||
|
@ -3863,6 +3863,12 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
||||||
#define SF_INCLASS_INLINE 2 /* The function is an inline, defined
|
#define SF_INCLASS_INLINE 2 /* The function is an inline, defined
|
||||||
in the class body. */
|
in the class body. */
|
||||||
|
|
||||||
|
/* Used with start_decl's initialized parameter. */
|
||||||
|
#define SD_UNINITIALIZED 0
|
||||||
|
#define SD_INITIALIZED 1
|
||||||
|
#define SD_DEFAULTED 2
|
||||||
|
#define SD_DELETED 3
|
||||||
|
|
||||||
/* Returns nonzero iff TYPE1 and TYPE2 are the same type, or if TYPE2
|
/* Returns nonzero iff TYPE1 and TYPE2 are the same type, or if TYPE2
|
||||||
is derived from TYPE1, or if TYPE2 is a pointer (reference) to a
|
is derived from TYPE1, or if TYPE2 is a pointer (reference) to a
|
||||||
class derived from the type pointed to (referred to) by TYPE1. */
|
class derived from the type pointed to (referred to) by TYPE1. */
|
||||||
|
|
|
@ -3969,14 +3969,14 @@ groktypename (cp_decl_specifier_seq *type_specifiers,
|
||||||
grokfield.) The DECL corresponding to the DECLARATOR is returned.
|
grokfield.) The DECL corresponding to the DECLARATOR is returned.
|
||||||
If an error occurs, the error_mark_node is returned instead.
|
If an error occurs, the error_mark_node is returned instead.
|
||||||
|
|
||||||
DECLSPECS are the decl-specifiers for the declaration. INITIALIZED is 1
|
DECLSPECS are the decl-specifiers for the declaration. INITIALIZED is
|
||||||
if an explicit initializer is present, or 2 for an explicitly defaulted
|
SD_INITIALIZED if an explicit initializer is present, or SD_DEFAULTED
|
||||||
function, or 3 for an explicitly deleted function, but 0 if this is a
|
for an explicitly defaulted function, or SD_DELETED for an explicitly
|
||||||
variable implicitly initialized via a default constructor. ATTRIBUTES
|
deleted function, but 0 (SD_UNINITIALIZED) if this is a variable
|
||||||
and PREFIX_ATTRIBUTES are GNU attributes associated with this
|
implicitly initialized via a default constructor. ATTRIBUTES and
|
||||||
declaration. *PUSHED_SCOPE_P is set to the scope entered in this
|
PREFIX_ATTRIBUTES are GNU attributes associated with this declaration.
|
||||||
function, if any; if set, the caller is responsible for calling
|
*PUSHED_SCOPE_P is set to the scope entered in this function, if any; if
|
||||||
pop_scope. */
|
set, the caller is responsible for calling pop_scope. */
|
||||||
|
|
||||||
tree
|
tree
|
||||||
start_decl (const cp_declarator *declarator,
|
start_decl (const cp_declarator *declarator,
|
||||||
|
@ -4034,7 +4034,7 @@ start_decl (const cp_declarator *declarator,
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
case FUNCTION_DECL:
|
case FUNCTION_DECL:
|
||||||
if (initialized == 3)
|
if (initialized == SD_DELETED)
|
||||||
/* We'll handle the rest of the semantics later, but we need to
|
/* We'll handle the rest of the semantics later, but we need to
|
||||||
set this now so it's visible to duplicate_decls. */
|
set this now so it's visible to duplicate_decls. */
|
||||||
DECL_DELETED_FN (decl) = 1;
|
DECL_DELETED_FN (decl) = 1;
|
||||||
|
|
|
@ -3767,6 +3767,12 @@ mark_used (tree decl)
|
||||||
TREE_USED (decl) = 1;
|
TREE_USED (decl) = 1;
|
||||||
if (DECL_CLONED_FUNCTION_P (decl))
|
if (DECL_CLONED_FUNCTION_P (decl))
|
||||||
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
|
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
|
||||||
|
if (TREE_CODE (decl) == FUNCTION_DECL
|
||||||
|
&& DECL_DELETED_FN (decl))
|
||||||
|
{
|
||||||
|
error ("deleted function %q+D", decl);
|
||||||
|
error ("used here");
|
||||||
|
}
|
||||||
/* If we don't need a value, then we don't need to synthesize DECL. */
|
/* If we don't need a value, then we don't need to synthesize DECL. */
|
||||||
if (skip_evaluation)
|
if (skip_evaluation)
|
||||||
return;
|
return;
|
||||||
|
@ -3830,12 +3836,6 @@ mark_used (tree decl)
|
||||||
/* If we've already synthesized the method we don't need to
|
/* If we've already synthesized the method we don't need to
|
||||||
do the instantiation test below. */
|
do the instantiation test below. */
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (decl) == FUNCTION_DECL
|
|
||||||
&& DECL_DELETED_FN (decl))
|
|
||||||
{
|
|
||||||
error ("deleted function %q+D", decl);
|
|
||||||
error ("used here");
|
|
||||||
}
|
|
||||||
else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
|
else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
|
||||||
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
|
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
|
||||||
&& (!DECL_EXPLICIT_INSTANTIATION (decl)
|
&& (!DECL_EXPLICIT_INSTANTIATION (decl)
|
||||||
|
|
|
@ -12610,7 +12610,7 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||||
|| token->type == CPP_OPEN_PAREN
|
|| token->type == CPP_OPEN_PAREN
|
||||||
|| token->type == CPP_OPEN_BRACE)
|
|| token->type == CPP_OPEN_BRACE)
|
||||||
{
|
{
|
||||||
is_initialized = 1;
|
is_initialized = SD_INITIALIZED;
|
||||||
initialization_kind = token->type;
|
initialization_kind = token->type;
|
||||||
|
|
||||||
if (token->type == CPP_EQ
|
if (token->type == CPP_EQ
|
||||||
|
@ -12618,9 +12618,9 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||||
{
|
{
|
||||||
cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
|
cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
|
||||||
if (t2->keyword == RID_DEFAULT)
|
if (t2->keyword == RID_DEFAULT)
|
||||||
is_initialized = 2;
|
is_initialized = SD_DEFAULTED;
|
||||||
else if (t2->keyword == RID_DELETE)
|
else if (t2->keyword == RID_DELETE)
|
||||||
is_initialized = 3;
|
is_initialized = SD_DELETED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -12633,7 +12633,7 @@ cp_parser_init_declarator (cp_parser* parser,
|
||||||
cp_parser_error (parser, "expected initializer");
|
cp_parser_error (parser, "expected initializer");
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
is_initialized = 0;
|
is_initialized = SD_UNINITIALIZED;
|
||||||
initialization_kind = CPP_EOF;
|
initialization_kind = CPP_EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -704,7 +704,8 @@ check_narrowing (tree type, tree init)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
error ("narrowing conversion of %qE to %qT inside { }", init, type);
|
permerror (input_location, "narrowing conversion of %qE to %qT inside { }",
|
||||||
|
init, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process the initializer INIT for a variable of type TYPE, emitting
|
/* Process the initializer INIT for a variable of type TYPE, emitting
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
// PR c++/37208: SFINAE and deleted functions.
|
||||||
|
|
||||||
|
// { dg-options "-std=c++0x" }
|
||||||
|
// { dg-do compile }
|
||||||
|
template<int> struct A { };
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
int& int_if_addable(A<sizeof((*(T*)0) + (*(T*)0))>*);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
float& int_if_addable(...);
|
||||||
|
|
||||||
|
struct X { };
|
||||||
|
|
||||||
|
struct Y { };
|
||||||
|
Y operator+(Y, Y);
|
||||||
|
|
||||||
|
struct Z { };
|
||||||
|
Z operator+(Z, Z) = delete;
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
float& x = int_if_addable<X>(0);
|
||||||
|
int& y = int_if_addable<Y>(0);
|
||||||
|
float& z = int_if_addable<Z>(0);
|
||||||
|
}
|
Loading…
Reference in New Issue