@@ -101,12 +101,54 @@ struct constexpr_global_ctx
101101 auto_vec<tree, 16 > heap_vars;
102102 /* Cleanups that need to be evaluated at the end of CLEANUP_POINT_EXPR. */
103103 vec<tree> *cleanups;
104+ /* If non-null, only allow modification of existing values of the variables
105+ in this set. Set by modifiable_tracker, below. */
106+ hash_set<tree> *modifiable;
104107 /* Number of heap VAR_DECL deallocations. */
105108 unsigned heap_dealloc_count;
106109 /* Constructor. */
107110 constexpr_global_ctx ()
108111 : constexpr_ops_count (0 ), cleanups (NULL ), heap_dealloc_count (0 )
109112 {}
113+
114+ tree get_value (tree t)
115+ {
116+ if (tree *p = values.get (t))
117+ if (*p != void_node)
118+ return *p;
119+ return NULL_TREE;
120+ }
121+ tree *get_value_ptr (tree t, bool initializing)
122+ {
123+ if (modifiable && !modifiable->contains (t))
124+ return nullptr ;
125+ if (tree *p = values.get (t))
126+ {
127+ if (*p != void_node)
128+ return p;
129+ else if (initializing)
130+ {
131+ *p = NULL_TREE;
132+ return p;
133+ }
134+ }
135+ return nullptr ;
136+ }
137+ void put_value (tree t, tree v)
138+ {
139+ bool already_in_map = values.put (t, v);
140+ if (!already_in_map && modifiable)
141+ modifiable->add (t);
142+ }
143+ void destroy_value (tree t)
144+ {
145+ if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL
146+ || TREE_CODE (t) == RESULT_DECL)
147+ values.put (t, void_node);
148+ else
149+ values.remove (t);
150+ }
151+ void clear_value (tree t) { values.remove (t); }
110152};
111153
112154/* In constexpr.cc */
@@ -457,6 +499,7 @@ save_fundef_copy (tree fun, tree copy)
457499
458500static tree constant_value_1 (tree decl, bool strict_p,
459501 bool return_aggregate_cst_ok_p, bool unshare_p);
502+ static tree decl_really_constant_value (tree decl, bool unshare_p /* = true*/ );
460503tree decl_constant_value (tree decl, bool unshare_p);
461504
462505static void non_const_var_error (location_t loc, tree r);
@@ -1925,30 +1968,40 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
19251968 }
19261969 /* fall through */
19271970 case CONST_DECL:
1928- {
1929- /* We used to not check lval for CONST_DECL, but darwin.cc uses
1930- CONST_DECL for aggregate constants. */
1931- if (lval)
1932- return t;
1933- else if (t == ctx->object )
1934- return ctx->ctor ;
1935- if (VAR_P (t))
1936- if (tree *p = ctx->global ->values .get (t))
1937- if (*p != NULL_TREE)
1938- {
1939- r = *p;
1940- break ;
1941- }
1971+ /* We used to not check lval for CONST_DECL, but darwin.cc uses
1972+ CONST_DECL for aggregate constants. */
1973+ if (lval)
1974+ return t;
1975+ else if (t == ctx->object )
1976+ return ctx->ctor ;
1977+ if (VAR_P (t))
1978+ {
1979+ if (tree v = ctx->global ->get_value (t))
1980+ {
1981+ r = v;
1982+ break ;
1983+ }
1984+ }
1985+ if (COMPLETE_TYPE_P (TREE_TYPE (t))
1986+ && is_really_empty_class (TREE_TYPE (t), /* ignore_vptr*/ false ))
1987+ {
1988+ /* If the class is empty, we aren't actually loading anything. */
1989+ r = build_constructor (TREE_TYPE (t), NULL );
1990+ TREE_CONSTANT (r) = true ;
1991+ }
1992+ else if (ctx->strict )
1993+ r = decl_really_constant_value (t, /* unshare_p=*/ false );
1994+ else
19421995 r = decl_constant_value (t, /* unshare_p=*/ false );
1943- if (TREE_CODE (r) == TARGET_EXPR
1944- && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
1945- r = TARGET_EXPR_INITIAL (r);
1946- if (DECL_P (r))
1947- {
1996+ if (TREE_CODE (r) == TARGET_EXPR
1997+ && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
1998+ r = TARGET_EXPR_INITIAL (r);
1999+ if (DECL_P (r) && !(VAR_P (t) && TYPE_REF_P (TREE_TYPE (t))))
2000+ {
2001+ if (!ctx->quiet )
19482002 non_const_var_error (loc, r);
1949- return r;
1950- }
1951- }
2003+ *non_constant_p = true ;
2004+ }
19522005 break ;
19532006
19542007 case PARM_DECL:
@@ -4024,6 +4077,17 @@ constant_value_1 (tree decl, bool, bool, bool unshare_p)
40244077 return unshare_p ? unshare_expr (decl) : decl;
40254078}
40264079
4080+ /* Like scalar_constant_value, but can also return aggregate initializers.
4081+ If UNSHARE_P, return an unshared copy of the initializer. */
4082+
4083+ tree
4084+ decl_really_constant_value (tree decl, bool unshare_p /* = true*/ )
4085+ {
4086+ return constant_value_1 (decl, /* strict_p=*/ true ,
4087+ /* return_aggregate_cst_ok_p=*/ true ,
4088+ /* unshare_p=*/ unshare_p);
4089+ }
4090+
40274091// A more relaxed version of decl_really_constant_value, used by the
40284092// common C/C++ code.
40294093tree
@@ -4037,15 +4101,38 @@ decl_constant_value (tree decl, bool unshare_p)
40374101static void
40384102non_const_var_error (location_t loc, tree r)
40394103{
4040- error_at (loc,
4041- " the value of %qD is not usable in a constant "
4042- " expression" ,
4043- r);
4104+ tree type = TREE_TYPE (r);
4105+
40444106 /* Avoid error cascade. */
40454107 if (DECL_INITIAL (r) == error_mark_node)
40464108 return ;
4047-
4048- // more in cp/constexpr.cc
4109+ if (DECL_DECLARED_CONSTEXPR_P (r))
4110+ inform (DECL_SOURCE_LOCATION (r), " %qD used in its own initializer" , r);
4111+ else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
4112+ {
4113+ if (!DECL_INITIAL (r) || !TREE_CONSTANT (DECL_INITIAL (r))
4114+ || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r))
4115+ inform (DECL_SOURCE_LOCATION (r),
4116+ " %qD was not initialized with a constant "
4117+ " expression" ,
4118+ r);
4119+ else
4120+ gcc_unreachable ();
4121+ }
4122+ else if (TYPE_REF_P (type))
4123+ inform (DECL_SOURCE_LOCATION (r),
4124+ " %qD was not initialized with a constant "
4125+ " expression" ,
4126+ r);
4127+ else
4128+ {
4129+ if (!DECL_DECLARED_CONSTEXPR_P (r))
4130+ inform (DECL_SOURCE_LOCATION (r), " %qD was not declared %<constexpr%>" ,
4131+ r);
4132+ else
4133+ inform (DECL_SOURCE_LOCATION (r),
4134+ " %qD does not have integral or enumeration type" , r);
4135+ }
40494136}
40504137
40514138static tree
0 commit comments