aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c150
1 files changed, 90 insertions, 60 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c9d1d96..8585288 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -178,6 +178,8 @@ static tree start_cleanup_fn PARAMS ((void));
static void end_cleanup_fn PARAMS ((void));
static tree cp_make_fname_decl PARAMS ((tree, const char *, int));
static void initialize_predefined_identifiers PARAMS ((void));
+static tree check_special_function_return_type
+ PARAMS ((special_function_kind, tree, tree, tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PARAMS ((void));
@@ -9298,6 +9300,54 @@ create_array_type_for_decl (name, type, size)
return build_cplus_array_type (type, itype);
}
+/* Check that it's OK to declare a function with the indicated TYPE.
+ SFK indicates the kind of special function (if any) that this
+ function is. CTYPE is the class of which this function is a
+ member. OPTYPE is the type given in a conversion operator
+ declaration. Returns the actual return type of the function; that
+ may be different than TYPE if an error occurs, or for certain
+ special functions. */
+
+static tree
+check_special_function_return_type (sfk, type, ctype, optype)
+ special_function_kind sfk;
+ tree type;
+ tree ctype;
+ tree optype;
+{
+ switch (sfk)
+ {
+ case sfk_constructor:
+ if (type)
+ cp_error ("return type specification for constructor invalid");
+
+ /* In the old ABI, we return `this'; in the new ABI we don't
+ bother. */
+ type = flag_new_abi ? void_type_node : build_pointer_type (ctype);
+ break;
+
+ case sfk_destructor:
+ if (type)
+ cp_error ("return type specification for destructor invalid");
+ type = void_type_node;
+ break;
+
+ case sfk_conversion:
+ if (type && !same_type_p (type, optype))
+ cp_error ("operator `%T' declared to return `%T'", optype, type);
+ else if (type)
+ cp_pedwarn ("return type specified for `operator %T'", optype);
+ type = optype;
+ break;
+
+ default:
+ my_friendly_abort (20000408);
+ break;
+ }
+
+ return type;
+}
+
/* Given declspecs and a declarator,
determine the name and type of the object declared
and construct a ..._DECL node for it.
@@ -9358,8 +9408,6 @@ create_array_type_for_decl (name, type, size)
May return void_type_node if the declarator turned out to be a friend.
See grokfield for details. */
-enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
-
tree
grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree declspecs;
@@ -9398,7 +9446,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Keep track of what sort of function is being processed
so that we can warn about default return values, or explicit
return values which do not match prescribed defaults. */
- enum return_types return_type = return_normal;
+ special_function_kind sfk = sfk_none;
tree dname = NULL_TREE;
tree ctype = current_class_type;
@@ -9448,7 +9496,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
my_friendly_assert (flags == NO_SPECIAL, 152);
flags = DTOR_FLAG;
- return_type = return_dtor;
+ sfk = sfk_destructor;
if (TREE_CODE (name) == TYPE_DECL)
TREE_OPERAND (decl, 0) = name = constructor_name (name);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
@@ -9547,7 +9595,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& decl != NULL_TREE && flags != DTOR_FLAG
&& decl == constructor_name (ctype))
{
- return_type = return_ctor;
+ sfk = sfk_constructor;
ctor_return_type = ctype;
}
ctype = NULL_TREE;
@@ -9595,7 +9643,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname);
- return_type = return_conversion;
+ sfk = sfk_conversion;
}
name = operator_name_string (dname);
}
@@ -9659,7 +9707,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (decl) == IDENTIFIER_NODE
&& constructor_name (ctype) == decl)
{
- return_type = return_ctor;
+ sfk = sfk_constructor;
ctor_return_type = ctype;
}
else if (TREE_CODE (decl) == BIT_NOT_EXPR
@@ -9667,7 +9715,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& (constructor_name (ctype) == TREE_OPERAND (decl, 0)
|| constructor_name_full (ctype) == TREE_OPERAND (decl, 0)))
{
- return_type = return_dtor;
+ sfk = sfk_destructor;
ctor_return_type = ctype;
flags = DTOR_FLAG;
TREE_OPERAND (decl, 0) = constructor_name (ctype);
@@ -9883,58 +9931,35 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
defaulted_int = 1;
}
- if (type == NULL_TREE)
+ if (sfk != sfk_none)
+ type = check_special_function_return_type (sfk, type,
+ ctor_return_type,
+ ctor_return_type);
+ else if (type == NULL_TREE)
{
+ int is_main;
+
explicit_int = -1;
- if (return_type == return_dtor)
- type = void_type_node;
- else if (return_type == return_ctor)
- type = build_pointer_type (ctor_return_type);
- else if (return_type == return_conversion)
- type = ctor_return_type;
- else
- {
+
/* We handle `main' specially here, because 'main () { }' is so
common. With no options, it is allowed. With -Wreturn-type,
it is a warning. It is only an error with -pedantic-errors. */
- int is_main = (funcdef_flag
- && MAIN_NAME_P (dname)
- && ctype == NULL_TREE
- && in_namespace == NULL_TREE
- && current_namespace == global_namespace);
-
- if (in_system_header || flag_ms_extensions)
- /* Allow it, sigh. */;
- else if (pedantic || ! is_main)
- cp_pedwarn ("ISO C++ forbids declaration of `%s' with no type",
- name);
- else if (warn_return_type)
- cp_warning ("ISO C++ forbids declaration of `%s' with no type",
- name);
+ is_main = (funcdef_flag
+ && MAIN_NAME_P (dname)
+ && ctype == NULL_TREE
+ && in_namespace == NULL_TREE
+ && current_namespace == global_namespace);
+
+ if (in_system_header || flag_ms_extensions)
+ /* Allow it, sigh. */;
+ else if (pedantic || ! is_main)
+ cp_pedwarn ("ISO C++ forbids declaration of `%s' with no type",
+ name);
+ else if (warn_return_type)
+ cp_warning ("ISO C++ forbids declaration of `%s' with no type",
+ name);
- type = integer_type_node;
- }
- }
- else if (return_type == return_dtor)
- {
- error ("return type specification for destructor invalid");
- type = void_type_node;
- }
- else if (return_type == return_ctor)
- {
- error ("return type specification for constructor invalid");
- type = build_pointer_type (ctor_return_type);
- }
- else if (return_type == return_conversion)
- {
- if (!same_type_p (type, ctor_return_type))
- cp_error ("operator `%T' declared to return `%T'",
- ctor_return_type, type);
- else
- cp_pedwarn ("return type specified for `operator %T'",
- ctor_return_type);
-
- type = ctor_return_type;
+ type = integer_type_node;
}
ctype = NULL_TREE;
@@ -10079,7 +10104,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = build_complex_type (type);
}
- if (return_type == return_conversion
+ if (sfk == sfk_conversion
&& (RIDBIT_SETP (RID_CONST, specbits)
|| RIDBIT_SETP (RID_VOLATILE, specbits)
|| RIDBIT_SETP (RID_RESTRICT, specbits)))
@@ -10376,7 +10401,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& (friendp == 0 || dname == current_class_name))
ctype = current_class_type;
- if (ctype && return_type == return_conversion)
+ if (ctype && sfk == sfk_conversion)
TYPE_HAS_CONVERSION (ctype) = 1;
if (ctype && constructor_name (ctype) == dname)
{
@@ -10435,7 +10460,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (RIDBIT_ANY_SET (tmp_bits))
error ("return value type specifier for constructor ignored");
}
- type = build_pointer_type (ctype);
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
@@ -10443,7 +10467,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
flags))
return void_type_node;
TYPE_HAS_CONSTRUCTOR (ctype) = 1;
- if (return_type != return_ctor)
+ if (sfk != sfk_constructor)
return NULL_TREE;
}
}
@@ -13532,7 +13556,12 @@ start_function (declspecs, declarator, attrs, flags)
dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
DECL_CONTEXT (dtor_label) = current_function_decl;
}
- else if (DECL_CONSTRUCTOR_P (decl1))
+ /* Under the old ABI we return `this' from constructors, so we make
+ ordinary `return' statements in constructors jump to CTOR_LABEL;
+ from there we return `this'. Under the new ABI, we don't bother
+ with any of this. By not setting CTOR_LABEL the remainder of the
+ machinery is automatically disabled. */
+ else if (!flag_new_abi && DECL_CONSTRUCTOR_P (decl1))
{
ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
DECL_CONTEXT (ctor_label) = current_function_decl;
@@ -13764,7 +13793,8 @@ static void
finish_constructor_body ()
{
/* Any return from a constructor will end up here. */
- add_tree (build_min_nt (LABEL_STMT, ctor_label));
+ if (ctor_label)
+ add_tree (build_min_nt (LABEL_STMT, ctor_label));
/* Clear CTOR_LABEL so that finish_return_stmt knows to really
generate the return, rather than a goto to CTOR_LABEL. */