+2019-02-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/87921 - wrong error with inline static data member.
+ * decl2.c (finish_static_data_member_decl): Don't set DECL_IN_AGGR_P
+ for a non-template inline variable. Do nothing for an
+ already-instantiated variable.
+ (c_parse_final_cleanups): Check DECL_IN_AGGR_P without
+ DECL_INLINE_VAR_P.
+ * decl.c (check_initializer): Likewise.
+ (make_rtl_for_nonlocal_decl): Likewise.
+ * pt.c (instantiate_decl): Likewise.
+ * typeck2.c (store_init_value): Likewise.
+
2019-02-20 Jakub Jelinek <jakub@redhat.com>
PR c++/89403
/* Nonzero for _DECL means that this decl appears in (or will appear
in) as a member in a RECORD_TYPE or UNION_TYPE node. It is also for
detecting circularity in case members are multiply defined. In the
- case of a VAR_DECL, it is also used to determine how program storage
- should be allocated. */
+ case of a VAR_DECL, it means that no definition has been seen, even
+ if an initializer has been. */
#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE))
/* Nonzero for a VAR_DECL means that the variable's initialization (if
}
if (init_code
- && (DECL_IN_AGGR_P (decl)
- && DECL_INITIALIZED_IN_CLASS_P (decl)
- && !DECL_VAR_DECLARED_INLINE_P (decl)))
+ && DECL_IN_AGGR_P (decl)
+ && DECL_INITIALIZED_IN_CLASS_P (decl))
{
static int explained = 0;
external; it is only a declaration, and not a definition. */
if (init == NULL_TREE)
gcc_assert (DECL_EXTERNAL (decl)
- || !TREE_PUBLIC (decl)
- || DECL_INLINE_VAR_P (decl));
+ || !TREE_PUBLIC (decl));
}
/* We don't create any RTL for local variables. */
tree asmspec_tree,
int flags)
{
+ if (DECL_TEMPLATE_INSTANTIATED (decl))
+ /* We already needed to instantiate this, so the processing in this
+ function is unnecessary/wrong. */
+ return;
+
DECL_CONTEXT (decl) = current_class_type;
/* We cannot call pushdecl here, because that would fill in the
break;
}
- DECL_IN_AGGR_P (decl) = 1;
+ if (DECL_INLINE_VAR_P (decl) && !DECL_TEMPLATE_INSTANTIATION (decl))
+ /* An inline variable is immediately defined, so don't set DECL_IN_AGGR_P.
+ Except that if decl is a template instantiation, it isn't defined until
+ instantiate_decl. */;
+ else
+ DECL_IN_AGGR_P (decl) = 1;
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& TYPE_DOMAIN (TREE_TYPE (decl)) == NULL_TREE)
{
if (var_finalized_p (decl) || DECL_REALLY_EXTERN (decl)
/* Don't write it out if we haven't seen a definition. */
- || (DECL_IN_AGGR_P (decl) && !DECL_INLINE_VAR_P (decl)))
+ || DECL_IN_AGGR_P (decl))
continue;
import_export_decl (decl);
/* If this static data member is needed, provide it to the
{
deleted_p = false;
if (DECL_CLASS_SCOPE_P (code_pattern))
- pattern_defined = (! DECL_IN_AGGR_P (code_pattern)
- || DECL_INLINE_VAR_P (code_pattern));
+ pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
else
pattern_defined = ! DECL_EXTERNAL (code_pattern);
}
value = fold_non_dependent_expr (value);
if (DECL_DECLARED_CONSTEXPR_P (decl)
|| (DECL_IN_AGGR_P (decl)
- && DECL_INITIALIZED_IN_CLASS_P (decl)
- && !DECL_VAR_DECLARED_INLINE_P (decl)))
+ && DECL_INITIALIZED_IN_CLASS_P (decl)))
{
/* Diagnose a non-constant initializer for constexpr variable or
non-inline in-class-initialized static data member. */
--- /dev/null
+// PR c++/87921
+// { dg-do compile { target c++17 } }
+
+template <class H>
+struct X
+{
+ static inline long x[] = { 1L };
+ long foo () { return x[0]; }
+};
+
+void
+bar ()
+{
+ class L {};
+ X<L> v {};
+}