Implement P0386R2 - C++17 inline variables
2016-10-11 Jakub Jelinek <jakub@redhat.com> * dwarf2out.c (gen_member_die): Handle inline static data member definitions. c-family/ * c-cppbuiltin.c (c_cpp_builtins): Add __cpp_inline_variables. cp/ * cp-tree.h (struct lang_type): Shrink language field to 1 bit from 4. Add var_declared_inline_p field. Mention 2 spare bits. (DECL_VAR_DECLARED_INLINE_P): Define. (SET_DECL_VAR_DECLARED_INLINE_P): Define. (DECL_INLINE_VAR_P): Define. (diagnose_inline_vars_for_namespace): Declare. * decl.c (diagnose_inline_vars_for_namespace): New function. (duplicate_decls): For static data members copy DECL_DECLARED_CONSTEXPR_P. (redeclaration_error_message): Handle C++17 redundant redeclaration of constexpr static data member outside of class. (maybe_commonize_var): Handle inline variables. (check_initializer): Ignore inline variables for diagnostics. Adjust diagnostic wording for C++17. (make_rtl_for_nonlocal_decl): Allow in-class definition of inline static data members. (bad_specifiers): Don't diagnose inline on variables here. (grokvardecl): Add inlinep argument, non-static const inline variables are TREE_PUBLIC. (check_static_variable_definition): Return early also for inline variables. (grokdeclarator): Handle inline variables and inline static data members. * typeck2.c (store_init_value): Don't diagnose non-constant initializers for non-constexpr inline static data members. * decl2.c (vague_linkage_p): Return true for inline variables. (c_parse_final_cleanups): In-class declaration of inline static data members is a definition. Call diagnose_inline_vars_for_namespace through walk_namespaces. * pt.c (instantiate_decl): Set pattern_defined for in-class definitions of inline static data members. From-SVN: r241137
This commit is contained in:
parent
fc0911e0b8
commit
14a2c9aac0
@ -1,3 +1,8 @@
|
||||
2016-10-13 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* dwarf2out.c (gen_member_die): Handle inline static data member
|
||||
definitions.
|
||||
|
||||
2016-10-13 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* gcov-io.c (gcov_open): Fix documentation. Simplify setting
|
||||
|
@ -1,3 +1,7 @@
|
||||
2016-10-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* c-cppbuiltin.c (c_cpp_builtins): Add __cpp_inline_variables.
|
||||
|
||||
2016-10-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
|
||||
|
||||
* c-cppbuiltin.c: Include memmodel.h.
|
||||
|
@ -935,6 +935,7 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
cpp_define (pfile, "__cpp_constexpr=201603");
|
||||
cpp_define (pfile, "__cpp_if_constexpr=201606");
|
||||
cpp_define (pfile, "__cpp_capture_star_this=201603");
|
||||
cpp_define (pfile, "__cpp_inline_variables=201606");
|
||||
}
|
||||
if (flag_concepts)
|
||||
/* Use a value smaller than the 201507 specified in
|
||||
|
@ -1,3 +1,44 @@
|
||||
2016-10-13 Jakub Jelinek <jakub@redhat.com>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
Implement P0386R2 - C++17 inline variables
|
||||
* cp-tree.h (struct lang_type): Shrink language field to 1 bit
|
||||
from 4. Add var_declared_inline_p field. Mention 2 spare bits.
|
||||
(DECL_VAR_DECLARED_INLINE_P): Define.
|
||||
(SET_DECL_VAR_DECLARED_INLINE_P): Define.
|
||||
(DECL_INLINE_VAR_P): Define.
|
||||
(diagnose_inline_vars_for_namespace): Declare.
|
||||
* decl.c (diagnose_inline_vars_for_namespace): New function.
|
||||
(duplicate_decls): For static data members copy
|
||||
DECL_DECLARED_CONSTEXPR_P.
|
||||
(redeclaration_error_message): Handle C++17 redundant redeclaration
|
||||
of constexpr static data member outside of class.
|
||||
(maybe_commonize_var): Handle inline variables.
|
||||
(check_initializer): Ignore inline variables for diagnostics.
|
||||
Adjust diagnostic wording for C++17.
|
||||
(make_rtl_for_nonlocal_decl): Allow in-class definition of
|
||||
inline static data members.
|
||||
(bad_specifiers): Don't diagnose inline on variables here.
|
||||
(grokvardecl): Add inlinep argument, non-static const inline variables
|
||||
are TREE_PUBLIC.
|
||||
(check_static_variable_definition): Return early also for inline
|
||||
variables.
|
||||
(mark_inline_variable): New.
|
||||
(grokdeclarator): Handle inline variables and inline static data
|
||||
members.
|
||||
* typeck2.c (store_init_value): Don't diagnose non-constant
|
||||
initializers for non-constexpr inline static data members.
|
||||
* decl2.c (vague_linkage_p): Return true for inline variables.
|
||||
(c_parse_final_cleanups): In-class declaration of inline static
|
||||
data members is a definition. Call diagnose_inline_vars_for_namespace
|
||||
through walk_namespaces.
|
||||
* pt.c (instantiate_decl): Set pattern_defined for in-class definitions
|
||||
of inline static data members.
|
||||
|
||||
2016-10-13 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* decl.c (mark_inline_variable): New.
|
||||
|
||||
2016-10-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
|
||||
|
||||
* decl2.c: Include memmodel.h.
|
||||
|
@ -2214,7 +2214,7 @@ struct GTY(()) lang_type {
|
||||
|
||||
struct GTY(()) lang_decl_base {
|
||||
unsigned selector : 16; /* Larger than necessary for faster access. */
|
||||
ENUM_BITFIELD(languages) language : 4;
|
||||
ENUM_BITFIELD(languages) language : 1;
|
||||
unsigned use_template : 2;
|
||||
unsigned not_really_extern : 1; /* var or fn */
|
||||
unsigned initialized_in_class : 1; /* var or fn */
|
||||
@ -2227,7 +2227,8 @@ struct GTY(()) lang_decl_base {
|
||||
unsigned odr_used : 1; /* var or fn */
|
||||
unsigned u2sel : 1;
|
||||
unsigned concept_p : 1; /* applies to vars and functions */
|
||||
/* 0 spare bits */
|
||||
unsigned var_declared_inline_p : 1; /* var */
|
||||
/* 2 spare bits */
|
||||
};
|
||||
|
||||
/* True for DECL codes which have template info and access. */
|
||||
@ -3607,6 +3608,23 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
||||
#define CP_DECL_THREADPRIVATE_P(DECL) \
|
||||
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (DECL))->u.base.threadprivate_or_deleted_p)
|
||||
|
||||
/* Nonzero if NODE is a VAR_DECL which has been declared inline. */
|
||||
#define DECL_VAR_DECLARED_INLINE_P(NODE) \
|
||||
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) \
|
||||
? DECL_LANG_SPECIFIC (NODE)->u.base.var_declared_inline_p \
|
||||
: false)
|
||||
#define SET_DECL_VAR_DECLARED_INLINE_P(NODE) \
|
||||
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.var_declared_inline_p \
|
||||
= true)
|
||||
|
||||
/* Nonzero if NODE is an inline VAR_DECL. In C++17, static data members
|
||||
declared with constexpr specifier are implicitly inline variables. */
|
||||
#define DECL_INLINE_VAR_P(NODE) \
|
||||
(DECL_VAR_DECLARED_INLINE_P (NODE) \
|
||||
|| (cxx_dialect >= cxx1z \
|
||||
&& DECL_DECLARED_CONSTEXPR_P (NODE) \
|
||||
&& DECL_CLASS_SCOPE_P (NODE)))
|
||||
|
||||
/* Nonzero if DECL was declared with '= delete'. */
|
||||
#define DECL_DELETED_FN(DECL) \
|
||||
(LANG_DECL_FN_CHECK (DECL)->min.base.threadprivate_or_deleted_p)
|
||||
@ -5799,6 +5817,7 @@ typedef int (*walk_namespaces_fn) (tree, void *);
|
||||
extern int walk_namespaces (walk_namespaces_fn,
|
||||
void *);
|
||||
extern int wrapup_globals_for_namespace (tree, void *);
|
||||
extern int diagnose_inline_vars_for_namespace (tree, void *);
|
||||
extern tree create_implicit_typedef (tree, tree);
|
||||
extern int local_variable_p (const_tree);
|
||||
extern tree register_dtor_fn (tree);
|
||||
|
134
gcc/cp/decl.c
134
gcc/cp/decl.c
@ -68,7 +68,7 @@ static int unary_op_p (enum tree_code);
|
||||
static void push_local_name (tree);
|
||||
static tree grok_reference_init (tree, tree, tree, int);
|
||||
static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *,
|
||||
int, int, int, tree);
|
||||
int, int, int, int, tree);
|
||||
static int check_static_variable_definition (tree, tree);
|
||||
static void record_unknown_type (tree, const char *);
|
||||
static tree builtin_function_1 (tree, tree, bool);
|
||||
@ -937,6 +937,27 @@ wrapup_globals_for_namespace (tree name_space, void* data ATTRIBUTE_UNUSED)
|
||||
/* Write out any globals that need to be output. */
|
||||
return wrapup_global_declarations (vec, len);
|
||||
}
|
||||
|
||||
/* Diagnose odr-used extern inline variables without definitions
|
||||
in the current TU. */
|
||||
int
|
||||
diagnose_inline_vars_for_namespace (tree name_space, void *)
|
||||
{
|
||||
cp_binding_level *level = NAMESPACE_LEVEL (name_space);
|
||||
vec<tree, va_gc> *statics = level->static_decls;
|
||||
tree decl;
|
||||
unsigned int i;
|
||||
|
||||
FOR_EACH_VEC_SAFE_ELT (statics, i, decl)
|
||||
if (VAR_P (decl)
|
||||
&& DECL_EXTERNAL (decl)
|
||||
&& DECL_INLINE_VAR_P (decl)
|
||||
&& DECL_ODR_USED (decl))
|
||||
error_at (DECL_SOURCE_LOCATION (decl),
|
||||
"odr-used inline variable %qD is not defined", decl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* In C++, you don't have to write `struct S' to refer to `S'; you
|
||||
can just use `S'. We accomplish this by creating a TYPE_DECL as
|
||||
@ -2098,6 +2119,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|
||||
|= DECL_NONTRIVIALLY_INITIALIZED_P (olddecl);
|
||||
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|
||||
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
|
||||
if (DECL_CLASS_SCOPE_P (olddecl))
|
||||
DECL_DECLARED_CONSTEXPR_P (newdecl)
|
||||
|= DECL_DECLARED_CONSTEXPR_P (olddecl);
|
||||
|
||||
/* Merge the threadprivate attribute from OLDDECL into NEWDECL. */
|
||||
if (DECL_LANG_SPECIFIC (olddecl)
|
||||
@ -2882,6 +2906,27 @@ redeclaration_error_message (tree newdecl, tree olddecl)
|
||||
is valid. */
|
||||
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
|
||||
return NULL;
|
||||
|
||||
/* Static data member declared outside a class definition
|
||||
if the variable is defined within the class with constexpr
|
||||
specifier is declaration rather than definition (and
|
||||
deprecated). */
|
||||
if (cxx_dialect >= cxx1z
|
||||
&& DECL_CLASS_SCOPE_P (olddecl)
|
||||
&& DECL_DECLARED_CONSTEXPR_P (olddecl)
|
||||
&& !DECL_INITIAL (newdecl))
|
||||
{
|
||||
DECL_EXTERNAL (newdecl) = 1;
|
||||
/* For now, only warn with explicit -Wdeprecated. */
|
||||
if (global_options_set.x_warn_deprecated
|
||||
&& warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wdeprecated,
|
||||
"redundant redeclaration of %<constexpr%> static "
|
||||
"data member %qD", newdecl))
|
||||
inform (DECL_SOURCE_LOCATION (olddecl),
|
||||
"previous declaration of %qD", olddecl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Reject two definitions. */
|
||||
return G_("redefinition of %q#D");
|
||||
}
|
||||
@ -5405,11 +5450,12 @@ maybe_commonize_var (tree decl)
|
||||
{
|
||||
/* Static data in a function with comdat linkage also has comdat
|
||||
linkage. */
|
||||
if (TREE_STATIC (decl)
|
||||
if ((TREE_STATIC (decl)
|
||||
/* Don't mess with __FUNCTION__. */
|
||||
&& ! DECL_ARTIFICIAL (decl)
|
||||
&& DECL_FUNCTION_SCOPE_P (decl)
|
||||
&& vague_linkage_p (DECL_CONTEXT (decl)))
|
||||
|| (TREE_PUBLIC (decl) && DECL_INLINE_VAR_P (decl)))
|
||||
{
|
||||
if (flag_weak)
|
||||
{
|
||||
@ -5435,10 +5481,17 @@ maybe_commonize_var (tree decl)
|
||||
be merged. */
|
||||
TREE_PUBLIC (decl) = 0;
|
||||
DECL_COMMON (decl) = 0;
|
||||
const char *msg;
|
||||
if (DECL_INLINE_VAR_P (decl))
|
||||
msg = G_("sorry: semantics of inline variable "
|
||||
"%q#D are wrong (you%'ll wind up with "
|
||||
"multiple copies)");
|
||||
else
|
||||
msg = G_("sorry: semantics of inline function "
|
||||
"static data %q#D are wrong (you%'ll wind "
|
||||
"up with multiple copies)");
|
||||
if (warning_at (DECL_SOURCE_LOCATION (decl), 0,
|
||||
"sorry: semantics of inline function static "
|
||||
"data %q#D are wrong (you%'ll wind up "
|
||||
"with multiple copies)", decl))
|
||||
msg, decl))
|
||||
inform (DECL_SOURCE_LOCATION (decl),
|
||||
"you can work around this by removing the initializer");
|
||||
}
|
||||
@ -6282,15 +6335,19 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
|
||||
TREE_CONSTANT (decl) = false;
|
||||
}
|
||||
|
||||
if (init_code && DECL_IN_AGGR_P (decl))
|
||||
if (init_code
|
||||
&& (DECL_IN_AGGR_P (decl) && !DECL_VAR_DECLARED_INLINE_P (decl)))
|
||||
{
|
||||
static int explained = 0;
|
||||
|
||||
if (cxx_dialect < cxx11)
|
||||
error ("initializer invalid for static member with constructor");
|
||||
else
|
||||
else if (cxx_dialect < cxx1z)
|
||||
error ("non-constant in-class initialization invalid for static "
|
||||
"member %qD", decl);
|
||||
else
|
||||
error ("non-constant in-class initialization invalid for non-inline "
|
||||
"static member %qD", decl);
|
||||
if (!explained)
|
||||
{
|
||||
inform (input_location,
|
||||
@ -6346,7 +6403,9 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
|
||||
/* An in-class declaration of a static data member should be
|
||||
external; it is only a declaration, and not a definition. */
|
||||
if (init == NULL_TREE)
|
||||
gcc_assert (DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl));
|
||||
gcc_assert (DECL_EXTERNAL (decl)
|
||||
|| !TREE_PUBLIC (decl)
|
||||
|| DECL_INLINE_VAR_P (decl));
|
||||
}
|
||||
|
||||
/* We don't create any RTL for local variables. */
|
||||
@ -7745,8 +7804,6 @@ bad_specifiers (tree object,
|
||||
case BSP_VAR:
|
||||
if (virtualp)
|
||||
error ("%qD declared as a %<virtual%> variable", object);
|
||||
if (inlinep)
|
||||
error ("%qD declared as an %<inline%> variable", object);
|
||||
if (quals)
|
||||
error ("%<const%> and %<volatile%> function specifiers on "
|
||||
"%qD invalid in variable declaration", object);
|
||||
@ -8456,6 +8513,7 @@ grokvardecl (tree type,
|
||||
const cp_decl_specifier_seq *declspecs,
|
||||
int initialized,
|
||||
int flags,
|
||||
int inlinep,
|
||||
int template_count,
|
||||
tree scope)
|
||||
{
|
||||
@ -8520,7 +8578,9 @@ grokvardecl (tree type,
|
||||
else if (toplevel_bindings_p ())
|
||||
{
|
||||
TREE_PUBLIC (decl) = (declspecs->storage_class != sc_static
|
||||
&& (DECL_THIS_EXTERN (decl) || ! constp));
|
||||
&& (DECL_THIS_EXTERN (decl)
|
||||
|| ! constp
|
||||
|| inlinep));
|
||||
TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
|
||||
}
|
||||
/* Not at top level, only `static' makes a static definition. */
|
||||
@ -8692,8 +8752,10 @@ check_static_variable_definition (tree decl, tree type)
|
||||
if (dependent_type_p (type))
|
||||
return 0;
|
||||
/* If DECL is declared constexpr, we'll do the appropriate checks
|
||||
in check_initializer. */
|
||||
if (DECL_P (decl) && DECL_DECLARED_CONSTEXPR_P (decl))
|
||||
in check_initializer. Similarly for inline static data members. */
|
||||
if (DECL_P (decl)
|
||||
&& (DECL_DECLARED_CONSTEXPR_P (decl)
|
||||
|| DECL_VAR_DECLARED_INLINE_P (decl)))
|
||||
return 0;
|
||||
else if (cxx_dialect >= cxx11 && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
|
||||
{
|
||||
@ -9241,6 +9303,29 @@ check_var_type (tree identifier, tree type)
|
||||
return type;
|
||||
}
|
||||
|
||||
/* Handle declaring DECL as an inline variable. */
|
||||
|
||||
static void
|
||||
mark_inline_variable (tree decl)
|
||||
{
|
||||
bool inlinep = true;
|
||||
if (! toplevel_bindings_p ())
|
||||
{
|
||||
error ("%<inline%> specifier invalid for variable "
|
||||
"%qD declared at block scope", decl);
|
||||
inlinep = false;
|
||||
}
|
||||
else if (cxx_dialect < cxx1z)
|
||||
pedwarn (DECL_SOURCE_LOCATION (decl), 0,
|
||||
"inline variables are only available "
|
||||
"with -std=c++1z or -std=gnu++1z");
|
||||
if (inlinep)
|
||||
{
|
||||
retrofit_lang_decl (decl);
|
||||
SET_DECL_VAR_DECLARED_INLINE_P (decl);
|
||||
}
|
||||
}
|
||||
|
||||
/* Given declspecs and a declarator (abstract or otherwise), determine
|
||||
the name and type of the object declared and construct a DECL node
|
||||
for it.
|
||||
@ -11349,11 +11434,6 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
: input_location,
|
||||
VAR_DECL, unqualified_id, type);
|
||||
set_linkage_for_static_data_member (decl);
|
||||
/* Even if there is an in-class initialization, DECL
|
||||
is considered undefined until an out-of-class
|
||||
definition is provided. */
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
|
||||
if (thread_p)
|
||||
{
|
||||
CP_DECL_THREAD_LOCAL_P (decl) = true;
|
||||
@ -11371,6 +11451,17 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
"initializer", decl);
|
||||
constexpr_p = false;
|
||||
}
|
||||
|
||||
if (inlinep)
|
||||
mark_inline_variable (decl);
|
||||
|
||||
if (!DECL_VAR_DECLARED_INLINE_P (decl)
|
||||
&& !(cxx_dialect >= cxx1z && constexpr_p))
|
||||
/* Even if there is an in-class initialization, DECL
|
||||
is considered undefined until an out-of-class
|
||||
definition is provided, unless this is an inline
|
||||
variable. */
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -11411,7 +11502,8 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
|
||||
bad_specifiers (decl, BSP_FIELD, virtualp,
|
||||
memfn_quals != TYPE_UNQUALIFIED,
|
||||
inlinep, friendp, raises != NULL_TREE);
|
||||
staticp ? false : inlinep, friendp,
|
||||
raises != NULL_TREE);
|
||||
}
|
||||
}
|
||||
else if (TREE_CODE (type) == FUNCTION_TYPE
|
||||
@ -11535,6 +11627,7 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
declspecs,
|
||||
initialized,
|
||||
((type_quals & TYPE_QUAL_CONST) != 0) | (2 * concept_p),
|
||||
inlinep,
|
||||
template_count,
|
||||
ctype ? ctype : in_namespace);
|
||||
if (decl == NULL_TREE)
|
||||
@ -11573,6 +11666,9 @@ grokdeclarator (const cp_declarator *declarator,
|
||||
decl);
|
||||
constexpr_p = false;
|
||||
}
|
||||
|
||||
if (inlinep)
|
||||
mark_inline_variable (decl);
|
||||
}
|
||||
|
||||
if (VAR_P (decl) && !initialized)
|
||||
|
@ -1827,7 +1827,8 @@ vague_linkage_p (tree decl)
|
||||
|| (TREE_CODE (decl) == FUNCTION_DECL
|
||||
&& DECL_DECLARED_INLINE_P (decl))
|
||||
|| (DECL_LANG_SPECIFIC (decl)
|
||||
&& DECL_TEMPLATE_INSTANTIATION (decl)))
|
||||
&& DECL_TEMPLATE_INSTANTIATION (decl))
|
||||
|| (VAR_P (decl) && DECL_INLINE_VAR_P (decl)))
|
||||
return true;
|
||||
else if (DECL_FUNCTION_SCOPE_P (decl))
|
||||
/* A local static in an inline effectively has vague linkage. */
|
||||
@ -4711,7 +4712,7 @@ c_parse_final_cleanups (void)
|
||||
{
|
||||
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_IN_AGGR_P (decl) && !DECL_INLINE_VAR_P (decl)))
|
||||
continue;
|
||||
import_export_decl (decl);
|
||||
/* If this static data member is needed, provide it to the
|
||||
@ -4728,6 +4729,8 @@ c_parse_final_cleanups (void)
|
||||
}
|
||||
while (reconsider);
|
||||
|
||||
walk_namespaces (diagnose_inline_vars_for_namespace, /*data=*/0);
|
||||
|
||||
lower_var_init ();
|
||||
|
||||
generate_mangling_aliases ();
|
||||
|
@ -21923,7 +21923,8 @@ instantiate_decl (tree d, int defer_ok,
|
||||
{
|
||||
deleted_p = false;
|
||||
if (DECL_CLASS_SCOPE_P (code_pattern))
|
||||
pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
|
||||
pattern_defined = (! DECL_IN_AGGR_P (code_pattern)
|
||||
|| DECL_INLINE_VAR_P (code_pattern));
|
||||
else
|
||||
pattern_defined = ! DECL_EXTERNAL (code_pattern);
|
||||
}
|
||||
|
@ -807,7 +807,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
|
||||
bool const_init;
|
||||
value = instantiate_non_dependent_expr (value);
|
||||
if (DECL_DECLARED_CONSTEXPR_P (decl)
|
||||
|| DECL_IN_AGGR_P (decl))
|
||||
|| (DECL_IN_AGGR_P (decl) && !DECL_VAR_DECLARED_INLINE_P (decl)))
|
||||
{
|
||||
/* Diagnose a non-constant initializer for constexpr. */
|
||||
if (processing_template_decl
|
||||
|
@ -22653,7 +22653,18 @@ gen_member_die (tree type, dw_die_ref context_die)
|
||||
|
||||
child = lookup_decl_die (member);
|
||||
if (child)
|
||||
{
|
||||
/* Handle inline static data members, which only have in-class
|
||||
declarations. */
|
||||
if (child->die_tag == DW_TAG_variable
|
||||
&& child->die_parent == comp_unit_die ())
|
||||
{
|
||||
reparent_child (child, context_die);
|
||||
child->die_tag = DW_TAG_member;
|
||||
}
|
||||
else
|
||||
splice_child_die (context_die, child);
|
||||
}
|
||||
|
||||
/* Do not generate standard DWARF for variant parts if we are generating
|
||||
the corresponding GNAT encodings: DIEs generated for both would
|
||||
|
@ -1,3 +1,13 @@
|
||||
2016-10-13 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* g++.dg/cpp1z/inline-var1.C: New test.
|
||||
* g++.dg/cpp1z/inline-var1a.C: New test.
|
||||
* g++.dg/cpp1z/inline-var1.h: New file.
|
||||
* g++.dg/cpp1z/inline-var2.C: New test.
|
||||
* g++.dg/cpp1z/inline-var3.C: New test.
|
||||
* g++.dg/concepts/decl-diagnose.C (struct X): Expect also error about
|
||||
uninitialized const.
|
||||
|
||||
2016-10-13 Sandra Loosemore <sandra@codesourcery.com>
|
||||
|
||||
* gcc.target/arm/scd42-1.c: Skip if -mcpu incompatible with
|
||||
|
@ -16,6 +16,7 @@ struct X
|
||||
template<typename T>
|
||||
static concept bool f6() { return true; } // { dg-error "a concept cannot be a member function" }
|
||||
static concept bool x; // { dg-error "declared 'concept'" }
|
||||
// { dg-error "uninitialized const" "" { target *-*-* } .-1 }
|
||||
concept int x2; // { dg-error "declared 'concept'" }
|
||||
concept ~X(); // { dg-error "a destructor cannot be 'concept'" }
|
||||
concept X(); // { dg-error "a constructor cannot be 'concept'" }
|
||||
|
@ -6,3 +6,5 @@ struct A
|
||||
constexpr A() {}
|
||||
static constexpr A a[2] = {}; // { dg-error "22:elements of array 'constexpr const A A::a \\\[2\\\]' have incomplete type" }
|
||||
};
|
||||
|
||||
// { dg-prune-output "storage size" }
|
||||
|
@ -356,6 +356,12 @@
|
||||
# error "__cpp_aligned_new != 201606"
|
||||
#endif
|
||||
|
||||
#ifndef __cpp_inline_variables
|
||||
# error "__cpp_inline_variables"
|
||||
#elif __cpp_inline_variables != 201606
|
||||
# error "__cpp_inline_variables != 201606"
|
||||
#endif
|
||||
|
||||
#ifndef __cpp_capture_star_this
|
||||
# error "__cpp_capture_star_this"
|
||||
#elif __cpp_capture_star_this != 201603
|
||||
|
216
gcc/testsuite/g++.dg/cpp1z/inline-var1.C
Normal file
216
gcc/testsuite/g++.dg/cpp1z/inline-var1.C
Normal file
@ -0,0 +1,216 @@
|
||||
// { dg-do run }
|
||||
// { dg-options "-std=c++1z -Wno-deprecated" }
|
||||
// { dg-require-weak "" }
|
||||
// { dg-additional-sources "inline-var1a.C" }
|
||||
|
||||
#include "inline-var1.h"
|
||||
|
||||
static inline int var19 = bar (0);
|
||||
static int inline var20 = bar (1);
|
||||
extern inline int var23;
|
||||
inline int var21 = foo (6);
|
||||
inline int var22 = foo (7);
|
||||
extern inline int var23, var22;
|
||||
inline int var23 = foo (8);
|
||||
|
||||
static int v, w;
|
||||
|
||||
int
|
||||
foo (int x)
|
||||
{
|
||||
if (x != v++)
|
||||
__builtin_abort ();
|
||||
return 36 + x;
|
||||
}
|
||||
|
||||
int
|
||||
bar (int x)
|
||||
{
|
||||
if (v < 6)
|
||||
__builtin_abort ();
|
||||
if ((x >> 4) != (w >> 4))
|
||||
{
|
||||
if ((x & 15) != 0 || (w & 15) != 2)
|
||||
__builtin_abort ();
|
||||
w = x + 1;
|
||||
}
|
||||
else if (x != w++)
|
||||
__builtin_abort ();
|
||||
return 46 + x;
|
||||
}
|
||||
|
||||
int &ref1 = var1;
|
||||
int &ref2 = N::var2;
|
||||
const int &ref3 = S::var3;
|
||||
int &ref4 = S::var4;
|
||||
const int &ref5 = S::var5;
|
||||
const int &ref6 = N::var6;
|
||||
int &ref7 = var7;
|
||||
double &ref8 = N::var8;
|
||||
double &ref9 = S::var9;
|
||||
const int &ref11 = S::var11;
|
||||
int &ref12 = var12;
|
||||
int &ref13 = var13;
|
||||
int &ref14 = U::var14;
|
||||
T &ref15 = U::var15;
|
||||
T &ref16 = U::var16;
|
||||
int &ref17 = U::var17;
|
||||
const double &ref18 = U::var18;
|
||||
int &ref19 = var19;
|
||||
int &ref20 = var20;
|
||||
int &ref21 = var21;
|
||||
int &ref22 = var22;
|
||||
int &ref23 = var23;
|
||||
const int &ref24 = Y<int>::var24;
|
||||
int &ref25 = Y<int>::var25;
|
||||
int &ref26 = Y<int>::var26;
|
||||
int &ref27 = var27<int>;
|
||||
const int &ref28 = Y<int>::var28;
|
||||
const char &ref24a = Y<char>::var24;
|
||||
char &ref25a = Y<char>::var25;
|
||||
int &ref26a = Y<char>::var26;
|
||||
char &ref27a = var27<char>;
|
||||
const char &ref28a = Y<char>::var28;
|
||||
extern int &alt1;
|
||||
extern int &alt2;
|
||||
extern const int &alt3;
|
||||
extern int &alt4;
|
||||
extern const int &alt5;
|
||||
extern const int &alt6;
|
||||
extern int &alt7;
|
||||
extern double &alt8;
|
||||
extern double &alt9;
|
||||
extern const int &alt11;
|
||||
extern int &alt12;
|
||||
extern int &alt13;
|
||||
extern int &alt14;
|
||||
extern T &alt15;
|
||||
extern T &alt16;
|
||||
extern int &alt17;
|
||||
extern const double &alt18;
|
||||
extern int &alt19;
|
||||
extern int &alt20;
|
||||
extern int &alt21;
|
||||
extern int &alt22;
|
||||
extern int &alt23;
|
||||
extern const int &alt24;
|
||||
extern int &alt25;
|
||||
extern int &alt26;
|
||||
extern int &alt27;
|
||||
extern const int &alt28;
|
||||
extern const char &alt24a;
|
||||
extern char &alt25a;
|
||||
extern int &alt26a;
|
||||
extern char &alt27a;
|
||||
extern const char &alt28a;
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (v != 9)
|
||||
__builtin_abort ();
|
||||
if (var1 != 4
|
||||
|| N::var2 != 0
|
||||
|| S::var3 != 5
|
||||
|| S::var4 != 6
|
||||
|| S::var5 != 7
|
||||
|| N::var6 != 8
|
||||
|| var7 != 9
|
||||
|| N::var8 != 2.0
|
||||
|| S::var9 != 3.0
|
||||
|| sizeof (N::var10) != 1
|
||||
|| S::var11 != 11
|
||||
|| var12 != 36
|
||||
|| var13 != 37
|
||||
|| U::var14 != 38
|
||||
|| U::var15.t != 39
|
||||
|| U::var16.t != 40
|
||||
|| U::var17 != 41
|
||||
|| U::var18 != 4.0
|
||||
|| var19 != 46
|
||||
|| var20 != 47
|
||||
|| var21 != 42
|
||||
|| var22 != 43
|
||||
|| var23 != 44
|
||||
|| Y<int>::var24 != 6
|
||||
|| Y<int>::var25 != 7
|
||||
|| Y<int>::var26 != 8
|
||||
|| var27<int> != 9
|
||||
|| Y<int>::var28 != 10
|
||||
|| Y<char>::var24 != 6
|
||||
|| Y<char>::var25 != 7
|
||||
|| Y<char>::var26 != 8
|
||||
|| var27<char> != 9
|
||||
|| Y<char>::var28 != 10)
|
||||
__builtin_abort ();
|
||||
if (ref1 != 4
|
||||
|| ref2 != 0
|
||||
|| ref3 != 5
|
||||
|| ref4 != 6
|
||||
|| ref5 != 7
|
||||
|| ref6 != 8
|
||||
|| ref7 != 9
|
||||
|| alt7 != 9
|
||||
|| ref8 != 2.0
|
||||
|| alt8 != 2.0
|
||||
|| ref9 != 3.0
|
||||
|| ref11 != 11
|
||||
|| ref12 != 36
|
||||
|| ref13 != 37
|
||||
|| ref14 != 38
|
||||
|| ref15.t != 39
|
||||
|| ref16.t != 40
|
||||
|| ref17 != 41
|
||||
|| ref18 != 4.0
|
||||
|| ref19 != 46
|
||||
|| alt19 != 62
|
||||
|| ref20 != 47
|
||||
|| alt20 != 63
|
||||
|| ref21 != 42
|
||||
|| ref22 != 43
|
||||
|| ref23 != 44
|
||||
|| ref24 != 6
|
||||
|| ref25 != 7
|
||||
|| ref26 != 8
|
||||
|| ref27 != 9
|
||||
|| ref28 != 10
|
||||
|| ref24a != 6
|
||||
|| ref25a != 7
|
||||
|| ref26a != 8
|
||||
|| ref27a != 9
|
||||
|| ref28a != 10)
|
||||
__builtin_abort ();
|
||||
if (&ref1 != &alt1
|
||||
|| &ref2 != &alt2
|
||||
|| &ref3 != &alt3
|
||||
|| &ref4 != &alt4
|
||||
|| &ref5 != &alt5
|
||||
|| &ref6 != &alt6
|
||||
|| &ref7 == &alt7
|
||||
|| &ref8 == &alt8
|
||||
|| &ref9 != &alt9
|
||||
|| &ref11 != &alt11
|
||||
|| &ref12 != &alt12
|
||||
|| &ref13 != &alt13
|
||||
|| &ref14 != &alt14
|
||||
|| &ref15 != &alt15
|
||||
|| &ref16 != &alt16
|
||||
|| &ref17 != &alt17
|
||||
|| &ref18 != &alt18
|
||||
|| &ref19 == &alt19
|
||||
|| &ref20 == &alt20
|
||||
|| &ref21 != &alt21
|
||||
|| &ref22 != &alt22
|
||||
|| &ref23 != &alt23
|
||||
|| &ref24 != &alt24
|
||||
|| &ref25 != &alt25
|
||||
|| &ref26 != &alt26
|
||||
|| &ref27 != &alt27
|
||||
|| &ref28 != &alt28
|
||||
|| &ref24a != &alt24a
|
||||
|| &ref25a != &alt25a
|
||||
|| &ref26a != &alt26a
|
||||
|| &ref27a != &alt27a
|
||||
|| &ref28a != &alt28a)
|
||||
__builtin_abort ();
|
||||
}
|
46
gcc/testsuite/g++.dg/cpp1z/inline-var1.h
Normal file
46
gcc/testsuite/g++.dg/cpp1z/inline-var1.h
Normal file
@ -0,0 +1,46 @@
|
||||
inline int var1 = 4;
|
||||
static inline int var7 = 9;
|
||||
namespace N
|
||||
{
|
||||
int inline var2;
|
||||
inline const int var6 = 8;
|
||||
static inline double var8 = 2.0;
|
||||
extern inline char var10;
|
||||
}
|
||||
struct S
|
||||
{
|
||||
static constexpr int var3 = 5;
|
||||
static inline int var4 = 6;
|
||||
static constexpr int var5 = 7;
|
||||
static inline double var9 = 3.0;
|
||||
static constexpr inline int var11 = 11;
|
||||
};
|
||||
const int S::var3;
|
||||
const int S::var3;
|
||||
extern int foo (int);
|
||||
extern int bar (int);
|
||||
struct T { T () { t = foo (3); } T (int x) { t = foo (x); } int t; };
|
||||
inline int var12 = foo (0);
|
||||
int inline var13 = foo (1);
|
||||
struct U
|
||||
{
|
||||
static inline int var14 = foo (2);
|
||||
static inline T var15;
|
||||
static inline T var16 = 4;
|
||||
static int inline var17 = foo (5);
|
||||
static constexpr double var18 = 4.0;
|
||||
};
|
||||
template <typename T>
|
||||
struct Y
|
||||
{
|
||||
static constexpr T var24 = 6;
|
||||
static inline T var25 = 7;
|
||||
static inline int var26 = 8;
|
||||
static constexpr T var28 = 10;
|
||||
};
|
||||
template <typename T>
|
||||
const T Y<T>::var24;
|
||||
template <typename T>
|
||||
const T Y<T>::var24;
|
||||
template <typename T>
|
||||
inline T var27 = 9;
|
44
gcc/testsuite/g++.dg/cpp1z/inline-var1a.C
Normal file
44
gcc/testsuite/g++.dg/cpp1z/inline-var1a.C
Normal file
@ -0,0 +1,44 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-std=c++1z -Wno-deprecated -g" }
|
||||
|
||||
#include "inline-var1.h"
|
||||
|
||||
static inline int var19 = bar (16);
|
||||
static int inline var20 = bar (17);
|
||||
inline int var21 = foo (6);
|
||||
inline int var22 = foo (7);
|
||||
extern inline int var23;
|
||||
inline int var23 = foo (8);
|
||||
|
||||
int &alt1 = var1;
|
||||
int &alt2 = N::var2;
|
||||
const int &alt3 = S::var3;
|
||||
int &alt4 = S::var4;
|
||||
const int &alt5 = S::var5;
|
||||
const int &alt6 = N::var6;
|
||||
int &alt7 = var7;
|
||||
double &alt8 = N::var8;
|
||||
double &alt9 = S::var9;
|
||||
const int &alt11 = S::var11;
|
||||
int &alt12 = var12;
|
||||
int &alt13 = var13;
|
||||
int &alt14 = U::var14;
|
||||
T &alt15 = U::var15;
|
||||
T &alt16 = U::var16;
|
||||
int &alt17 = U::var17;
|
||||
const double &alt18 = U::var18;
|
||||
int &alt19 = var19;
|
||||
int &alt20 = var20;
|
||||
int &alt21 = var21;
|
||||
int &alt22 = var22;
|
||||
int &alt23 = var23;
|
||||
const int &alt24 = Y<int>::var24;
|
||||
int &alt25 = Y<int>::var25;
|
||||
int &alt26 = Y<int>::var26;
|
||||
int &alt27 = var27<int>;
|
||||
const int &alt28 = Y<int>::var28;
|
||||
const char &alt24a = Y<char>::var24;
|
||||
char &alt25a = Y<char>::var25;
|
||||
int &alt26a = Y<char>::var26;
|
||||
char &alt27a = var27<char>;
|
||||
const char &alt28a = Y<char>::var28;
|
117
gcc/testsuite/g++.dg/cpp1z/inline-var2.C
Normal file
117
gcc/testsuite/g++.dg/cpp1z/inline-var2.C
Normal file
@ -0,0 +1,117 @@
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-Wdeprecated" }
|
||||
|
||||
inline int var1 = 4; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline int var7 = 9; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
namespace N
|
||||
{
|
||||
int inline var2; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
inline const int var6 = 8; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline double var8 = 2.0; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
extern inline char var10; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
}
|
||||
struct S
|
||||
{
|
||||
static constexpr int var3 = 5;
|
||||
static inline int var4 = 6; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static constexpr int var5 = 7;
|
||||
static inline double var9 = 3.0; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static constexpr inline int var11 = 11; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
};
|
||||
const int S::var3; // { dg-warning "redundant redeclaration of" "" { target c++1z } }
|
||||
const int S::var3; // { dg-error "redefinition of" "" { target c++14_down } }
|
||||
extern int foo (int); // { dg-warning "redundant redeclaration of" "" { target c++1z } .-1 }
|
||||
extern int bar (int);
|
||||
struct T { T () { t = foo (3); } T (int x) { t = foo (x); } int t; };
|
||||
inline int var12 = foo (0); // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
int inline var13 = foo (1); // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
struct U
|
||||
{
|
||||
static inline int var14 = foo (2); // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline T var15; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline T var16 = 4; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static int inline var17 = foo (5); // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static constexpr double var18 = 4.0;
|
||||
};
|
||||
extern inline int var19; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
extern inline int var20; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
int &ref19 = var19; // { dg-error "odr-used inline variable 'var19' is not defined" "" { target *-*-* } .-2 }
|
||||
int sz20 = sizeof (var20);
|
||||
struct V
|
||||
{
|
||||
static struct A var21; // { dg-warning "inline variables are only available with" "" { target c++14_down } .+1 }
|
||||
static inline struct B var22; // { dg-error "has incomplete type" }
|
||||
static inline struct C var23 = {}; // { dg-error "has incomplete type" }
|
||||
}; // { dg-warning "inline variables are only available with" "" { target c++14_down } .-1 }
|
||||
struct W
|
||||
{
|
||||
static inline int var24; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline const int var25; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
// { dg-error "uninitialized const" "" { target *-*-* } .-1 }
|
||||
static inline int var26 = 5; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline const int var27 = 6; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline double var28 = { 4.0 }; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static const inline double var29 = { 5.0 }; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
};
|
||||
int W::var24; // { dg-error "redefinition of" }
|
||||
const int W::var25; // { dg-error "redefinition of" }
|
||||
int W::var26; // { dg-error "redefinition of" }
|
||||
const int W::var27; // { dg-error "redefinition of" }
|
||||
double W::var28; // { dg-error "redefinition of" }
|
||||
double const W::var29; // { dg-error "redefinition of" }
|
||||
struct X
|
||||
{
|
||||
inline int var30; // { dg-error "'var30' declared as an 'inline' field" }
|
||||
};
|
||||
inline typedef int TT; // { dg-error "'TT' declared as an 'inline' type" }
|
||||
int
|
||||
foo (inline int var31) // { dg-error "'var31' declared as an 'inline' parameter" }
|
||||
{
|
||||
inline int var32; // { dg-error "'inline' specifier invalid for variable 'var32' declared at block scope" }
|
||||
static inline int var33; // { dg-error "'inline' specifier invalid for variable 'var33' declared at block scope" }
|
||||
}
|
||||
template <typename A, typename B, typename C>
|
||||
struct Y
|
||||
{
|
||||
static A var34; // { dg-warning "inline variables are only available with" "" { target c++14_down } .+1 }
|
||||
static inline B var35; // { dg-error "has incomplete type" }
|
||||
static inline C var36; // { dg-error "has incomplete type" }
|
||||
}; // { dg-warning "inline variables are only available with" "" { target c++14_down } .-1 }
|
||||
struct A;
|
||||
struct B;
|
||||
struct C;
|
||||
Y<A, B, C> y;
|
||||
A *ptr34 = &Y<A, B, C>::var34;
|
||||
B *ptr35 = &Y<A, B, C>::var35;
|
||||
C *ptr36 = &Y<A, B, C>::var36;
|
||||
template <int N>
|
||||
struct Z
|
||||
{
|
||||
static inline int var37; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline const int var38; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
// { dg-error "uninitialized const" "" { target *-*-* } .-1 }
|
||||
static inline int var39 = 5; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline const int var40 = 6; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static inline double var41 = { 4.0 }; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static const inline double var42 = { 5.0 }; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
static constexpr int var43 = 5;
|
||||
static constexpr inline int var44 = 5; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
};
|
||||
template <int N>
|
||||
int Z<N>::var37; // { dg-error "redefinition of" }
|
||||
template <int N>
|
||||
const int Z<N>::var38; // { dg-error "redefinition of" }
|
||||
const int &ref38 = Z<0>::var38;
|
||||
template <int N>
|
||||
int Z<N>::var39; // { dg-error "redefinition of" }
|
||||
template <int N>
|
||||
const int Z<N>::var40; // { dg-error "redefinition of" }
|
||||
template <int N>
|
||||
double Z<N>::var41; // { dg-error "redefinition of" }
|
||||
template <int N>
|
||||
double const Z<N>::var42; // { dg-error "redefinition of" }
|
||||
template <int N>
|
||||
const int Z<N>::var43; // { dg-warning "redundant redeclaration of" "" { target c++1z } }
|
||||
template <int N> // { dg-warning "redundant redeclaration of" "" { target c++1z } .+1 }
|
||||
const int Z<N>::var43; // { dg-error "redefinition of" "" { target c++14_down } }
|
||||
Z<0> z;
|
58
gcc/testsuite/g++.dg/cpp1z/inline-var3.C
Normal file
58
gcc/testsuite/g++.dg/cpp1z/inline-var3.C
Normal file
@ -0,0 +1,58 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "-g0" }
|
||||
// Verify that inline variables and static data members that aren't odr-used
|
||||
// aren't emitted into assembly even at -O0.
|
||||
// { dg-final { scan-assembler-not "inlvarvariable" } }
|
||||
|
||||
inline int inlvarvariable1 = 1; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
const inline int inlvarvariable2 = 2; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
namespace N
|
||||
{
|
||||
int inline inlvarvariable3; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
const int inline inlvarvariable4 = 4; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
}
|
||||
struct S
|
||||
{
|
||||
static inline double inlvarvariable5 = 5.0; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
#if __cplusplus >= 201103L
|
||||
static constexpr int inlvarvariable6 = 6;
|
||||
static inline constexpr int inlvarvariable7 = 7; // { dg-warning "inline variables are only available with" "" { target { c++11 && c++14_down } } }
|
||||
#endif
|
||||
};
|
||||
template <int N> // { dg-warning "variable templates only available with" "" { target c++11_down } .+1 }
|
||||
inline int inlvarvariable8; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
template <int N> // { dg-warning "variable templates only available with" "" { target c++11_down } .+1 }
|
||||
const int inline inlvarvariable9 = 9; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
namespace N
|
||||
{
|
||||
template <int N> // { dg-warning "variable templates only available with" "" { target c++11_down } .+1 }
|
||||
int inline inlvarvariable10 = 10; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
template <int N> // { dg-warning "variable templates only available with" "" { target c++11_down } .+1 }
|
||||
const inline double inlvarvariable11 = 11.0; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
}
|
||||
template <int N>
|
||||
struct T
|
||||
{
|
||||
static inline int inlvarvariable12 = 12; // { dg-warning "inline variables are only available with" "" { target c++14_down } }
|
||||
#if __cplusplus >= 201103L
|
||||
static constexpr int inlvarvariable13 = 13;
|
||||
static inline constexpr double inlvarvariable14 = 14.0; // { dg-warning "inline variables are only available with" "" { target { c++11 && c++14_down } } }
|
||||
#endif
|
||||
};
|
||||
#if __cplusplus < 201103L
|
||||
#define decltype(x) int
|
||||
#endif
|
||||
decltype (inlvarvariable1) v1 = inlvarvariable2 + sizeof (inlvarvariable1);
|
||||
decltype (N::inlvarvariable3) v2 = N::inlvarvariable4 + sizeof (N::inlvarvariable3);
|
||||
#if __cplusplus >= 201103L
|
||||
decltype (S::inlvarvariable6) v3 = sizeof (S::inlvarvariable5) + S::inlvarvariable6 + S::inlvarvariable7;
|
||||
#else
|
||||
int v3 = sizeof (S::inlvarvariable5);
|
||||
#endif
|
||||
decltype (inlvarvariable8<2>) v4 = inlvarvariable9<2> + sizeof (inlvarvariable8<2>);
|
||||
decltype (N::inlvarvariable10<0>) v5 = sizeof (N::inlvarvariable10<0>) + sizeof (N::inlvarvariable11<0>);
|
||||
#if __cplusplus >= 201103L
|
||||
decltype (T<-1>::inlvarvariable12) v6 = sizeof (T<-1>::inlvarvariable14) + sizeof (T<-1>::inlvarvariable12) + T<-1>::inlvarvariable13;
|
||||
#else
|
||||
int v6 = sizeof (T<-1>::inlvarvariable12);
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
// { dg-do assemble }
|
||||
// GROUPS passed miscellaneous
|
||||
// test that use of `inline' is forbidden when it should be
|
||||
inline int i;// { dg-error "" } .*
|
||||
inline int i;// { dg-error "" "" { target c++14_down } } .*
|
||||
struct c { inline int i; };// { dg-error "" } .*
|
||||
int foo (inline int i);// { dg-error "" } .*
|
||||
inline class c; // { dg-error "'inline' can only be specified for functions" } inline
|
||||
|
Loading…
Reference in New Issue
Block a user