From patchwork Mon Aug 8 19:52:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dodji Seketeli X-Patchwork-Id: 109094 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]) by ozlabs.org (Postfix) with SMTP id 7B08DB6F69 for ; Tue, 9 Aug 2011 05:52:54 +1000 (EST) Received: (qmail 23407 invoked by alias); 8 Aug 2011 19:52:52 -0000 Received: (qmail 23390 invoked by uid 22791); 8 Aug 2011 19:52:48 -0000 X-SWARE-Spam-Status: No, hits=-4.1 required=5.0 tests=AWL, BAYES_50, KAM_STOCKGEN, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_CX, TW_TM X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 08 Aug 2011 19:52:33 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p78JqWmO019201 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 8 Aug 2011 15:52:32 -0400 Received: from localhost (ovpn-113-89.phx2.redhat.com [10.3.113.89]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p78JqVsl006687 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 8 Aug 2011 15:52:32 -0400 Received: by localhost (Postfix, from userid 500) id 4E41C29C06A; Mon, 8 Aug 2011 21:52:30 +0200 (CEST) From: Dodji Seketeli To: Jason Merrill Cc: Paolo Carlini , GCC Patches Subject: Re: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning References: <4E325AAC.9010006@redhat.com> <4E3E08D0.6060901@redhat.com> X-URL: http://www.redhat.com Date: Mon, 08 Aug 2011 21:52:30 +0200 In-Reply-To: <4E3E08D0.6060901@redhat.com> (Jason Merrill's message of "Sat, 06 Aug 2011 23:38:56 -0400") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 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 Hello, Jason Merrill writes: > On 08/06/2011 06:57 AM, Dodji Seketeli wrote: > > @@ -4340,6 +4340,8 @@ c_sizeof_or_alignof_type (location_t loc, > > value = fold_convert_loc (loc, size_type_node, value); > > gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value))); > > > > + maybe_record_local_typedef_use (type); > > Why is this still needed? It is not. I just forgot to remove it. Done now. > > > +/* Return TRUE if DECL is declared in the current function. */ > > + > > +bool > > +local_decl_p (tree decl) > > I don't think we need to work so hard to compare contexts to > current_function_decl; just checking that the decl is in some function > should be enough, i.e. decl_function_context is non-null. Thanks. I didn't know about decl_function_context. I grepped for functions containing "local" in their names but I was doomed to failure. I am using that now. > > > + static int unused_local_typedefs_warn_count; > > This could use a comment. Added. > > > +/* If T is a typedef variant type or a TYPE_DECL declared locally, > > + mark it as used. */ > > + > > +void > > +maybe_record_local_typedef_use (tree t) > > Does this still need to handle types? And the meaning of TREE_USED > shouldn't change depending on a warning flag or whether a decl is > local or not; let's just mark all TYPE_DECLs as used. OK, done. > > Seems like we don't need local_decl_p at all; at the definition point, > if we're in a function, a new declaration must be local enough for our > purposes. > > > +void > > +cp_maybe_record_local_typedef_use (tree t) > > +{ > > + /* If the current function is being instantiated, bail out. */ > > As above, I think we shouldn't put so many conditions on setting > TREE_USED. I have removed cp_maybe_record_local_typedef_use altogether and just use maybe_record_typedef_use now. > > > @@ -19572,6 +19572,9 @@ cp_parser_lookup_name (cp_parser *parser, tree name, > > if (DECL_P (decl)) > > check_accessibility_of_qualified_id (decl, object_type, parser->scope); > > > > + cp_maybe_record_local_typedef_use (decl); > > + cp_maybe_record_local_typedef_use (parser->scope); > > Why do we need to handle parser->scope? Wasn't it previously looked up? Sigh, my bad.. Fixed. Below is the updated patch that passed bootstrap and regression tests on x86_64-unknown-linux-gnu against trunk. Thanks. From: Dodji Seketeli Date: Mon, 25 Jul 2011 19:02:07 +0200 Subject: [PATCH] PR c++/33255 - Support -Wunused-local-typedefs warning gcc/ * c-decl.c (lookup_name): Use the new maybe_record_typedef_use. (pushdecl): Use the new record_locally_defined_typedef. (store_parm_decls): Allocate cfun->language. (finish_function): Use the new maybe_warn_unused_local_typedefs, and mark cfun->language to be collected. (c_push_function_context): Allocate cfun->language here only if needed. (c_pop_function_context): Likewise, mark cfun->language for collection only when it should be done. * c-typeck.c (c_expr_sizeof_type, c_cast_expr): Use the new maybe_record_local_typedef_use. gcc/c-family * c-common.h (struct c_language_function::local_typedefs): New field. (record_locally_defined_typedef, maybe_record_typedef_use) (maybe_warn_unused_local_typedefs): Declare new functions. * c-common.c (record_locally_defined_typedef) (maybe_record_typedef_use) (maybe_warn_unused_local_typedefs): Define new functions. * c.opt: Declare new -Wunused-local-typedefs flag. gcc/cp * name-lookup.c (pushdecl_maybe_friend_1): Use the new record_locally_defined_typedef. * decl.c (finish_function): Use the new maybe_warn_unused_local_typedefs. (grokfield): Use the new record_locally_defined_typedef. * parser.c (lookup_name): Use the new maybe_record_typedef_use. gcc/doc/ * invoke.texi: Update documentation for -Wunused-local-typedefs. gcc/testsuite/ * g++.dg/warn/Wunused-local-typedefs.C: New test file. * c-c++-common/Wunused-local-typedefs.c: Likewise. libstdc++-v3/ * include/ext/bitmap_allocator.h (__detail::__mini_vector::__lower_bound): Remove unused typedef. * src/istream.cc (std::operator>>(basic_istream& __in, basic_string& __str)): Likewise. (std::getline): Likewise. * src/valarray.cc (__valarray_product): Likewise. --- gcc/c-decl.c | 38 +++++- gcc/c-family/c-common.c | 71 ++++++++++ gcc/c-family/c-common.h | 7 + gcc/c-family/c.opt | 4 + gcc/cp/decl.c | 4 + gcc/cp/decl2.c | 1 + gcc/cp/name-lookup.c | 7 + gcc/cp/parser.c | 2 + gcc/doc/invoke.texi | 9 +- .../c-c++-common/Wunused-local-typedefs.c | 38 +++++ gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C | 146 ++++++++++++++++++++ libstdc++-v3/include/ext/bitmap_allocator.h | 2 - libstdc++-v3/src/istream.cc | 3 - libstdc++-v3/src/valarray.cc | 1 - 14 files changed, 319 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/Wunused-local-typedefs.c create mode 100644 gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 33d2615..230f1a7 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2769,7 +2769,15 @@ pushdecl (tree x) skip_external_and_shadow_checks: if (TREE_CODE (x) == TYPE_DECL) - set_underlying_type (x); + { + /* So this is a typedef, set its underlying type. */ + set_underlying_type (x); + + /* If X is a typedef defined in the current function, record it + for the purpose of implementing the -Wunused-local-typedefs + warning. */ + record_locally_defined_typedef (x); + } bind (name, x, scope, /*invisible=*/false, nested, locus); @@ -3435,7 +3443,10 @@ lookup_name (tree name) { struct c_binding *b = I_SYMBOL_BINDING (name); if (b && !b->invisible) - return b->decl; + { + maybe_record_typedef_use (b->decl); + return b->decl; + } return 0; } @@ -8158,6 +8169,9 @@ store_parm_decls (void) /* Initialize the RTL code for the function. */ allocate_struct_function (fndecl, false); + if (warn_unused_local_typedefs) + cfun->language = ggc_alloc_cleared_language_function (); + /* Begin the statement tree for this function. */ DECL_SAVED_TREE (fndecl) = push_stmt_list (); @@ -8265,6 +8279,10 @@ finish_function (void) "parameter %qD set but not used", decl); } + /* Complain about locally defined typedefs that are not used in this + function. */ + maybe_warn_unused_local_typedefs (); + /* Store the end of the function, so that we get good line number info for the epilogue. */ cfun->function_end_locus = input_location; @@ -8310,6 +8328,8 @@ finish_function (void) if (!decl_function_context (fndecl)) undef_nested_function = false; + cfun->language = NULL; + /* We're leaving the context of this function, so zap cfun. It's still in DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation. */ @@ -8421,9 +8441,11 @@ check_for_loop_decls (location_t loc, bool turn_off_iso_c99_error) void c_push_function_context (void) { - struct language_function *p; - p = ggc_alloc_language_function (); - cfun->language = p; + struct language_function *p = cfun->language; + /* cfun->language might have been already allocated by the use of + -Wunused-local-typedefs. In that case, just re-use it. */ + if (p == NULL) + cfun->language = p = ggc_alloc_cleared_language_function (); p->base.x_stmt_tree = c_stmt_tree; c_stmt_tree.x_cur_stmt_list @@ -8449,7 +8471,11 @@ c_pop_function_context (void) pop_function_context (); p = cfun->language; - cfun->language = NULL; + /* When -Wunused-local-typedefs is in effect, cfun->languages is + used to store data throughout the life time of the current cfun, + So don't deallocate it. */ + if (!warn_unused_local_typedefs) + cfun->language = NULL; if (DECL_STRUCT_FUNCTION (current_function_decl) == 0 && DECL_SAVED_TREE (current_function_decl) == NULL_TREE) diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 96275ba..290240a 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -9604,6 +9604,77 @@ record_types_used_by_current_var_decl (tree decl) } } +/* If DECL is a typedef that is declared in the current function, + record it for the purpose of -Wunused-local-typedefs. */ + +void +record_locally_defined_typedef (tree decl) +{ + struct c_language_function *l; + + if (!warn_unused_local_typedefs + || cfun == NULL + /* if this is not a locally defined typedef then we are not + interested. */ + || !is_typedef_decl (decl) + || !decl_function_context (decl)) + return; + + l = (struct c_language_function *) cfun->language; + VEC_safe_push (tree, gc, l->local_typedefs, decl); +} + +/* If T is a TYPE_DECL declared locally, mark it as used. */ + +void +maybe_record_typedef_use (tree t) +{ + /* We want T to be either a type or a TYPE_DECL. */ + if (!is_typedef_decl (t)) + return; + + TREE_USED (t) = true; +} + +/* Warn if there are some unused locally defined typedefs in the + current function. */ + +void +maybe_warn_unused_local_typedefs (void) +{ + int i; + tree decl; + /* The number of times we have emitted -Wunused-local-typedefs + warnings. If this is different from errorcount, that means some + unrelated errors have been issued. In which case, we'll avoid + emitting "unused-local-typedefs" warnings. */ + static int unused_local_typedefs_warn_count; + struct c_language_function *l; + + if (cfun == NULL) + return; + + if ((l = (struct c_language_function *) cfun->language) == NULL) + return; + + if (warn_unused_local_typedefs + && errorcount == unused_local_typedefs_warn_count) + { + FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl) + if (!TREE_USED (decl)) + warning_at (DECL_SOURCE_LOCATION (decl), + OPT_Wunused_local_typedefs, + "typedef %qD locally defined but not used", decl); + unused_local_typedefs_warn_count = errorcount; + } + + if (l->local_typedefs) + { + VEC_free (tree, gc, l->local_typedefs); + l->local_typedefs = NULL; + } +} + /* The C and C++ parsers both use vectors to hold function arguments. For efficiency, we keep a cache of unused vectors. This is the cache. */ diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 3a49779..6b324d4 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -505,6 +505,10 @@ struct GTY(()) c_language_function { /* While we are parsing the function, this contains information about the statement-tree that we are building. */ struct stmt_tree_s x_stmt_tree; + + /* Vector of locally defined typedefs, for + -Wunused-local-typedefs. */ + VEC(tree,gc) *local_typedefs; }; #define stmt_list_stack (current_stmt_tree ()->x_cur_stmt_list) @@ -986,6 +990,9 @@ extern void warn_for_sign_compare (location_t, extern void do_warn_double_promotion (tree, tree, tree, const char *, location_t); extern void set_underlying_type (tree); +extern void record_locally_defined_typedef (tree); +extern void maybe_record_typedef_use (tree); +extern void maybe_warn_unused_local_typedefs (void); extern VEC(tree,gc) *make_tree_vector (void); extern void release_tree_vector (VEC(tree,gc) *); extern VEC(tree,gc) *make_tree_vector_single (tree); diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 617ea2d..e6ac5dc 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -653,6 +653,10 @@ Wunsuffixed-float-constants C ObjC Var(warn_unsuffixed_float_constants) Warning Warn about unsuffixed float constants +Wunused-local-typedefs +C ObjC C++ ObjC++ Var(warn_unused_local_typedefs) Warning +Warn about + Wunused-macros C ObjC C++ ObjC++ Warning Warn about macros defined in the main file that are not used diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f0d1a1a..cc06682 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13385,6 +13385,10 @@ finish_function (int flags) unused_but_set_errorcount = errorcount; } + /* Complain about locally defined typedefs that are not used in this + function. */ + maybe_warn_unused_local_typedefs (); + /* Genericize before inlining. */ if (!processing_template_decl) { diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index f05b0f8..68e9b9b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -868,6 +868,7 @@ grokfield (const cp_declarator *declarator, && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value) set_underlying_type (value); + record_locally_defined_typedef (value); return value; } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 1afd9ed..512480c 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -868,6 +868,13 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) && TYPE_NAME (type) && TYPE_IDENTIFIER (type)) set_identifier_type_value (DECL_NAME (x), x); + + /* If this is a locally defined typedef in a function that + is not a template instantation, record it to implement + -Wunused-local-typedefs. */ + if (current_instantiation () == NULL + || (current_instantiation ()->decl != current_function_decl)) + record_locally_defined_typedef (x); } /* Multiple external decls of the same identifier ought to match. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9b3e56d..ba27acc 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -19572,6 +19572,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name, if (DECL_P (decl)) check_accessibility_of_qualified_id (decl, object_type, parser->scope); + maybe_record_typedef_use (decl); + return decl; } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6fd78d5..5430803 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -267,8 +267,9 @@ Objective-C and Objective-C++ Dialects}. -Wsystem-headers -Wtrampolines -Wtrigraphs -Wtype-limits -Wundef @gol -Wuninitialized -Wunknown-pragmas -Wno-pragmas @gol -Wunsuffixed-float-constants -Wunused -Wunused-function @gol --Wunused-label -Wunused-parameter -Wno-unused-result -Wunused-value @gol --Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable @gol +-Wunused-label -Wunused-local-typedefs -Wunused-parameter @gol +-Wno-unused-result -Wunused-value @gol -Wunused-variable @gol +-Wunused-but-set-parameter -Wunused-but-set-variable @gol -Wvariadic-macros -Wvla -Wvolatile-register-var -Wwrite-strings} @item C and Objective-C-only Warning Options @@ -3499,6 +3500,10 @@ This warning is enabled by @option{-Wall}. To suppress this warning use the @samp{unused} attribute (@pxref{Variable Attributes}). +@item -Wunused-local-typedefs @r{(C, Objective-C, C++ and Objective-C++ only)} +@opindex Wunused-local-typedefs +Warn when a typedef locally defined in a function is not used. + @item -Wunused-parameter @opindex Wunused-parameter @opindex Wno-unused-parameter diff --git a/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c new file mode 100644 index 0000000..32fb723 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wunused-local-typedefs.c @@ -0,0 +1,38 @@ +/* Origin PR c++/33255 + { dg-options "-Wunused-local-typedefs" } + { dg-do compile } +*/ + +void +test_warn () +{ + typedef int foo; // { dg-warning "locally defined but not used" } +} + +void +test0 () +{ + typedef int foo; + foo var __attribute__((unused)); +} + +void +test1 () +{ + typedef int foo; + const foo *var = 0; +} + +void +test2 () +{ + typedef int foo; + void func(foo); +} + +void +test7 (void) +{ + typedef int foo; + int vec[1] = {sizeof (foo)}; +} diff --git a/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C new file mode 100644 index 0000000..87feb52 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wunused-local-typedefs.C @@ -0,0 +1,146 @@ +// Origin PR c++/33255 +// { dg-options "-Wunused-local-typedefs" } +// { dg-do compile } + +void +test_warn() +{ + typedef int foo; // { dg-warning "locally defined but not used" } +} + +struct S +{ + typedef int T; + S() {} + S(int) {} +}; + +template +struct ST +{ + typedef T type; + ST (int) {} + ST () {} +}; + +template +void +test0_tmpl(void) +{ + typedef struct ST foo; + foo(2); +} + +int +test0(void) +{ + test0_tmpl(); +} + +void +test1(void) +{ + typedef int foo; + ST a; +} + + +int +test2(void) +{ + typedef S foo; + foo::T i = 0; + return i; +} + +template +void +test3_tmpl(void) +{ + typedef struct ST foo; + ST v; + const foo &var = v; +} + +void +test3(void) +{ + test3_tmpl(); +} + +void +test4(void) +{ + typedef int foo; + int vec[1] = {sizeof (foo)}; +} + +void +test5(void) +{ + typedef int T0; + typedef char T1; + typedef int* T2; + typedef unsigned T3; + struct C0 { virtual void f(void) {}}; + struct C1 : C0 {}; + typedef C0 T4; + + int v0 = (T0) 2; + char v1 = static_cast (0); + reinterpret_cast (&v0); + unsigned* const c = 0; + unsigned* v2 = const_cast (c); + C0 *p0 = 0; + C1 *p1 = 0; + p0 = dynamic_cast (p1); +} + +void +test6(void) +{ + struct C0 {}; + typedef C0 foo; + C0 *v = new foo; +} + +template +struct S7 +{ + void + f() + { + typedef int foo; + sizeof(foo); + } +}; + +template +void +test7(void) +{ + typedef typename ST::T bar; // { dg-warning "locally defined but not used" } + typedef typename ST::T foo; // We shouldn't warn for this one, as + // it's used below. + S7 v; +} + + +template +void +test8(void) +{ + int f(S7); + void g(int); + typedef T foo; + g(f(S7())); +} + +int +test9(void) +{ + struct s { typedef int foo;}; // { dg-warning "locally defined but not used" } + struct t { typedef int bar;}; + t::bar b = 0; + return b; +} diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h b/libstdc++-v3/include/ext/bitmap_allocator.h index dd0634b..41b0b1f 100644 --- a/libstdc++-v3/include/ext/bitmap_allocator.h +++ b/libstdc++-v3/include/ext/bitmap_allocator.h @@ -238,8 +238,6 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) __lower_bound(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __val, _Compare __comp) { - typedef typename __mv_iter_traits<_ForwardIterator>::value_type - _ValueType; typedef typename __mv_iter_traits<_ForwardIterator>::difference_type _DistanceType; diff --git a/libstdc++-v3/src/istream.cc b/libstdc++-v3/src/istream.cc index f161016..6bcf2db 100644 --- a/libstdc++-v3/src/istream.cc +++ b/libstdc++-v3/src/istream.cc @@ -280,7 +280,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef basic_istream __istream_type; typedef __istream_type::int_type __int_type; - typedef __istream_type::char_type __char_type; typedef __istream_type::traits_type __traits_type; typedef __istream_type::__streambuf_type __streambuf_type; typedef __istream_type::__ctype_type __ctype_type; @@ -364,7 +363,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef __istream_type::char_type __char_type; typedef __istream_type::traits_type __traits_type; typedef __istream_type::__streambuf_type __streambuf_type; - typedef __istream_type::__ctype_type __ctype_type; typedef basic_string __string_type; typedef __string_type::size_type __size_type; @@ -610,7 +608,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef __istream_type::char_type __char_type; typedef __istream_type::traits_type __traits_type; typedef __istream_type::__streambuf_type __streambuf_type; - typedef __istream_type::__ctype_type __ctype_type; typedef basic_string __string_type; typedef __string_type::size_type __size_type; diff --git a/libstdc++-v3/src/valarray.cc b/libstdc++-v3/src/valarray.cc index 4d21ab1..5de146b 100644 --- a/libstdc++-v3/src/valarray.cc +++ b/libstdc++-v3/src/valarray.cc @@ -49,7 +49,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline size_t __valarray_product(const valarray& __a) { - typedef const size_t* __restrict__ _Tp; const size_t __n = __a.size(); // XXX: This ugly cast is necessary because // valarray::operator[]() const return a VALUE!