* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139926
138bc75d-0d04-0410-961f-
82ee72b054a4
+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.
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.
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
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 {
/* 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) \
#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. */
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,
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;
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;
/* 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)
|| 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
{
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
cp_parser_error (parser, "expected initializer");
return error_mark_node;
}
- is_initialized = 0;
+ is_initialized = SD_UNINITIALIZED;
initialization_kind = CPP_EOF;
}
}
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
--- /dev/null
+// 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);
+}