summaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-27 19:31:33 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2010-10-27 19:31:33 +0000
commitca63c29a80eadc10563d1c6d8ce0d4b3884ad930 (patch)
tree935f90ff364485ab5facda1e86039d079df9a040 /gcc/cp/parser.c
parentc99de5410bf4296b7138c0813696e8c19b412902 (diff)
downloadgcc-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.c55
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);