diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-10-27 19:31:33 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-10-27 19:31:33 +0000 |
commit | ca63c29a80eadc10563d1c6d8ce0d4b3884ad930 (patch) | |
tree | 935f90ff364485ab5facda1e86039d079df9a040 /gcc/cp/parser.c | |
parent | c99de5410bf4296b7138c0813696e8c19b412902 (diff) | |
download | gcc-ca63c29a80eadc10563d1c6d8ce0d4b3884ad930.tar.gz |
* parser.c (cp_parser_ctor_initializer_opt_and_function_body):
Make sure a constexpr ctor has an empty body.
* class.c (type_has_constexpr_default_constructor): New.
* cp-tree.h: Declare it.
* init.c (perform_member_init): Complain about uninitialized
member in constexpr ctor.
(emit_mem_initializers): And uninitialized base.
* decl.c (check_tag_decl): Fix typo.
* semantics.c (valid_type_in_constexpr_fundecl_p): New fn.
(is_valid_constexpr_fn): New fn.
(validate_constexpr_fundecl): Use it.
* decl.c (validate_constexpr_redeclaration): New.
(duplicate_decls): Use it.
(cp_finish_decl): Call validate_constexpr_fundecl and
ensure_literal_type_for_constexpr_object here.
(start_decl): Not here. Don't ICE on constexpr reference.
(check_for_uninitialized_const_var): Don't handle constexpr specially.
(grokfndecl): Set DECL_DECLARED_CONSTEXPR_P.
(check_static_variable_definition): Give friendly message about
missing constexpr.
(grokdeclarator): Complain about typedef and volatile with constexpr.
Reorganize. Give sorry about non-static data members in C++0x mode.
(start_preparsed_function): Check validate_constexpr_fundecl here.
(check_function_type): Not here.
* decl2.c (finish_static_data_member_decl): Don't complain about
in-class init.
* parser.c (CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR): New.
(cp_parser_condition): Pass it to cp_parser_decl_specifier_seq.
(cp_parser_decl_specifier_seq): Handle it.
(cp_parser_explicit_instantiation): Diagnose inline and constexpr.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166013 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d0bd6bb5e0b..0d28345034c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1334,7 +1334,10 @@ enum CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2, /* When parsing a type-specifier, do not try to parse a class-specifier or enum-specifier. */ - CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4 + CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4, + /* When parsing a decl-specifier-seq, only allow type-specifier or + constexpr. */ + CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8 }; /* This type is used for parameters and variables which hold @@ -8509,6 +8512,7 @@ cp_parser_condition (cp_parser* parser) { cp_decl_specifier_seq type_specifiers; const char *saved_message; + int declares_class_or_enum; /* Try the declaration first. */ cp_parser_parse_tentatively (parser); @@ -8518,9 +8522,10 @@ cp_parser_condition (cp_parser* parser) parser->type_definition_forbidden_message = G_("types may not be defined in conditions"); /* Parse the type-specifier-seq. */ - cp_parser_type_specifier_seq (parser, /*is_declaration==*/true, - /*is_trailing_return=*/false, - &type_specifiers); + cp_parser_decl_specifier_seq (parser, + CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR, + &type_specifiers, + &declares_class_or_enum); /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; /* If all is well, we might be looking at a declaration. */ @@ -9851,6 +9856,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser, break; } + if (found_decl_spec + && (flags & CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR) + && token->keyword != RID_CONSTEXPR) + error ("decl-specifier invalid in condition"); + /* Constructors are a special case. The `S' in `S()' is not a decl-specifier; it is the beginning of the declarator. */ constructor_p @@ -12231,6 +12241,13 @@ cp_parser_explicit_instantiation (cp_parser* parser) decl_specifiers.type_location); if (declarator != cp_error_declarator) { + if (decl_specifiers.specs[(int)ds_inline]) + permerror (input_location, "explicit instantiation shall not use" + " %<inline%> specifier"); + if (decl_specifiers.specs[(int)ds_constexpr]) + permerror (input_location, "explicit instantiation shall not use" + " %<constexpr%> specifier"); + decl = grokdeclarator (declarator, &decl_specifiers, NORMAL, 0, &decl_specifiers.attributes); /* Turn access control back on for names used during @@ -16245,15 +16262,43 @@ cp_parser_function_body (cp_parser *parser) static bool cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser) { - tree body; + tree body, list; bool ctor_initializer_p; + const bool check_body_p = + DECL_CONSTRUCTOR_P (current_function_decl) + && DECL_DECLARED_CONSTEXPR_P (current_function_decl); + tree last = NULL; /* Begin the function body. */ body = begin_function_body (); /* Parse the optional ctor-initializer. */ ctor_initializer_p = cp_parser_ctor_initializer_opt (parser); + + /* If we're parsing a constexpr constructor definition, we need + to check that the constructor body is indeed empty. However, + before we get to cp_parser_function_body lot of junk has been + generated, so we can't just check that we have an empty block. + Rather we take a snapshot of the outermost block, and check whether + cp_parser_function_body changed its state. */ + if (check_body_p) + { + list = body; + if (TREE_CODE (list) == BIND_EXPR) + list = BIND_EXPR_BODY (list); + if (TREE_CODE (list) == STATEMENT_LIST + && STATEMENT_LIST_TAIL (list) != NULL) + last = STATEMENT_LIST_TAIL (list)->stmt; + } /* Parse the function-body. */ cp_parser_function_body (parser); + if (check_body_p + && (TREE_CODE (list) != STATEMENT_LIST + || (last == NULL && STATEMENT_LIST_TAIL (list) != NULL) + || (last != NULL && last != STATEMENT_LIST_TAIL (list)->stmt))) + { + error ("constexpr constructor does not have empty body"); + DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false; + } /* Finish the function body. */ finish_function_body (body); |