This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]