From patchwork Fri Aug 1 10:21:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Braden Obrzut X-Patchwork-Id: 375695 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id DEFB51400D7 for ; Fri, 1 Aug 2014 20:22:01 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=ZFvT6AwqcNxQyeGk3 tx7s++FzsCUzKrN3OiGXNiJTTVqaVlpP0n8D8ePK3s3RZWV2A1Of1wZWf2+I2iWT HbXQUjYEA8aG+BHGDFxPxnmfMcF8z2s+Y+9M5vZ/GXzwvNbTCgSVW89Ny5th9kb2 S6n7ur0B2JaF31J+3KMzTMMyfU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=ENmgVwjHmTgAgnQoupzAvEX vTao=; b=JeGUD58AmIFxmDDH5T7FSEITSw0tYeb0cNCjwcSwJzeelTQsNT/0/iN PTZeB3+mB070wIYRO4gijgjVpO1lR9PNqJAoTTohCIqjcLgjvECy0IP9dh+a+0er WumoAJez3RSav4JrFZiqEvu2Fc8M6orao8apFbVapjiZ5KxTOh04= Received: (qmail 18257 invoked by alias); 1 Aug 2014 10:21:52 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 18165 invoked by uid 89); 1 Aug 2014 10:21:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-ie0-f170.google.com Received: from mail-ie0-f170.google.com (HELO mail-ie0-f170.google.com) (209.85.223.170) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 01 Aug 2014 10:21:45 +0000 Received: by mail-ie0-f170.google.com with SMTP id rl12so5524519iec.15 for ; Fri, 01 Aug 2014 03:21:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-type; bh=T3SITmRwPR7RHQOosgE++7JXb7Vw92KVuWjNY5kuNDE=; b=NCG8SJzw0/OKNDA5IMXE8dvxHrZbRkYin05VazhpAy+ySde0Bi2rYKXKJficqW6jbB gKnBoMYMgneX6+RkVX39WYe90ebHClMJGQ1F+JE3j5X5z3imiBLg9cnkV8qhLcmviTm5 URh2x+uusagnZQ5VTSn1If9DWaIh1+ecz3o88Z110ryHnx+5lniaJJ0VQcYlbVhIlgYE ETZ2x5h1toJxfaS/RTztbdL+q7N8oreiWwtOL38dCvHfs7W6vKaTWN2loqrtqzOar09z wgkx6Bg5xnPkPxqd21itajUHOUKclMQeY9N+eMocI0NGqTc7FQ63vMWsz2uMVciwKtSK Hsuw== X-Gm-Message-State: ALoCoQndcKTcasV3NmvVla4Y8f9s7AadZMJdrlBtOasN8uZfbpxAVR620vY8ynONwOkCKem2miw/ X-Received: by 10.50.128.234 with SMTP id nr10mr5987047igb.3.1406888503619; Fri, 01 Aug 2014 03:21:43 -0700 (PDT) Received: from [192.168.2.199] (dynamic-acs-24-101-71-96.zoominternet.net. [24.101.71.96]) by mx.google.com with ESMTPSA id lb2sm8659780igb.6.2014.08.01.03.21.42 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 01 Aug 2014 03:21:42 -0700 (PDT) Message-ID: <53DB6A37.3040703@maniacsvault.net> Date: Fri, 01 Aug 2014 06:21:43 -0400 From: Braden Obrzut User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 MIME-Version: 1.0 To: Jason Merrill CC: Adam Butcher , Andrew Sutton , Ed Smith-Rowland <3dw4rd@verizon.net>, gcc-patches Subject: Re: Patch for constexpr variable templates References: <53CCFBEF.9080804@verizon.net> <53CDD522.9040508@maniacsvault.net> <53D172E4.9020902@redhat.com> <53D242FD.70002@maniacsvault.net> <53D2CB20.1090201@redhat.com> <53D352F7.7040402@maniacsvault.net> <53D3D34A.9080009@redhat.com> <53D3D3D9.9000102@redhat.com> <0d580e6525100d13a49b2c9327c727f8@imap.force9.net> <280a4c80527b753476c274f90ab92fa6@imap.force9.net> <53D5B03D.1010300@maniacsvault.net> <53D688DE.6020001@redhat.com> <53D78C0B.10701@maniacsvault.net> <53D9591B.9020402@redhat.com> <53D964B3.4070201@maniacsvault.net> <53DA3C32.1030600@redhat.com> In-Reply-To: <53DA3C32.1030600@redhat.com> On 07/31/2014 08:53 AM, Jason Merrill wrote: > In the original mail you mentioned doing it in cp_parser_template_id; > I agree that we probably don't want to do it there because of the > complications you are seeing. I was thinking about doing it when we > normally resolve an id-expression that refers to a variable, once we > know we're looking at an expression and not a declarator-id. But I > think my suggestion of cp_parser_id_expression was wrong, and it would > be better in finish_id_expression. > > Jason > Ahh sorry, I misread the function name you gave. finish_id_expression works just fine and doesn't require any extra work. How does this patch look? - Braden Obrzut 2014-08-01 Braden Obrzut * decl.c (grokvardecl): Handle specializations of variable templates. (grokdeclarator): Handle variable template id expressions and NULL_TREE return from grokvardecl. * decl2.c (check_member_template): Allow declaration of template member variables. * parser.c (cp_parser_template_id): Build a TEMPLATE_ID_EXPR for variable templates. * pt.c (determine_specialization): Accept variable templates. (check_template_variable): Fixed wanted template header count and change non static data member error to variable template warning. (check_explicit_specialization): Handle and check for malformed variable template specializations. (lookup_template_variable): New. (tsubst_decl): Handle variable template specializations. (do_decl_instantiation): Handle template variables. (instantiate_decl): Handle template variables. * semantics.c (finish_template_variable): New. (finish_id_expression): Instantiate variable templates. 2014-08-01 Braden Obrzut * g++.dg/cpp1y/var-templ1.C: New. * g++.dg/cpp1y/var-templ2.C: New. * g++.dg/cpp1y/var-templ3.C: New. * g++.dg/cpp1y/var-templ4.C: New. * g++.dg/cpp1y/var-templ5.C: New. * g++.dg/cpp1y/pr59638.C: Marked xfail for template variables as function pointers taking auto are considered templates at the moment. * g++.dg/parse/error50.C: Malformed statements look like variable templ. * g++.dg/template/crash71.C: Looks like variable templ. * g++.old-deja/g++.oliva/template10.C: Looks like variable templ. * g++.old-deja/g++.pt/var1.C: Non-constexpr variable templ. 2013-03-29 Gabriel Dos Reis * cp-tree.h (variable_template_p): Do not check scope. * pt.c (check_template_variable): Fix thinko from previous change. (push_template_decl_real): Fix formatting. 2013-03-29 Gabriel Dos Reis * cp-tree.h (variable_template_p): New. * pt.c (check_template_variable): Accept variable temploids at non-class scope. (push_template_decl_real): The current instantiation of a template can be a VAR_DECL. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a5cb98..caaaa6c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5027,6 +5027,17 @@ class_of_this_parm (const_tree fntype) return TREE_TYPE (type_of_this_parm (fntype)); } +/* True if T designates a variable template declaration. */ +inline bool +variable_template_p (tree t) +{ + if (TREE_CODE (t) != TEMPLATE_DECL) + return false; + if (tree r = DECL_TEMPLATE_RESULT (t)) + return VAR_P (r); + return false; +} + /* A parameter list indicating for a function with no parameters, e.g "int f(void)". */ extern cp_parameter_declarator *no_parameters; @@ -5554,6 +5565,7 @@ extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); extern tree lookup_template_function (tree, tree); +extern tree lookup_template_variable (tree, tree); extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern bool in_template_function (void); @@ -5816,6 +5828,7 @@ extern tree perform_koenig_lookup (tree, vec *, tsubst_flags_t); extern tree finish_call_expr (tree, vec **, bool, bool, tsubst_flags_t); +extern tree finish_template_variable (tree); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dae85c2..2ac0472 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -80,8 +80,8 @@ static int ambi_op_p (enum tree_code); 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, const cp_decl_specifier_seq *, - int, int, tree); +static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *, + 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); @@ -7943,9 +7943,11 @@ set_linkage_for_static_data_member (tree decl) static tree grokvardecl (tree type, tree name, + tree orig_declarator, const cp_decl_specifier_seq *declspecs, int initialized, int constp, + int template_count, tree scope) { tree decl; @@ -7975,7 +7977,10 @@ grokvardecl (tree type, || (TREE_CODE (scope) == NAMESPACE_DECL && current_lang_name != lang_name_cplusplus) /* Similarly for static data members. */ - || TYPE_P (scope))) + || TYPE_P (scope) + /* Similarly for explicit specializations. */ + || (orig_declarator + && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR))) decl = build_lang_decl (VAR_DECL, name, type); else decl = build_decl (input_location, VAR_DECL, name, type); @@ -8043,7 +8048,14 @@ grokvardecl (tree type, else DECL_INTERFACE_KNOWN (decl) = 1; - return decl; + // Handle explicit specializations and instantiations of variable templates. + if (orig_declarator) + { + decl = check_explicit_specialization (orig_declarator, decl, + template_count, 0); + } + + return decl != error_mark_node ? decl : NULL_TREE; } /* Create and return a canonical pointer to member function type, for @@ -8944,8 +8956,13 @@ grokdeclarator (const cp_declarator *declarator, dname = fns; if (!identifier_p (dname)) { - gcc_assert (is_overloaded_fn (dname)); - dname = DECL_NAME (get_first_fn (dname)); + if (variable_template_p (dname)) + dname = DECL_NAME (dname); + else + { + gcc_assert (is_overloaded_fn (dname)); + dname = DECL_NAME (get_first_fn (dname)); + } } } /* Fall through. */ @@ -9986,7 +10003,8 @@ grokdeclarator (const cp_declarator *declarator, if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR && TREE_CODE (type) != FUNCTION_TYPE - && TREE_CODE (type) != METHOD_TYPE) + && TREE_CODE (type) != METHOD_TYPE + && !variable_template_p (TREE_OPERAND (unqualified_id, 0))) { error ("template-id %qD used as a declarator", unqualified_id); @@ -10876,11 +10894,15 @@ grokdeclarator (const cp_declarator *declarator, /* It's a variable. */ /* An uninitialized decl with `extern' is a reference. */ - decl = grokvardecl (type, unqualified_id, + decl = grokvardecl (type, dname, unqualified_id, declspecs, initialized, (type_quals & TYPE_QUAL_CONST) != 0, + template_count, ctype ? ctype : in_namespace); + if (decl == NULL_TREE) + return error_mark_node; + bad_specifiers (decl, BSP_VAR, virtualp, memfn_quals != TYPE_UNQUALIFIED, inlinep, friendp, raises != NULL_TREE); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0926dbc..5f4a644 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -529,6 +529,8 @@ check_member_template (tree tmpl) with member templates. */ DECL_IGNORED_P (tmpl) = 1; } + else if (variable_template_p (tmpl)) + /* OK */; else error ("template declaration of %q#D", decl); } diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 72f987e..2551e06 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -13558,6 +13558,10 @@ cp_parser_template_id (cp_parser *parser, template_id = finish_template_type (templ, arguments, entering_scope); } + else if (variable_template_p (templ)) + { + template_id = lookup_template_variable (templ, arguments); + } else { /* If it's not a class-template or a template-template, it should be diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7b79280..2d8a689 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -1878,11 +1878,16 @@ determine_specialization (tree template_id, if (BASELINK_P (fns)) fns = BASELINK_FUNCTIONS (fns); - if (!is_overloaded_fn (fns)) + if (TREE_CODE (decl) == FUNCTION_DECL && !is_overloaded_fn (fns)) { error ("%qD is not a function template", fns); return error_mark_node; } + else if (VAR_P (decl) && !variable_template_p (fns)) + { + error ("%qD is not a variable template", fns); + return error_mark_node; + } /* Count the number of template headers specified for this specialization. */ @@ -1892,7 +1897,12 @@ determine_specialization (tree template_id, b = b->level_chain) ++header_count; - for (; fns; fns = OVL_NEXT (fns)) + if (variable_template_p (fns)) + { + templates = tree_cons (explicit_targs, fns, templates); + } + else + for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); @@ -2308,9 +2318,16 @@ check_template_variable (tree decl) tree ctx = CP_DECL_CONTEXT (decl); int wanted = num_template_headers_for_class (ctx); if (!TYPE_P (ctx) || !CLASSTYPE_TEMPLATE_INFO (ctx)) - permerror (DECL_SOURCE_LOCATION (decl), - "%qD is not a static data member of a class template", decl); - else if (template_header_count > wanted) + { + if (cxx_dialect < cxx1y) + pedwarn (DECL_SOURCE_LOCATION (decl), 0, + "variable templates only available with " + "-std=c++1y or -std=gnu++1y"); + + // Namespace-scope variable templates should have a template header. + ++wanted; + } + if (template_header_count > wanted) { bool warned = pedwarn (DECL_SOURCE_LOCATION (decl), 0, "too many template headers for %D (should be %d)", @@ -2442,6 +2459,13 @@ check_explicit_specialization (tree declarator, /* Fall through. */ case tsk_expl_spec: + if (VAR_P (decl) && TREE_CODE (declarator) != TEMPLATE_ID_EXPR) + { + // In cases like template<> constexpr bool v = true; + error ("%qD is not a template variable", dname); + break; + } + SET_DECL_TEMPLATE_SPECIALIZATION (decl); if (ctype) member_specialization = 1; @@ -2481,7 +2505,10 @@ check_explicit_specialization (tree declarator, gcc_unreachable (); } - if (specialization || member_specialization) + if ((specialization || member_specialization) + /* Variable templates don't apply. */ + && (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)) { tree t = TYPE_ARG_TYPES (TREE_TYPE (decl)); for (; t; t = TREE_CHAIN (t)) @@ -2566,6 +2593,10 @@ check_explicit_specialization (tree declarator, else if (ctype != NULL_TREE && (identifier_p (TREE_OPERAND (declarator, 0)))) { + // Ignore variable templates + if (VAR_P (decl)) + return decl; + /* Find the list of functions in ctype that have the same name as the declared function. */ tree name = TREE_OPERAND (declarator, 0); @@ -2691,7 +2722,8 @@ check_explicit_specialization (tree declarator, /* If we thought that the DECL was a member function, but it turns out to be specializing a static member function, make DECL a static member function as well. */ - if (DECL_STATIC_FUNCTION_P (tmpl) + if (DECL_FUNCTION_TEMPLATE_P (tmpl) + && DECL_STATIC_FUNCTION_P (tmpl) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) revert_static_member_fn (decl); @@ -2725,7 +2757,8 @@ check_explicit_specialization (tree declarator, /* Inherit default function arguments from the template DECL is specializing. */ - copy_default_args_to_explicit_spec (decl); + if (DECL_FUNCTION_TEMPLATE_P (tmpl)) + copy_default_args_to_explicit_spec (decl); /* This specialization has the same protection as the template it specializes. */ @@ -2794,6 +2827,7 @@ check_explicit_specialization (tree declarator, /* A 'structor should already have clones. */ gcc_assert (decl == error_mark_node + || variable_template_p (tmpl) || !(DECL_CONSTRUCTOR_P (decl) || DECL_DESTRUCTOR_P (decl)) || DECL_CLONED_FUNCTION_P (DECL_CHAIN (decl))); @@ -4738,6 +4772,14 @@ push_template_decl_real (tree decl, bool is_friend) && TYPE_DECL_ALIAS_P (decl)) /* alias-declaration */ gcc_assert (!DECL_ARTIFICIAL (decl)); + else if (VAR_P (decl)) + { + if (!DECL_DECLARED_CONSTEXPR_P (decl)) + { + sorry ("template declaration of non-constexpr variable %qD", decl); + return error_mark_node; + } + } else { error ("template declaration of %q#D", decl); @@ -7899,6 +7941,14 @@ lookup_template_class (tree d1, tree arglist, tree in_decl, tree context, timevar_pop (TV_TEMPLATE_INST); return ret; } + +/* Return a TEMPLATE_ID_EXPR for the given variable template and ARGLIST. */ + +tree +lookup_template_variable (tree templ, tree arglist) +{ + return build2 (TEMPLATE_ID_EXPR, TREE_TYPE (templ), templ, arglist); +} struct pair_fn_data { @@ -10466,7 +10516,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) if (PRIMARY_TEMPLATE_P (t)) DECL_PRIMARY_TEMPLATE (r) = r; - if (TREE_CODE (decl) != TYPE_DECL) + if (TREE_CODE (decl) != TYPE_DECL && TREE_CODE (decl) != VAR_DECL) /* Record this non-type partial instantiation. */ register_specialization (r, t, DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)), @@ -19146,7 +19196,11 @@ do_decl_instantiation (tree decl, tree storage) error ("explicit instantiation of non-template %q#D", decl); return; } - else if (VAR_P (decl)) + + bool var_templ = (DECL_TEMPLATE_INFO (decl) + && variable_template_p (DECL_TI_TEMPLATE (decl))); + + if (VAR_P (decl) && !var_templ) { /* There is an asymmetry here in the way VAR_DECLs and FUNCTION_DECLs are handled by grokdeclarator. In the case of @@ -19175,7 +19229,7 @@ do_decl_instantiation (tree decl, tree storage) return; } } - else if (TREE_CODE (decl) != FUNCTION_DECL) + else if (TREE_CODE (decl) != FUNCTION_DECL && !var_templ) { error ("explicit instantiation of %q#D", decl); return; @@ -19885,10 +19939,12 @@ instantiate_decl (tree d, int defer_ok, tree ns; tree init; bool const_init = false; + bool enter_context = DECL_CLASS_SCOPE_P (d); ns = decl_namespace_context (d); push_nested_namespace (ns); - push_nested_class (DECL_CONTEXT (d)); + if (enter_context) + push_nested_class (DECL_CONTEXT (d)); init = tsubst_expr (DECL_INITIAL (code_pattern), args, tf_warning_or_error, NULL_TREE, @@ -19900,7 +19956,8 @@ instantiate_decl (tree d, int defer_ok, cp_finish_decl (d, init, /*init_const_expr_p=*/const_init, /*asmspec_tree=*/NULL_TREE, LOOKUP_ONLYCONVERTING); - pop_nested_class (); + if (enter_context) + pop_nested_class (); pop_nested_namespace (ns); } @@ -19997,10 +20054,15 @@ instantiate_decl (tree d, int defer_ok, DECL_EXTERNAL (d) = 0; /* Enter the scope of D so that access-checking works correctly. */ - push_nested_class (DECL_CONTEXT (d)); + bool enter_context = DECL_CLASS_SCOPE_P (d); + if (enter_context) + push_nested_class (DECL_CONTEXT (d)); + const_init = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (code_pattern); cp_finish_decl (d, init, const_init, NULL_TREE, 0); - pop_nested_class (); + + if (enter_context) + pop_nested_class (); } else if (TREE_CODE (d) == FUNCTION_DECL && DECL_DEFAULTED_FN (code_pattern)) synthesize_method (d); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index a6d941b..5438608 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2418,6 +2418,15 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, return result; } +/* Instantiate a variable declaration from a TEMPLATE_ID_EXPR for use. */ + +tree +finish_template_variable (tree var) +{ + return instantiate_template (TREE_OPERAND (var, 0), TREE_OPERAND (var, 1), + tf_error); +} + /* Finish a call to a postfix increment or decrement or EXPR. (Which is indicated by CODE, which should be POSTINCREMENT_EXPR or POSTDECREMENT_EXPR.) */ @@ -3500,6 +3509,11 @@ finish_id_expression (tree id_expression, a call to its wrapper. */ decl = build_cxx_call (wrap, 0, NULL, tf_warning_or_error); } + else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR + && variable_template_p (TREE_OPERAND (decl, 0))) + { + decl = finish_template_variable (decl); + } else if (scope) { decl = (adjust_result_of_qualified_name_lookup diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59638.C b/gcc/testsuite/g++.dg/cpp1y/pr59638.C index 0125bdc..a4c63ac 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr59638.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr59638.C @@ -1,10 +1,11 @@ // PR c++/59638 // { dg-do compile { target c++1y } } // { dg-options "" } +// { dg-excess-errors "sorry" } -void (*a)(auto); // { dg-error "template declaration" } +void (*a)(auto); // { dg-error "" "" { xfail *-*-* } } -void (*b)(auto) = 0; // { dg-error "template declaration" } +void (*b)(auto) = 0; // { dg-error "" "" { xfail *-*-* } } typedef void (*f)(auto); // { dg-error "template declaration" } diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ1.C b/gcc/testsuite/g++.dg/cpp1y/var-templ1.C new file mode 100644 index 0000000..9219303 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ1.C @@ -0,0 +1,22 @@ +// { dg-do run } +// { dg-options "-std=c++1y" } + +template + struct S1 + { + static constexpr int a = A; + static constexpr int b = B; + }; + +template + constexpr int var = T::a + T::b; + +int main () +{ + int v = var>/2; + return !( + var> == v + && var> == var>>> + && var> != 222 + ); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ2.C b/gcc/testsuite/g++.dg/cpp1y/var-templ2.C new file mode 100644 index 0000000..315ac3e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ2.C @@ -0,0 +1,34 @@ +// { dg-do compile } +// { dg-options "-std=c++1y" } + +// Template variables and static member variables of template classes are +// often confused. + +template + struct S1 + { + static int n; + static int arr[]; + }; + +template + constexpr int var = sizeof (T); + +template + int S1::n = sizeof (T); + +template + int S1::arr[sizeof (T)]; + +template<> + int S1::n = 8; + +template<> + int S1::arr[8]; + +int main () +{ + S1 v1; + var>; + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ3.C b/gcc/testsuite/g++.dg/cpp1y/var-templ3.C new file mode 100644 index 0000000..d3fbad4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ3.C @@ -0,0 +1,19 @@ +// { dg-do run } +// { dg-options "-std=c++1y" } + +template + constexpr int var = sizeof (T); + +template + struct S1 + { + template + static constexpr int a = sizeof (U) + sizeof (T); + }; + +int main () +{ + return !( + var + var == S1::a + ); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ4.C b/gcc/testsuite/g++.dg/cpp1y/var-templ4.C new file mode 100644 index 0000000..1d6cf1d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ4.C @@ -0,0 +1,16 @@ +// { dg-do run } +// { dg-options "-std=c++1y" } + +template + constexpr int var = sizeof (T); + +template<> + constexpr int var = 100000; + +int main () +{ + return !( + var == 100000 + && var == sizeof(char) + ); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ5.C b/gcc/testsuite/g++.dg/cpp1y/var-templ5.C new file mode 100644 index 0000000..32d0ee1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ5.C @@ -0,0 +1,23 @@ +// { dg-do run } +// { dg-options "-std=c++1y" } + +template + struct S1 + { + static constexpr int a = A; + static constexpr int b = B; + }; + +template + constexpr int var = T::a + T::b; + +template class T, int A> + constexpr int var2 = var> + A; + +int main () +{ + return !( + var2 == 120 + ); +} + diff --git a/gcc/testsuite/g++.dg/parse/error50.C b/gcc/testsuite/g++.dg/parse/error50.C index dbd8958..f9c42dd 100644 --- a/gcc/testsuite/g++.dg/parse/error50.C +++ b/gcc/testsuite/g++.dg/parse/error50.C @@ -15,4 +15,4 @@ struct B static T i; }; -template<> template <> int B::i; // { dg-error "should be 1" } +template<> template <> int B::i; // { dg-error "template|should be 1" } diff --git a/gcc/testsuite/g++.dg/template/crash71.C b/gcc/testsuite/g++.dg/template/crash71.C index 86aa152..3ac862e 100644 --- a/gcc/testsuite/g++.dg/template/crash71.C +++ b/gcc/testsuite/g++.dg/template/crash71.C @@ -1,3 +1,3 @@ // PR c++/30659 -extern "C" template A foo(); // { dg-error "forbids|static data|expected" } +extern "C" template A foo(); // { dg-error "forbids|static data|expected|template" } diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/template10.C b/gcc/testsuite/g++.old-deja/g++.oliva/template10.C index 5c1204b..168a003 100644 --- a/gcc/testsuite/g++.old-deja/g++.oliva/template10.C +++ b/gcc/testsuite/g++.old-deja/g++.oliva/template10.C @@ -19,4 +19,4 @@ template<> struct A { }; bool A::a = true; // ok -template<> bool A::b = false; // { dg-error "template header" } +template<> bool A::b = false; // { dg-error "template (header|variable)" } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/var1.C b/gcc/testsuite/g++.old-deja/g++.pt/var1.C index a15743d..ec91bc4 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/var1.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/var1.C @@ -1,4 +1,5 @@ // { dg-do assemble } // Origin: Jason Merrill +// { dg-excess-errors "sorry" } -template T t; // { dg-error "" } template declaration of t +template T t; // template declaration of t