diff options
author | Jason Merrill <jason@redhat.com> | 2008-09-03 00:10:27 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2008-09-03 00:10:27 -0400 |
commit | 4ad610c9785f0022e5ebe686650abaa7ff3c2d5c (patch) | |
tree | 593d0e7109cbda785c4e54b5d01f619e24dea375 /gcc | |
parent | a63068b6dd49f620e85c95f1dfed8f7d7473e17c (diff) | |
download | gcc-4ad610c9785f0022e5ebe686650abaa7ff3c2d5c.zip gcc-4ad610c9785f0022e5ebe686650abaa7ff3c2d5c.tar.gz gcc-4ad610c9785f0022e5ebe686650abaa7ff3c2d5c.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cp/call.c | 4 | ||||
-rw-r--r-- | gcc/cp/class.c | 4 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 12 | ||||
-rw-r--r-- | gcc/cp/decl.c | 18 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 12 | ||||
-rw-r--r-- | gcc/cp/parser.c | 8 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/defaulted4.C | 26 |
9 files changed, 84 insertions, 23 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c5ccb40..88b3946 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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> * typeck.c (build_array_ref): Use new location argument. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 571f36f..653e06e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5119,6 +5119,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) 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 FN is a template function, two cases must be considered. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4f69c7e..ab8391b 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6185,6 +6185,10 @@ resolve_address_of_overloaded_function (tree target_type, function will be marked as used at this point. */ if (!(flags & tf_conv)) { + /* Make =delete work with SFINAE. */ + if (DECL_DELETED_FN (fn) && !(flags & tf_error)) + return error_mark_node; + mark_used (fn); /* We could not check access when this expression was originally created since we did not know at that time to which function diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 09b3b2f..a668aa0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1629,7 +1629,7 @@ struct lang_decl_flags GTY(()) unsigned this_thunk_p : 1; unsigned repo_available_p : 1; unsigned hidden_friend_p : 1; - unsigned threadprivate_p : 1; + unsigned threadprivate_or_deleted_p : 1; unsigned defaulted_p : 1; 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 #pragma omp threadprivate. */ #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'. */ #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'. */ #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 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 is derived from TYPE1, or if TYPE2 is a pointer (reference) to a class derived from the type pointed to (referred to) by TYPE1. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0d735c4..0f7b5d7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3969,14 +3969,14 @@ groktypename (cp_decl_specifier_seq *type_specifiers, grokfield.) The DECL corresponding to the DECLARATOR is returned. If an error occurs, the error_mark_node is returned instead. - DECLSPECS are the decl-specifiers for the declaration. INITIALIZED is 1 - if an explicit initializer is present, or 2 for an explicitly defaulted - function, or 3 for an explicitly deleted function, but 0 if this is a - variable implicitly initialized via a default constructor. ATTRIBUTES - and PREFIX_ATTRIBUTES are GNU attributes associated with this - declaration. *PUSHED_SCOPE_P is set to the scope entered in this - function, if any; if set, the caller is responsible for calling - pop_scope. */ + DECLSPECS are the decl-specifiers for the declaration. INITIALIZED is + SD_INITIALIZED if an explicit initializer is present, or SD_DEFAULTED + for an explicitly defaulted function, or SD_DELETED for an explicitly + deleted function, but 0 (SD_UNINITIALIZED) if this is a variable + implicitly initialized via a default constructor. ATTRIBUTES and + PREFIX_ATTRIBUTES are GNU attributes associated with this declaration. + *PUSHED_SCOPE_P is set to the scope entered in this function, if any; if + set, the caller is responsible for calling pop_scope. */ tree start_decl (const cp_declarator *declarator, @@ -4034,7 +4034,7 @@ start_decl (const cp_declarator *declarator, return error_mark_node; case FUNCTION_DECL: - if (initialized == 3) + if (initialized == SD_DELETED) /* We'll handle the rest of the semantics later, but we need to set this now so it's visible to duplicate_decls. */ DECL_DELETED_FN (decl) = 1; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0e56c07..4f19766 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3767,6 +3767,12 @@ mark_used (tree decl) TREE_USED (decl) = 1; if (DECL_CLONED_FUNCTION_P (decl)) 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 (skip_evaluation) return; @@ -3830,12 +3836,6 @@ mark_used (tree decl) /* If we've already synthesized the method we don't need to 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) && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) && (!DECL_EXPLICIT_INSTANTIATION (decl) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4549f8f..32907b2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -12610,7 +12610,7 @@ cp_parser_init_declarator (cp_parser* parser, || token->type == CPP_OPEN_PAREN || token->type == CPP_OPEN_BRACE) { - is_initialized = 1; + is_initialized = SD_INITIALIZED; initialization_kind = token->type; 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); if (t2->keyword == RID_DEFAULT) - is_initialized = 2; + is_initialized = SD_DEFAULTED; else if (t2->keyword == RID_DELETE) - is_initialized = 3; + is_initialized = SD_DELETED; } } else @@ -12633,7 +12633,7 @@ cp_parser_init_declarator (cp_parser* parser, cp_parser_error (parser, "expected initializer"); return error_mark_node; } - is_initialized = 0; + is_initialized = SD_UNINITIALIZED; initialization_kind = CPP_EOF; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 24d003f..bf0ff6b 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -704,7 +704,8 @@ check_narrowing (tree type, tree init) } 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 diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted4.C b/gcc/testsuite/g++.dg/cpp0x/defaulted4.C new file mode 100644 index 0000000..5605384 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted4.C @@ -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); +} |