diff options
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 226 |
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; |