This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Preliminary support constexpr
- From: Gabriel Dos Reis <gdr at cs dot tamu dot edu>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 01 Oct 2009 00:19:42 -0500
- Subject: Preliminary support constexpr
Jason reviewed and approved this patch late in the evening.
This is a preliminary support for constexpr. Compile-time evaluation
of function calls is not supported in this patch; that is the subject of
the follow up patch.
Bootstrapped on an x86_64-suse-linux.
Applied to trunk.
gcc/
2009-09-30 Gabriel Dos Reis <gdr@cs.tamu.edu>
* tree.h (tree_decl_common::lang_flag_8): New.
* c-common.c (c_common_reswords): Include "constexpr" as C++0x
keyword.
* c-common.h (RID_CONSTEXPR): New.
gcc/cp/
2009-09-30 Gabriel Dos Reis <gdr@cs.tamu.edu>
* decl.c (check_for_uninitialized_const_var): Check constexpr
variables too.
(build_ptrmemfunc_type): Make the result a literal type.
(build_ptrmem_type): Likewise.
(grokdeclarator): Handle `constexpr'.
(check_tag_decl): Reject `constexpr'.
(check_function_type): Check constexpr functions.
* cp-tree.h (ds_constexpr): New cp_decl_spec enumerator.
(CLASSTYPE_LITERAL_P): New.
(lang_type_class::is_literal): New.
(lang_type_class::dummy): Adjust width.
(literal_type_p): Declare.
* parser.c (cp_parser_check_decl_spec): Print it.
(cp_parser_decl_specifier_seq): Accept "constexpr".
* semantics.c (validate_constexpr_fundecl): Define.
(literal_type_p): Define.
*** gcc/c-common.c (revision 152384)
--- gcc/c-common.c (local)
*************** const struct c_common_resword c_common_r
*** 631,636 ****
--- 631,637 ----
{ "char32_t", RID_CHAR32, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN },
{ "const", RID_CONST, 0 },
+ { "constexpr", RID_CONSTEXPR, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "const_cast", RID_CONSTCAST, D_CXXONLY | D_CXXWARN },
{ "continue", RID_CONTINUE, 0 },
{ "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX0X | D_CXXWARN },
*** gcc/c-common.h (revision 152384)
--- gcc/c-common.h (local)
*************** enum rid
*** 114,120 ****
RID_IS_UNION,
/* C++0x */
! RID_STATIC_ASSERT, RID_DECLTYPE,
/* Objective-C */
RID_AT_ENCODE, RID_AT_END,
--- 114,120 ----
RID_IS_UNION,
/* C++0x */
! RID_STATIC_ASSERT, RID_CONSTEXPR, RID_DECLTYPE,
/* Objective-C */
RID_AT_ENCODE, RID_AT_END,
*** gcc/cp/cp-tree.h (revision 152384)
--- gcc/cp/cp-tree.h (local)
*************** framework extensions, you must include t
*** 112,122 ****
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
TYPE_MARKED_P (in _TYPE)
Usage of TYPE_LANG_FLAG_?:
0: TYPE_DEPENDENT_P
1: TYPE_HAS_USER_CONSTRUCTOR.
! 2: Unused
3: TYPE_FOR_JAVA.
4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE)
--- 112,124 ----
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
TYPE_MARKED_P (in _TYPE)
+ 7: DECL_DEAD_FOR_LOCAL (in VAR_DECL)
+ 8: DECL_DECLARED_CONSTEXPR_P (in VAR_DECL, FUNCTION_DECL)
Usage of TYPE_LANG_FLAG_?:
0: TYPE_DEPENDENT_P
1: TYPE_HAS_USER_CONSTRUCTOR.
! 2: unused
3: TYPE_FOR_JAVA.
4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE)
*************** struct GTY(()) lang_type_class {
*** 1211,1216 ****
--- 1213,1219 ----
unsigned has_list_ctor : 1;
unsigned non_std_layout : 1;
unsigned lazy_move_ctor : 1;
+ unsigned is_literal : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
*************** struct GTY(()) lang_type_class {
*** 1219,1225 ****
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
! unsigned dummy : 8;
tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices;
--- 1222,1228 ----
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
! unsigned dummy : 7;
tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices;
*************** struct GTY(()) lang_decl {
*** 2189,2194 ****
--- 2192,2201 ----
#define DECL_REPO_AVAILABLE_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.base.repo_available_p)
+ /* True if DECL is declared 'constexpr'. */
+ #define DECL_DECLARED_CONSTEXPR_P(DECL) \
+ DECL_LANG_FLAG_8 (VAR_OR_FUNCTION_DECL_CHECK (DECL))
+
/* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
template function. */
#define DECL_PRETTY_FUNCTION_P(NODE) \
*************** more_aggr_init_expr_args_p (const aggr_i
*** 2846,2851 ****
--- 2853,2862 ----
#define INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P(TYPE) \
(UNSCOPED_ENUM_P (TYPE) || CP_INTEGRAL_TYPE_P (TYPE))
+ /* True if the class type TYPE is a literal type. */
+ #define CLASSTYPE_LITERAL_P(TYPE) \
+ (LANG_TYPE_CLASS_CHECK (TYPE)->is_literal)
+
/* [basic.fundamental]
Integral and floating types are collectively called arithmetic
*************** typedef enum cp_decl_spec {
*** 4190,4195 ****
--- 4201,4207 ----
ds_explicit,
ds_friend,
ds_typedef,
+ ds_constexpr,
ds_complex,
ds_thread,
ds_last
*************** extern tree begin_handler (void);
*** 4937,4942 ****
--- 4949,4957 ----
extern void finish_handler_parms (tree, tree);
extern void finish_handler (tree);
extern void finish_cleanup (tree, tree);
+ extern bool literal_type_p (tree);
+ extern tree validate_constexpr_fundecl (tree);
+ extern tree ensure_literal_type_for_constexpr_object (tree);
enum {
BCS_NO_SCOPE = 1,
*** gcc/cp/decl.c (revision 152384)
--- gcc/cp/decl.c (local)
*************** record_builtin_java_type (const char* na
*** 3231,3237 ****
}
else
{ /* "__java_float" or ""__java_double". */
! type = make_node (REAL_TYPE);
TYPE_PRECISION (type) = - size;
layout_type (type);
}
--- 3231,3237 ----
}
else
{ /* "__java_float" or ""__java_double". */
! type = cxx_make_type (REAL_TYPE);
TYPE_PRECISION (type) = - size;
layout_type (type);
}
*************** cxx_init_decl_processing (void)
*** 3397,3403 ****
/* C++ extensions */
! unknown_type_node = make_node (UNKNOWN_TYPE);
record_unknown_type (unknown_type_node, "unknown type");
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
--- 3397,3403 ----
/* C++ extensions */
! unknown_type_node = cxx_make_type (UNKNOWN_TYPE);
record_unknown_type (unknown_type_node, "unknown type");
/* Indirecting an UNKNOWN_TYPE node yields an UNKNOWN_TYPE node. */
*************** cxx_init_decl_processing (void)
*** 3408,3420 ****
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
! init_list_type_node = make_node (UNKNOWN_TYPE);
record_unknown_type (init_list_type_node, "init list");
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
! tree vfunc_type = make_node (FUNCTION_TYPE);
TREE_TYPE (vfunc_type) = integer_type_node;
TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
layout_type (vfunc_type);
--- 3408,3420 ----
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
! init_list_type_node = cxx_make_type (UNKNOWN_TYPE);
record_unknown_type (init_list_type_node, "init list");
{
/* Make sure we get a unique function type, so we can give
its pointer type a name. (This wins for gdb.) */
! tree vfunc_type = cxx_make_type (FUNCTION_TYPE);
TREE_TYPE (vfunc_type) = integer_type_node;
TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
layout_type (vfunc_type);
*************** cxx_init_decl_processing (void)
*** 3436,3442 ****
abi_node = current_namespace;
pop_namespace ();
! global_type_node = make_node (LANG_TYPE);
record_unknown_type (global_type_node, "global type");
/* Now, C++. */
--- 3436,3442 ----
abi_node = current_namespace;
pop_namespace ();
! global_type_node = cxx_make_type (LANG_TYPE);
record_unknown_type (global_type_node, "global type");
/* Now, C++. */
*************** check_tag_decl (cp_decl_specifier_seq *d
*** 3939,3944 ****
--- 3939,3946 ----
"and functions");
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");
}
return declared_type;
*************** start_decl (const cp_declarator *declara
*** 4181,4186 ****
--- 4183,4191 ----
error ("duplicate initialization of %qD", decl);
if (duplicate_decls (decl, field, /*newdecl_is_friend=*/false))
decl = field;
+ if (declspecs->specs[(int) ds_constexpr]
+ && !DECL_DECLARED_CONSTEXPR_P (field))
+ error ("%qD declared %<constexpr%> outside its class", field);
}
}
else
*************** start_decl (const cp_declarator *declara
*** 4219,4224 ****
--- 4224,4232 ----
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
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);
*************** check_for_uninitialized_const_var (tree
*** 4660,4669 ****
{
tree type = TREE_TYPE (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 */
! if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
--- 4668,4681 ----
{
tree type = 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
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
*************** grokdeclarator (const cp_declarator *dec
*** 7590,7595 ****
--- 7602,7608 ----
bool type_was_error_mark_node = false;
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
bool template_type_arg = false;
+ bool constexpr_p = declspecs->specs[(int) ds_constexpr];
const char *errmsg;
signed_p = declspecs->specs[(int)ds_signed];
*************** grokdeclarator (const cp_declarator *dec
*** 8034,8039 ****
--- 8047,8063 ----
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])
*************** grokdeclarator (const cp_declarator *dec
*** 8105,8110 ****
--- 8129,8142 ----
error ("parameter declared %<auto%>");
type = error_mark_node;
}
+
+ /* Function parameters cannot be constexpr. If we saw one, moan
+ and pretend it wasn't there. */
+ if (constexpr_p)
+ {
+ error ("a parameter cannot be declared %<constexpr%>");
+ constexpr_p = 0;
+ }
}
/* Give error if `virtual' is used outside of class declaration. */
*************** grokdeclarator (const cp_declarator *dec
*** 8412,8417 ****
--- 8444,8464 ----
}
}
+ /* 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);
*************** grokdeclarator (const cp_declarator *dec
*** 8656,8661 ****
--- 8703,8714 ----
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
*************** grokdeclarator (const cp_declarator *dec
*** 9123,9128 ****
--- 9176,9183 ----
uqname, ctype);
return error_mark_node;
}
+ if (constexpr_p)
+ error ("a destructor cannot be %<constexpr%>");
}
else if (sfk == sfk_constructor && friendp)
{
*************** grokdeclarator (const cp_declarator *dec
*** 9143,9149 ****
parms,
unqualified_id,
virtualp, flags, memfn_quals, raises,
! friendp ? -1 : 0, friendp, publicp, inlinep,
sfk,
funcdef_flag, template_count, in_namespace,
attrlist, declarator->id_loc);
--- 9198,9205 ----
parms,
unqualified_id,
virtualp, flags, memfn_quals, raises,
! friendp ? -1 : 0, friendp, publicp,
! inlinep || constexpr_p,
sfk,
funcdef_flag, template_count, in_namespace,
attrlist, declarator->id_loc);
*************** grokdeclarator (const cp_declarator *dec
*** 9235,9240 ****
--- 9291,9297 ----
decl = do_friend (ctype, unqualified_id, decl,
*attrlist, flags,
funcdef_flag);
+ DECL_DECLARED_CONSTEXPR_P (decl) = constexpr_p;
return decl;
}
else
*************** grokdeclarator (const cp_declarator *dec
*** 9296,9301 ****
--- 9353,9361 ----
}
else
{
+ if (constexpr_p)
+ error ("non-static data member %qE declared %<constexpr%>",
+ unqualified_id);
decl = build_decl (input_location,
FIELD_DECL, unqualified_id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
*************** grokdeclarator (const cp_declarator *dec
*** 9390,9396 ****
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, memfn_quals, raises,
1, friendp,
! publicp, inlinep, sfk, funcdef_flag,
template_count, in_namespace, attrlist,
declarator->id_loc);
if (decl == NULL_TREE)
--- 9450,9456 ----
decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
virtualp, flags, memfn_quals, raises,
1, friendp,
! publicp, inlinep || constexpr_p, sfk, funcdef_flag,
template_count, in_namespace, attrlist,
declarator->id_loc);
if (decl == NULL_TREE)
*************** grokdeclarator (const cp_declarator *dec
*** 9487,9492 ****
--- 9547,9556 ----
else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
+ /* Don't forget constexprness. */
+ if (VAR_OR_FUNCTION_DECL_P (decl))
+ DECL_DECLARED_CONSTEXPR_P (decl) = constexpr_p;
+
/* Record constancy and volatility on the DECL itself . There's
no need to do this when processing a template; we'll do this
for the instantiated declaration based on the type of DECL. */
*************** start_enum (tree name, tree underlying_t
*** 10983,10989 ****
if (enumtype == error_mark_node)
name = make_anon_name ();
! enumtype = make_node (ENUMERAL_TYPE);
enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
}
--- 11047,11053 ----
if (enumtype == error_mark_node)
name = make_anon_name ();
! enumtype = cxx_make_type (ENUMERAL_TYPE);
enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
}
*************** check_function_type (tree decl, tree cur
*** 11426,11431 ****
--- 11490,11499 ----
/* 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)
*** gcc/cp/parser.c (revision 152384)
--- gcc/cp/parser.c (local)
*************** cp_parser_check_decl_spec (cp_decl_speci
*** 2195,2200 ****
--- 2195,2201 ----
"explicit",
"friend",
"typedef",
+ "constexpr",
"__complex",
"__thread"
};
*************** cp_parser_decl_specifier_seq (cp_parser*
*** 9030,9036 ****
switch (token->keyword)
{
/* decl-specifier:
! friend */
case RID_FRIEND:
if (!at_class_scope_p ())
{
--- 9031,9038 ----
switch (token->keyword)
{
/* decl-specifier:
! friend
! constexpr */
case RID_FRIEND:
if (!at_class_scope_p ())
{
*************** cp_parser_decl_specifier_seq (cp_parser*
*** 9045,9050 ****
--- 9047,9057 ----
}
break;
+ case RID_CONSTEXPR:
+ ++decl_specs->specs[(int) ds_constexpr];
+ cp_lexer_consume_token (parser->lexer);
+ break;
+
/* function-specifier:
inline
virtual
*** gcc/cp/pt.c (revision 152384)
--- gcc/cp/pt.c (local)
*************** make_pack_expansion (tree arg)
*** 3013,3019 ****
pointer_set_destroy (ppd.visited);
/* Create the pack expansion type for the base type. */
! purpose = make_node (TYPE_PACK_EXPANSION);
SET_PACK_EXPANSION_PATTERN (purpose, TREE_PURPOSE (arg));
PACK_EXPANSION_PARAMETER_PACKS (purpose) = parameter_packs;
--- 3013,3019 ----
pointer_set_destroy (ppd.visited);
/* Create the pack expansion type for the base type. */
! purpose = cxx_make_type (TYPE_PACK_EXPANSION);
SET_PACK_EXPANSION_PATTERN (purpose, TREE_PURPOSE (arg));
PACK_EXPANSION_PARAMETER_PACKS (purpose) = parameter_packs;
*************** make_pack_expansion (tree arg)
*** 3028,3034 ****
for_types = true;
/* Build the PACK_EXPANSION_* node. */
! result = make_node (for_types ? TYPE_PACK_EXPANSION : EXPR_PACK_EXPANSION);
SET_PACK_EXPANSION_PATTERN (result, arg);
if (TREE_CODE (result) == EXPR_PACK_EXPANSION)
{
--- 3028,3036 ----
for_types = true;
/* Build the PACK_EXPANSION_* node. */
! result = for_types
! ? cxx_make_type (TYPE_PACK_EXPANSION)
! : make_node (EXPR_PACK_EXPANSION);
SET_PACK_EXPANSION_PATTERN (result, arg);
if (TREE_CODE (result) == EXPR_PACK_EXPANSION)
{
*************** current_template_args (void)
*** 3538,3544 ****
tree vec = make_tree_vec (1);
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
! t = make_node (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (t, vec);
}
}
--- 3540,3546 ----
tree vec = make_tree_vec (1);
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
! t = cxx_make_type (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (t, vec);
}
}
*************** coerce_template_parameter_pack (tree par
*** 5575,5581 ****
if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
|| TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
! argument_pack = make_node (TYPE_ARGUMENT_PACK);
else
{
argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
--- 5577,5583 ----
if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL
|| TREE_CODE (TREE_VALUE (parm)) == TEMPLATE_DECL)
! argument_pack = cxx_make_type (TYPE_ARGUMENT_PACK);
else
{
argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
*************** lookup_template_class (tree d1,
*** 6261,6267 ****
the values for the enumeration constants may involve
template parameters. And, no one should be interested
in the enumeration constants for such a type. */
! t = make_node (ENUMERAL_TYPE);
SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
}
}
--- 6263,6269 ----
the values for the enumeration constants may involve
template parameters. And, no one should be interested
in the enumeration constants for such a type. */
! t = cxx_make_type (ENUMERAL_TYPE);
SET_SCOPED_ENUM_P (t, SCOPED_ENUM_P (template_type));
}
}
*************** make_fnparm_pack (tree spec_parm)
*** 7816,7822 ****
tree parmvec;
tree parmtypevec;
tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
! tree argtypepack = make_node (TYPE_ARGUMENT_PACK);
int i, len = list_length (spec_parm);
/* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
--- 7818,7824 ----
tree parmvec;
tree parmtypevec;
tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
! tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
int i, len = list_length (spec_parm);
/* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
*************** tsubst_template_args (tree t, tree args,
*** 8147,8153 ****
else if (ARGUMENT_PACK_P (orig_arg))
{
/* Substitute into each of the arguments. */
! new_arg = make_node (TREE_CODE (orig_arg));
SET_ARGUMENT_PACK_ARGS (
new_arg,
--- 8149,8157 ----
else if (ARGUMENT_PACK_P (orig_arg))
{
/* Substitute into each of the arguments. */
! new_arg = TYPE_P (orig_arg)
! ? cxx_make_type (TREE_CODE (orig_arg))
! : make_node (TREE_CODE (orig_arg));
SET_ARGUMENT_PACK_ARGS (
new_arg,
*************** tsubst (tree t, tree args, tsubst_flags_
*** 10186,10192 ****
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
! tree r = make_node (TREE_CODE (t));
tree packed_out =
tsubst_template_args (ARGUMENT_PACK_ARGS (t),
args,
--- 10190,10198 ----
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
! tree r = TYPE_P (t)
! ? cxx_make_type (TREE_CODE (t))
! : make_node (TREE_CODE (t));
tree packed_out =
tsubst_template_args (ARGUMENT_PACK_ARGS (t),
args,
*************** type_unification_real (tree tparms,
*** 13167,13173 ****
TREE_CONSTANT (arg) = 1;
}
else
! arg = make_node (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (arg, make_tree_vec (0));
--- 13173,13179 ----
TREE_CONSTANT (arg) = 1;
}
else
! arg = cxx_make_type (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (arg, make_tree_vec (0));
*************** unify_pack_expansion (tree tparms, tree
*** 13744,13750 ****
TREE_CONSTANT (result) = 1;
}
else
! result = make_node (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (result, new_args);
--- 13750,13756 ----
TREE_CONSTANT (result) = 1;
}
else
! result = cxx_make_type (TYPE_ARGUMENT_PACK);
SET_ARGUMENT_PACK_ARGS (result, new_args);
*** gcc/cp/semantics.c (revision 152384)
--- gcc/cp/semantics.c (local)
*************** float_const_decimal64_p (void)
*** 5203,5208 ****
--- 5203,5289 ----
return 0;
}
+ /* Return true if T is a literal type. */
+
+ bool
+ literal_type_p (tree t)
+ {
+ if (SCALAR_TYPE_P (t))
+ return true;
+ if (CLASS_TYPE_P (t))
+ return CLASSTYPE_LITERAL_P (t);
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ return literal_type_p (strip_array_types (t));
+ return false;
+ }
+
+
+ /* If DECL is a variable declared `constexpr', require its type
+ be literal. Return the DECL if OK, otherwise NULL. */
+
+ tree
+ ensure_literal_type_for_constexpr_object (tree decl)
+ {
+ tree type = TREE_TYPE (decl);
+ if (TREE_CODE (decl) == VAR_DECL && DECL_DECLARED_CONSTEXPR_P (decl)
+ && !processing_template_decl && !literal_type_p (type))
+ {
+ error ("the type %qT of constexpr variable %qD is not literal",
+ type, decl);
+ return NULL;
+ }
+ return decl;
+ }
+
+ /* Return non-null if FUN certainly designates a valid constexpr function
+ declaration. Otherwise return NULL. Issue appropriate diagnostics
+ if necessary. Note that we only check the declaration, not the body
+ of the function. */
+
+ tree
+ validate_constexpr_fundecl (tree fun)
+ {
+ tree rettype = NULL;
+ tree parm = NULL;
+
+ /* Don't bother if FUN is not marked constexpr. */
+ if (!DECL_DECLARED_CONSTEXPR_P (fun))
+ return NULL;
+
+ /* For a function template, we have absolutely no guarantee that all
+ instantiations will be constexpr. */
+ if (TREE_CODE (fun) == TEMPLATE_DECL)
+ return NULL;
+
+ parm = FUNCTION_FIRST_USER_PARM (fun);
+ for (; parm != NULL; parm = TREE_CHAIN (parm))
+ {
+ tree type = TREE_TYPE (parm);
+ if (dependent_type_p (type))
+ return NULL;
+ if (!literal_type_p (type))
+ {
+ error ("parameter %q#D is not of literal type", parm);
+ return NULL;
+ }
+ }
+
+ if (DECL_CONSTRUCTOR_P (fun))
+ return fun;
+
+ rettype = TREE_TYPE (TREE_TYPE (fun));
+ if (dependent_type_p (rettype))
+ return NULL;
+ if (!literal_type_p (rettype))
+ {
+ error ("return type %qT of function %qD is not a literal type",
+ TREE_TYPE (TREE_TYPE (fun)), fun);
+ return NULL;
+ }
+ return fun;
+ }
+
+
/* Constructor for a lambda expression. */
tree
*** gcc/cp/tree.c (revision 152384)
--- gcc/cp/tree.c (local)
*************** build_cplus_array_type_1 (tree elt_type,
*** 639,645 ****
else
{
/* Build a new array type. */
! t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
TYPE_DOMAIN (t) = index_type;
--- 639,645 ----
else
{
/* Build a new array type. */
! t = cxx_make_type (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
TYPE_DOMAIN (t) = index_type;
*************** cp_build_qualified_type_real (tree type,
*** 942,948 ****
&& (TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result))
== TYPE_LANG_SPECIFIC (TYPE_CANONICAL (type))))
TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result)) = NULL;
-
return result;
}
--- 942,947 ----
*** gcc/tree.h (revision 152384)
--- gcc/tree.h (local)
*************** struct GTY(()) tree_decl_minimal {
*** 2597,2602 ****
--- 2597,2603 ----
#define DECL_LANG_FLAG_5(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_5)
#define DECL_LANG_FLAG_6(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_6)
#define DECL_LANG_FLAG_7(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_7)
+ #define DECL_LANG_FLAG_8(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_8)
/* Nonzero for a decl which is at file scope. */
#define DECL_FILE_SCOPE_P(EXP) \
*************** struct GTY(()) tree_decl_common {
*** 2639,2644 ****
--- 2640,2646 ----
unsigned lang_flag_5 : 1;
unsigned lang_flag_6 : 1;
unsigned lang_flag_7 : 1;
+ unsigned lang_flag_8 : 1;
/* In LABEL_DECL, this is DECL_ERROR_ISSUED.
In VAR_DECL and PARM_DECL, this is DECL_REGISTER. */
*************** struct GTY(()) tree_decl_common {
*** 2657,2664 ****
unsigned decl_by_reference_flag : 1;
/* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_RESTRICTED_P. */
unsigned decl_restricted_flag : 1;
/* Padding so that 'off_align' can be on a 32-bit boundary. */
! unsigned decl_common_unused : 3;
/* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
unsigned int off_align : 8;
--- 2659,2667 ----
unsigned decl_by_reference_flag : 1;
/* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_RESTRICTED_P. */
unsigned decl_restricted_flag : 1;
+
/* Padding so that 'off_align' can be on a 32-bit boundary. */
! unsigned decl_common_unused : 2;
/* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
unsigned int off_align : 8;