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.c226
1 files changed, 120 insertions, 106 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e27a64d..8b2af9cd 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1128,6 +1128,32 @@ check_redeclaration_exception_specification (tree new_decl,
}
}
+/* Return true if OLD_DECL and NEW_DECL agree on constexprness.
+ Otherwise issue diagnostics. */
+
+static bool
+validate_constexpr_redeclaration (tree old_decl, tree new_decl)
+{
+ old_decl = STRIP_TEMPLATE (old_decl);
+ new_decl = STRIP_TEMPLATE (new_decl);
+ if (!VAR_OR_FUNCTION_DECL_P (old_decl)
+ || !VAR_OR_FUNCTION_DECL_P (new_decl))
+ return true;
+ if (DECL_DECLARED_CONSTEXPR_P (old_decl)
+ == DECL_DECLARED_CONSTEXPR_P (new_decl))
+ return true;
+ if (TREE_CODE (old_decl) == FUNCTION_DECL && DECL_BUILT_IN (old_decl))
+ {
+ /* Hide a built-in declaration. */
+ DECL_DECLARED_CONSTEXPR_P (old_decl)
+ = DECL_DECLARED_CONSTEXPR_P (new_decl);
+ return true;
+ }
+ error ("redeclaration %qD differs in %<constexpr%>", new_decl);
+ error ("from previous declaration %q+D", old_decl);
+ return false;
+}
+
#define GNU_INLINE_P(fn) (DECL_DECLARED_INLINE_P (fn) \
&& lookup_attribute ("gnu_inline", \
DECL_ATTRIBUTES (fn)))
@@ -1607,6 +1633,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
warn about it. */
warn_extern_redeclared_static (newdecl, olddecl);
+ if (!validate_constexpr_redeclaration (olddecl, newdecl))
+ return error_mark_node;
+
/* We have committed to returning 1 at this point. */
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
@@ -4029,7 +4058,7 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
else if (saw_typedef)
warning (0, "%<typedef%> was ignored in this declaration");
else if (declspecs->specs[(int) ds_constexpr])
- error ("%<constexpr> cannot be used for type declarations");
+ error ("%<constexpr%> cannot be used for type declarations");
}
return declared_type;
@@ -4310,9 +4339,6 @@ start_decl (const cp_declarator *declarator,
&& !alias)
permerror (input_location, "declaration of %q#D outside of class is not definition",
decl);
-
- if (!ensure_literal_type_for_constexpr_object (decl))
- return error_mark_node;
}
was_public = TREE_PUBLIC (decl);
@@ -4344,7 +4370,7 @@ start_decl (const cp_declarator *declarator,
/* This is a const variable with implicit 'static'. Set
DECL_THIS_STATIC so we can tell it from variables that are
!TREE_PUBLIC because of the anonymous namespace. */
- gcc_assert (CP_TYPE_CONST_P (TREE_TYPE (decl)));
+ gcc_assert (CP_TYPE_CONST_P (TREE_TYPE (decl)) || errorcount);
DECL_THIS_STATIC (decl) = 1;
}
@@ -4753,14 +4779,10 @@ check_for_uninitialized_const_var (tree decl)
{
tree type = strip_array_types (TREE_TYPE (decl));
- if (TREE_CODE (decl) == VAR_DECL && DECL_DECLARED_CONSTEXPR_P (decl)
- && DECL_INITIAL (decl) == NULL)
- error ("missing initializer for constexpr %qD", decl);
-
/* ``Unless explicitly declared extern, a const object does not have
external linkage and must be initialized. ($8.4; $12.1)'' ARM
7.1.6 */
- else if (TREE_CODE (decl) == VAR_DECL
+ if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
&& (!TYPE_NEEDS_CONSTRUCTING (type)
@@ -5691,6 +5713,12 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
}
}
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ validate_constexpr_fundecl (decl);
+
+ else if (!ensure_literal_type_for_constexpr_object (decl))
+ DECL_DECLARED_CONSTEXPR_P (decl) = 0;
+
if (init && TREE_CODE (decl) == FUNCTION_DECL)
{
tree clone;
@@ -6959,6 +6987,8 @@ grokfndecl (tree ctype,
/* If the declaration was declared inline, mark it as such. */
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
+ if (inlinep & 2)
+ DECL_DECLARED_CONSTEXPR_P (decl) = true;
DECL_EXTERNAL (decl) = 1;
if (quals && TREE_CODE (type) == FUNCTION_TYPE)
@@ -7341,6 +7371,21 @@ build_ptrmem_type (tree class_type, tree member_type)
int
check_static_variable_definition (tree decl, tree type)
{
+ /* If DECL is declared constexpr, we'll do the appropriate checks
+ in check_initializer. */
+ if (DECL_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl))
+ return 0;
+ else if (cxx_dialect >= cxx0x && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
+ {
+ if (literal_type_p (type))
+ error ("%<constexpr%> needed for in-class initialization of static "
+ "data member %q#D of non-integral type", decl);
+ else
+ error ("in-class initialization of static data member %q#D of "
+ "non-literal type", decl);
+ return 1;
+ }
+
/* Motion 10 at San Diego: If a static const integral data member is
initialized with an integral constant expression, the initializer
may appear either in the declaration (within the class), or in
@@ -7352,10 +7397,6 @@ check_static_variable_definition (tree decl, tree type)
error ("invalid in-class initialization of static data member "
"of non-integral type %qT",
type);
- /* If we just return the declaration, crashes will sometimes
- occur. We therefore return void_type_node, as if this were a
- friend declaration, to cause callers to completely ignore
- this declaration. */
return 1;
}
else if (!CP_TYPE_CONST_P (type))
@@ -8046,6 +8087,12 @@ grokdeclarator (const cp_declarator *declarator,
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
+ if (constexpr_p && declspecs->specs[(int)ds_typedef])
+ {
+ error ("%<constexpr%> cannot appear in a typedef declaration");
+ return error_mark_node;
+ }
+
/* If there were multiple types specified in the decl-specifier-seq,
issue an error message. */
if (declspecs->multiple_types_p)
@@ -8299,17 +8346,6 @@ grokdeclarator (const cp_declarator *declarator,
type_quals = TYPE_UNQUALIFIED;
if (declspecs->specs[(int)ds_const])
type_quals |= TYPE_QUAL_CONST;
- /* A `constexpr' specifier used in an object declaration declares
- the object as `const'. */
- if (constexpr_p)
- {
- if (innermost_code == cdk_function)
- ;
- else if (declspecs->specs[(int)ds_const] != 0)
- error ("both %<const%> and %<constexpr%> cannot be used here");
- else
- type_quals |= TYPE_QUAL_CONST;
- }
if (declspecs->specs[(int)ds_volatile])
type_quals |= TYPE_QUAL_VOLATILE;
if (declspecs->specs[(int)ds_restrict])
@@ -8686,21 +8722,6 @@ grokdeclarator (const cp_declarator *declarator,
}
}
- /* It is not allowed to use `constexpr' in a function
- declaration that is not a definition.
- That is too strict, though. */
- if (constexpr_p && !funcdef_flag)
- {
- error ("the %<constexpr%> specifier cannot be used in "
- "a function declaration that is not a definition");
- constexpr_p = false;
- }
-
- /* A constexpr non-static member function is implicitly const. */
- if (constexpr_p && decl_context == FIELD && staticp == 0
- && sfk != sfk_constructor && sfk != sfk_destructor)
- memfn_quals |= TYPE_QUAL_CONST;
-
arg_types = grokparms (declarator->u.function.parameters,
&parms);
@@ -8878,6 +8899,18 @@ grokdeclarator (const cp_declarator *declarator,
}
}
+ /* A `constexpr' specifier used in an object declaration declares
+ the object as `const'. */
+ if (constexpr_p && innermost_code != cdk_function)
+ {
+ if (type_quals & TYPE_QUAL_CONST)
+ error ("both %<const%> and %<constexpr%> cannot be used here");
+ if (type_quals & TYPE_QUAL_VOLATILE)
+ error ("both %<volatile%> and %<constexpr%> cannot be used here");
+ type_quals |= TYPE_QUAL_CONST;
+ type = cp_build_qualified_type (type, type_quals);
+ }
+
if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
&& TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE)
@@ -8964,8 +8997,6 @@ grokdeclarator (const cp_declarator *declarator,
return error_mark_node;
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- tree sname = declarator->u.id.unqualified_name;
-
if (current_class_type
&& (!friendp || funcdef_flag))
{
@@ -8975,20 +9006,6 @@ grokdeclarator (const cp_declarator *declarator,
ctype, name, current_class_type);
return error_mark_node;
}
-
- /* It is not permitted to define a member function outside ist
- membership class as `constexpr'. */
- if (constexpr_p)
- error ("a constexpr function cannot be defined "
- "outside of its class");
-
- if (TREE_CODE (sname) == IDENTIFIER_NODE
- && NEW_DELETE_OPNAME_P (sname))
- /* Overloaded operator new and operator delete
- are always static functions. */
- ;
- else
- type = build_memfn_type (type, ctype, memfn_quals);
}
else if (declspecs->specs[(int)ds_typedef]
&& current_class_type)
@@ -8999,6 +9016,15 @@ grokdeclarator (const cp_declarator *declarator,
}
}
+ if (ctype == NULL_TREE && decl_context == FIELD && friendp == 0)
+ ctype = current_class_type;
+
+ /* A constexpr non-static member function is implicitly const. */
+ if (constexpr_p && ctype && staticp == 0
+ && TREE_CODE (type) == FUNCTION_TYPE
+ && sfk != sfk_constructor && sfk != sfk_destructor)
+ memfn_quals |= TYPE_QUAL_CONST;
+
/* Now TYPE has the actual type. */
if (returned_attrs)
@@ -9362,6 +9388,10 @@ grokdeclarator (const cp_declarator *declarator,
type = build_pointer_type (type);
}
+ if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
+ && !NEW_DELETE_OPNAME_P (unqualified_id))
+ type = build_memfn_type (type, ctype, memfn_quals);
+
{
tree decl;
@@ -9395,22 +9425,15 @@ grokdeclarator (const cp_declarator *declarator,
error ("invalid use of %<::%>");
return error_mark_node;
}
- else if (TREE_CODE (type) == FUNCTION_TYPE)
+ else if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
{
int publicp = 0;
tree function_context;
if (friendp == 0)
{
- if (ctype == NULL_TREE)
- ctype = current_class_type;
-
- if (ctype == NULL_TREE)
- {
- error ("can't make %qD into a method -- not in a class",
- unqualified_id);
- return error_mark_node;
- }
+ gcc_assert (ctype);
/* ``A union may [ ... ] not [ have ] virtual functions.''
ARM 9.5 */
@@ -9431,8 +9454,6 @@ grokdeclarator (const cp_declarator *declarator,
virtualp = 0;
}
}
- else if (staticp < 2)
- type = build_memfn_type (type, ctype, memfn_quals);
}
/* Check that the name used for a destructor makes sense. */
@@ -9455,9 +9476,12 @@ grokdeclarator (const cp_declarator *declarator,
return error_mark_node;
}
if (constexpr_p)
- error ("a destructor cannot be %<constexpr%>");
+ {
+ error ("a destructor cannot be %<constexpr%>");
+ return error_mark_node;
+ }
}
- else if (sfk == sfk_constructor && friendp)
+ else if (sfk == sfk_constructor && friendp && !ctype)
{
error ("expected qualified name in friend declaration "
"for constructor %qD",
@@ -9477,7 +9501,7 @@ grokdeclarator (const cp_declarator *declarator,
unqualified_id,
virtualp, flags, memfn_quals, raises,
friendp ? -1 : 0, friendp, publicp,
- inlinep || constexpr_p,
+ inlinep | (2 * constexpr_p),
sfk,
funcdef_flag, template_count, in_namespace,
attrlist, declarator->id_loc);
@@ -9499,25 +9523,6 @@ grokdeclarator (const cp_declarator *declarator,
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
}
- else if (TREE_CODE (type) == METHOD_TYPE)
- {
- /* We only get here for friend declarations of
- members of other classes. */
- /* All method decls are public, so tell grokfndecl to set
- TREE_PUBLIC, also. */
- decl = grokfndecl (ctype, type,
- TREE_CODE (unqualified_id) != TEMPLATE_ID_EXPR
- ? unqualified_id : dname,
- parms,
- unqualified_id,
- virtualp, flags, memfn_quals, raises,
- friendp ? -1 : 0, friendp, 1, 0, sfk,
- funcdef_flag, template_count, in_namespace,
- attrlist,
- declarator->id_loc);
- if (decl == NULL_TREE)
- return error_mark_node;
- }
else if (!staticp && !dependent_type_p (type)
&& !COMPLETE_TYPE_P (complete_type (type))
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
@@ -9596,15 +9601,25 @@ grokdeclarator (const cp_declarator *declarator,
the rest of the compiler does not correctly
handle the initialization unless the member is
static so we make it static below. */
- permerror (input_location, "ISO C++ forbids initialization of member %qD",
- unqualified_id);
- permerror (input_location, "making %qD static", unqualified_id);
- staticp = 1;
+ if (cxx_dialect >= cxx0x)
+ {
+ sorry ("non-static data member initializers");
+ }
+ else
+ {
+ permerror (input_location, "ISO C++ forbids initialization of member %qD",
+ unqualified_id);
+ permerror (input_location, "making %qD static", unqualified_id);
+ staticp = 1;
+ }
}
if (uses_template_parms (type))
/* We'll check at instantiation time. */
;
+ else if (constexpr_p)
+ /* constexpr has the same requirements. */
+ ;
else if (check_static_variable_definition (unqualified_id,
type))
/* If we just return the declaration, crashes
@@ -9714,11 +9729,6 @@ grokdeclarator (const cp_declarator *declarator,
sfk = sfk_none;
}
}
- else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
- && !NEW_DELETE_OPNAME_P (original_name))
- type = build_method_type_directly (ctype,
- TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
/* Record presence of `static'. */
publicp = (ctype != NULL_TREE
@@ -9728,7 +9738,8 @@ grokdeclarator (const cp_declarator *declarator,
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, memfn_quals, raises,
1, friendp,
- publicp, inlinep || constexpr_p, sfk, funcdef_flag,
+ publicp, inlinep | (2 * constexpr_p), sfk,
+ funcdef_flag,
template_count, in_namespace, attrlist,
declarator->id_loc);
if (decl == NULL_TREE)
@@ -9797,6 +9808,9 @@ grokdeclarator (const cp_declarator *declarator,
storage_class = sc_none;
}
}
+ else if (constexpr_p && DECL_EXTERNAL (decl))
+ error ("declaration of constexpr variable %qD is not a definition",
+ decl);
}
if (storage_class == sc_extern && initialized && !funcdef_flag)
@@ -9826,8 +9840,8 @@ grokdeclarator (const cp_declarator *declarator,
DECL_THIS_STATIC (decl) = 1;
/* Don't forget constexprness. */
- if (VAR_OR_FUNCTION_DECL_P (decl))
- DECL_DECLARED_CONSTEXPR_P (decl) = constexpr_p;
+ if (constexpr_p)
+ DECL_DECLARED_CONSTEXPR_P (decl) = true;
/* Record constancy and volatility on the DECL itself . There's
no need to do this when processing a template; we'll do this
@@ -11863,10 +11877,6 @@ check_function_type (tree decl, tree current_function_parms)
/* In a function definition, arg types must be complete. */
require_complete_types_for_parms (current_function_parms);
- /* constexpr functions must have literal argument types and
- literal return type. */
- validate_constexpr_fundecl (decl);
-
if (dependent_type_p (return_type))
return;
if (!COMPLETE_OR_VOID_TYPE_P (return_type)
@@ -12126,6 +12136,10 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
maybe_apply_pragma_weak (decl1);
}
+ /* constexpr functions must have literal argument types and
+ literal return type. */
+ validate_constexpr_fundecl (decl1);
+
/* Reset this in case the call to pushdecl changed it. */
current_function_decl = decl1;