[Bug libstdc++/56283] New: std::result_of does not gracefully SFINAE (not define ::type)
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56283 Bug #: 56283 Summary: std::result_of does not gracefully SFINAE (not define ::type) Classification: Unclassified Product: gcc Version: 4.7.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com >From the spec of std::result_of, If the expression INVOKE(declval(), declval()...) is well formed when treated as an unevaluated operand (Clause 5), the member typedef type shall name the type decltype(INVOKE(declval(), declval()...)); otherwise, there shall be no member type. If the given INVOKE expression is invalid, ::type should not exist. But an attempt to use it this way to detect a valid call fails. Below is a short demo program. A non-overloaded function name and a functor type with an overloaded call operator are passed to result_of through a type traits style SFINAE wrapper. None of the cases work. In 2 of the 3 cases the failure fires the static assertion, but not for the multiple overload issue. #include template< typename fn, typename = void > struct is_invokable : std::false_type {}; template< typename fn > struct is_invokable< fn, typename std::conditional< true, void, typename std::result_of< fn >::type >::type > : std::true_type {}; void f( int ); static_assert( ! is_invokable< decltype( f ) &( char const * ) >(), "can convert c-string to int" ); struct s { void operator() ( int ) {} void operator() ( float ) {} }; static_assert( ! is_invokable< s( double ) >(), "resolved ambiguous conversion" ); static_assert( ! is_invokable< s( char * ) >(), "converted pointer to number" );
[Bug libstdc++/56283] std::result_of does not gracefully SFINAE (not define ::type)
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56283 --- Comment #1 from David Krauss 2013-02-11 04:57:46 UTC --- Note, defining the trait with the expression declval()(declval()...) does work. Clang 3.1/libc++ behaves the same way.
[Bug c++/56317] New: inheriting constructor fails to move brace-initialized object
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56317 Bug #: 56317 Summary: inheriting constructor fails to move brace-initialized object Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com Although p{} in the example below is an rvalue, I get an error "cannot bind ‘p’ lvalue to ‘p&&’." It does compile if I don't use braces, and change p{} to p(). struct p {}; struct b { b( p && ) {} }; struct d : b { using b::b; }; d o( p{} ); In the original, full program, it doesn't mention a value category, and changing the braces to () doesn't work around the issue.
[Bug c++/56317] inheriting constructor fails to move brace-initialized object
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56317 --- Comment #1 from David Krauss 2013-02-14 09:35:12 UTC --- (But, perfect forwarding equivalent to the inheriting constructor semantic does work around the issue.)
[Bug c++/56333] New: cannot use typedef name in inheriting constructor
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56333 Bug #: 56333 Summary: cannot use typedef name in inheriting constructor Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com struct b {}; struct d : b { using t = b; using t::t; }; error: no members matching ‘d::t {aka b}::t’ in ‘using t = struct b {aka struct b}’ This is defined by §3.4.3.1/2: In a lookup in which the constructor is an acceptable lookup result and the nested-name-specifier nominates a class C: … — in a using-declaration (7.3.3) that is a member-declaration, if the name specified after the nested-name-specifier is the same as the identifier or the simple-template-id’s template-name in the last component of the nested-name-specifier, the name is instead considered to name the constructor of class C.
[Bug c++/56333] cannot use typedef name in inheriting constructor
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56333 --- Comment #2 from David Krauss 2013-02-15 15:43:07 UTC --- Also fixed within a day of updating my sources. Thanks guys!
[Bug c++/55576] Fails to compile a call to template member function
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55576 David Krauss changed: What|Removed |Added CC||potswa at mac dot com --- Comment #12 from David Krauss 2013-02-25 14:06:30 UTC --- Note, this is due to a C++11 change. Under C++03 there were additional rules in 3.4.5/1 rendering the code ill-formed. So it's not a coincidence this just popped up recently. Also, Clang compiles the example from comment 3.
[Bug c++/49122] [C++0x] initializer_list is broken
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49122 David Krauss changed: What|Removed |Added CC||potswa at mac dot com --- Comment #7 from David Krauss 2013-03-08 06:56:00 UTC --- I think this should be reopened. The return value object, which exists in the calling scope, is initialized from the braced-init-list. No copying occurs beyond what is demonstrated in the example in [dcl.init.list]/6. For more detail, see http://stackoverflow.com/q/15286450/153285 .
[Bug c++/49122] [C++0x] initializer_list is broken
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49122 --- Comment #8 from David Krauss 2013-03-08 07:57:03 UTC --- Oops, I didn't read the original code closely enough. To be OK by the above interpretation, the local initializer_list variable would need to be eliminated from main() and the loop would be for(int i: f()) Should I open a new bug?
[Bug c++/56567] New: ICE with lambda return type deduction and braced-init-list
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56567 Bug #: 56567 Summary: ICE with lambda return type deduction and braced-init-list Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com #include #include #include int main() { for ( auto && s : []() { return { std::string( "first" ), std::string( "second" ) }; }() ) std::cout << s << '\n'; } ildtice.cpp: In lambda function: ildtice.cpp:7:61: internal compiler error: in make_decl_rtl, at varasm.c:1136 { return { std::string( "first" ), std::string( "second" ) }; }() ) ^ ildtice.cpp:7:61: internal compiler error: Abort trap: 6 g++: internal compiler error: Abort trap: 6 (program cc1plus) C++11 5.1.2/4: … — if the compound-statement is of the form { attribute-specifier-seqopt return expression ; } … The return statement doesn't match the pattern because a braced-init-list is not an expression. Should be a proper error.
[Bug c++/56568] New: std::initializer_list return value contents lost prematurely
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56568 Bug #: 56568 Summary: std::initializer_list return value contents lost prematurely Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com See http://stackoverflow.com/q/15286450/153285 This program segfaults: #include #include #include int main() { for ( auto && s : []() -> std::initializer_list< std::string > { return { std::string( "first" ), std::string( "second" ) }; }() ) std::cout << s << '\n'; } The return value object should be initialized from the braced-init-list, and bound directly to the implicit "auto && __range" object of the range-based for statement. The array backing that object should have the same lifetime as it, namely the duration of the loop. Instead, the array is destroyed when the lambda exits. This is not easy to fix, but I'll just file this.
[Bug c++/56567] [4.8 Regression] ICE with lambda return type deduction and braced-init-list
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56567 --- Comment #4 from David Krauss 2013-03-10 02:18:18 UTC --- Note, there is nothing in the Standard to prohibit return of an initializer_list value, so this rejects programs which are conformant. Unless/until #56568 is resolved, doing so results in UB (whether or not that's a bug). That's only if the function is executed. It's certainly legal to compile a function returning an std::initializer list, which is never called. So this fix is problematic. For example []{ return std::initializer_list< int >{ 1, 2 }; }(); Not filing another report yet because I haven't pulled the changes and tested anything for myself.
[Bug c++/56567] [4.8 Regression] ICE with lambda return type deduction and braced-init-list
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56567 --- Comment #7 from David Krauss 2013-03-11 22:42:46 UTC --- Created attachment 29647 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=29647 alternative fix Yes. However, the above fix doesn't catch all instances of doing so; for example []() -> std::initializer_list< int >{ return { 1, 2 }; } Worse, one case still results in ICE []() { return std::initializer_list< int >{ 1, 2 }; } Here's an improved fix. It doesn't attempt to catch runtime UB. I think that should be another warning diagnostic, which can also flag such attempted workarounds as reference return types []() -> std::initializer_list< int > && { return { 1, 2 }; } Users are likely to try fiddling after we flag their initial attempt, so we might as well be as broad as possible. However, a specialization of std::min can return a valid std::initializer_list< T > const & : struct s { friend bool operator < ( s lhs, s rhs ) { return false; } friend bool operator < ( std::initializer_list< s > lhs, std::initializer_list< s > rhs ) { return std::lexicographical_compare( lhs.begin(), lhs.end(), rhs.begin(), rhs.end() ); } }; std::min( std::initializer_list< std::initializer_list< s > > { { s(), s(), s() }, { s(), s() } } );
[Bug c++/56567] [4.8 Regression] ICE with lambda return type deduction and braced-init-list
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56567 --- Comment #8 from David Krauss 2013-03-11 22:51:12 UTC --- Oops, I didn't see the preceding comment & checkin before submitting that. Maybe that's a better place to check, but we might keep the extra test cases. Make sure that the remaining ICE is gone.
[Bug libstdc++/41351] New: std::rotate on RAI does not conform to ISO complexity requirement
According to C++03 and C++0x, std::rotate has "Complexity: At most last - first swaps." The random iterator implementation does not call std::swap at all, but rather creates a temporary variable and uses the assignment operator to implement swapping. std::swap often has different complexity than two assignments, so this is non-conforming. Note that the standard requires that std::swap on any container take constant time, but assignment will take linear time. The temporary variable appears to be an optimization for native machine types: rather than move each object to its final location with a swap operation, move it with an assignment and avoid performing twice the necessary assignments. This is a good goal, and perhaps it may be achieved using a special temporary-variable template type which calls std::swap for all but some subset of types. -- Summary: std::rotate on RAI does not conform to ISO complexity requirement Product: gcc Version: 4.2.1 Status: UNCONFIRMED Severity: major Priority: P3 Component: libstdc++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: potswa at mac dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #4 from potswa at mac dot com 2009-09-14 16:35 --- I doubt that stable_partition can't be implemented with std::swap. If I understand you the problem lies in the temporary_buffer, which is uninitialized memory and hence un-swappable. One solution would be simply to initialize it. Already value_type is seeing its constructor called repeatedly, might as well use the default constructor rather than the copy constructor. Another solution would be to use the temporary_buffer for a parallel vector of iterators, pointers, or indexes rather than values. Insert references to the objects at desired locations in ascending order in [temp, temp+middle-first) and descending order in (temp+last-first,temp+middle-first] (that is, the sequences meet in the middle). Then use the buffer to reorder the sequence in fewer than n std::swaps. (See reorder_destructive() in http://stackoverflow.com/questions/838384/1267878#1267878). This buffer would be smaller than in the present implementation except for tiny structures. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #6 from potswa at mac dot com 2009-09-14 18:00 --- If the alternative stable_partition is faster, maybe it should be used anyway. For large blocks, virtual memory allocation time may dominate computation, so it should certainly be faster sometimes. Back to rotate, I was just answering another question on stackoverflow.com when I noticed that rotate on a two-dimensional vector would be slow and memory hungry. I don't actually use it. I haven't checked out the rvalue reference stuff yet, and from what I see I don't understand how stl_algo.h would be improved by it without specifying "&&" anywhere, but I'll take your word for it. Is there another header I missed? I do still believe that it would be best to let the complexity of a swap be exactly the runtime of std::swap, though. Given that there are several ways to optimize this code, the standard appears to be recommending a std::swap specialization as the preferred "helper function," and there does not appear to be a defect in it. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #8 from potswa at mac dot com 2009-09-14 21:36 --- Well, if fast is good, maybe you will consider this: const _Distance __d = __gcd(__n, __k), __r = __n / __d; for ( _Distance __i = 0; __i < __d; ++ __i ) { _ValueType __tmp = *__first; _RandomAccessIterator __p = __first + __l; for ( _Distance __j = 0; ; ) { swap( __tmp, * __p ); if ( ++ __j >= __r ) break; if ( __p >= __middle ) __p -= __n - __l; else __p += __l; } ++ __first; } It's a few times faster than the current implementation for the case of many small rings, and seems to be within 1% otherwise for both large and small data structures. (The way __tmp is used, it can always be optimized out.) There is a small penalty which seems to go away if I manually unroll the inner loop, which is annoying. It's also much, much more elegant. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #10 from potswa at mac dot com 2009-09-14 23:59 --- I'll look into it. That's a long list to do and learn ;v) . I think the general idea here is that the compiler is good at optimizing out the useless moves generated by swap. It turns out that my code has less of a straight line access pattern than the current impl, so I'd like to rewrite first in any case. Can you point me to the test cases? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #12 from potswa at mac dot com 2009-09-15 08:55 --- Just for safekeeping, here's the body of the final code. It's much faster than the current revision on my machine, 2.2 sec for 100 iterations rotating a 10 million int vector 5 places left or right, vs 10.5 sec currently. Also it doesn't use a separate gcd function; the computation is built in. for ( ;; ) { // preconditions: range in [p, p + n), stride = k if ( __k * 2 < __n ) { _RandomAccessIterator __q = __p + __k; for ( _Distance __i = 0; __i < __n - __k; ++ __i ) { iter_swap( __p ++, __q ++ ); } __n = __n % __k; if ( __n == 0 ) return; swap( __n, __k ); __k = __n - __k; } else { __k = __n - __k; _RandomAccessIterator __q = __p + __n; __p = __q - __k; for ( _Distance __i = 0; __i < __n - __k; ++ __i ) { iter_swap( -- __p, -- __q ); } __n = __n % __k; if ( __n == 0 ) return; swap( __n, __k ); } } -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #17 from potswa at mac dot com 2009-09-15 14:33 --- Hmm, on my Core2 my impl still beats the present one on many cases of shift by 1, but the margin is narrower. Shift by 1 is the only case where the temporary can really help, and I eliminated it completely. I suppose I should special-case it back in for k = ± 1. Also, before a commit I'd like to see about installing this algo for the forward and bidirectional cases. If it's not given n, it can compute it as a side effect of a run through the first loop. Once n is found, the second, backwards-iterating loop can be used with the bidirectional iterator and the first, forwards loop can be used with a forward iterator. These will carry the same optimal one-pass memory behavior and (n - gcd(n,k)) swap complexity to all the overloads. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #21 from potswa at mac dot com 2009-09-15 14:56 --- Just to be clear that "working properly" in this context means "working faster" ;v) . I just coded up a special case for k = ± 1 that uses std::copy, which should map to memmove for std::vector::iterator. That should beat anything else. When I posted the code I said "for safekeeping." I would like to officially become a contributor :v) but this is taking a fair amount of time and theoretically something could make me drop it but I don't have a job right now so that's unlikely. Also, what happens with std::__gcd? We erase it, right, and leave any surreptitious uses in the cold? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #23 from potswa at mac dot com 2009-09-15 15:29 --- With the new special case, I get 3x faster than current for n = 100, k = 99. Now it weighs in at 45 lines in my style, before conversion to official style, and not coincidentally I don't really feel like posting it again :vP . I'll do the legal stuff next. Note that a significant speedup is available if std::copy is used for other values of k than 1 and n-1. I just observed 4x over my algorithm and 7.5x over the current one for n = 100 k = n-2 which seems disproportionate but behavior is correct. (The advantage disappears for large n.) This strategy generally requires constructing min( k, n-k ) temporaries. What's the policy on that kind of optimization? The temporaries can only go on the stack, which makes things hairy. Although "isolated cases" benefit, its most reasonable to only special-case left and right shift by 1, right? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #25 from potswa at mac dot com 2009-09-23 21:07 --- Hello Donald, A week has passed. Do the papers usually take this long? - thanks, D On Sep 15, 2009, at 1:45 PM, ass...@gnu.org via RT wrote: Hello David, Thank you for contributing to GNU software. We'll send you the appropriate papers through the post. Please sign and return the original in the envelope provided. Once the FSF has signed it, we will send you a digital copy in pdf format for your records. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #28 from potswa at mac dot com 2009-10-05 05:01 --- I'm still waiting for the IP assignment papers. This is kinda disappointing. Hopefully I'll get a reply this time -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #30 from potswa at mac dot com 2009-10-07 19:57 --- The FSF receptionist says that the lawyer seems to have taken an unannounced vacation this week. It's now three weeks since I requested the forms (and since he confirmed my request). What is the timeframe we're shooting for? On an unrelated note, I checked out the bidirectional iterator implementation a couple weeks ago and it seems to be completely extraneous. The forward iterator implementation is very similar to my algorithm, and performs exactly (n - gcd(n,k)) swaps with a linear memory access pattern. The bidirectional implementation always performs (n) swaps and sweeps over the memory range twice, which hurts performance. So, I'd argue for deleting the bidirectional iterator function and letting the forward iterator function handle it. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #32 from potswa at mac dot com 2009-10-10 01:15 --- I have little experience in this field, so you would probably be a better judge of the best alternative to complete revision. My suggested code is a complete rewrite, based on creating a new algorithm from first principles. There's no going halfway there's the version I posted, without special cases for left/right by one, but that's not so much safer as merely inferior. Now that I've reread the forward iterator version and realized that it's the same as my algorithm, less my right-rotating case, countdown-style loops, and std::copy calls, I can see that its performance is nearly as good. If you like, you can benchmark it against the bidirectional and RAI cases. If you like the gain from simply deleting the bidirectional and RAI functions, you might check in that change. It is ironic that the highest performing (at least for large n) algorithm is the one which never gets used (as forward iterators are nonexistent among the STL classes). As currently written, the RAI algorithm accesses memory in long strides which are likely to thrash the cache and cause the worst possible memory bottleneck for large and coprime k. The bidirectional algorithm accesses memory in linear fashion, but reads and writes each location twice and furthermore performs up to twice as many swaps as necessary. The forward iterator algorithm touches memory locations mostly only once and always sequentially, locations which are touched repeatedly are spatially local and hence cached, and it always performs the minimum number of swaps. Of the current code, it gets the most fundamentals correct. My impression is that any new code is inherently "untrustworthy." I haven't benchmarked this suggestion, but I'm not really keen to check it in myself ;v) . Feel free if you guys like -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #33 from potswa at mac dot com 2009-10-17 20:45 --- I returned the copyright forms today, so now the wheels are turning :vD . -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #35 from potswa at mac dot com 2009-10-30 02:47 --- I got PDF's of the completed forms. What now? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #37 from potswa at mac dot com 2009-10-30 03:55 --- It seems like the goals are changing. Is this due to an approaching deadline? The "super" algorithm is the product of making every case faster. Removing any part of it (i.e. calls to std::copy) will regress performance of something. I don't think it's too complicated. I'm attaching my code so you can actually see it; I don't think I've shared it yet. See my post from October 10. The forward iterator implementation is already a stripped-down version of my algorithm. If we want simplicity, we can excise the reverse and RAI implementations and not add anything. If you're serious about this, I can benchmark that. But, it shouldn't be such a surprise that performance and minimalism are exclusive. The existing RAI algo also has forward and backward cases. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #38 from potswa at mac dot com 2009-10-30 03:56 --- Created an attachment (id=18932) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18932&action=view) C++ snippet containing example function template improved algorithm with forward/backward and std::copy cases. Excerpted from my test file. Not suitable for real use: at a glance, it's missing the random_access_iterator_tag argument. I'm not in the programming groove at the moment and can't proofread, polish, etc. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #41 from potswa at mac dot com 2009-10-30 19:07 --- Created an attachment (id=18934) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18934&action=view) table of benchmarks comparing various algorithms and parameters As the Euclidean ring division algorithm sweeps the memory range at least once per ring, you can see from this table that the present RAI implementation performs very poorly for small k greater than one. The final row, "fwd +copy", is a new proposal which adds the std::copy calls to the existing forward iterator algo. It remains compatible with bidirectional iterators and, from this data, looks pretty good. Its moderately bad showing in the final column I don't yet understand. The special cases for left and right by one should use std::move and std::move_backward, respectively, I guess. I'm not sure what state of testing I left things at before, but let's look at the performance numbers first. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #42 from potswa at mac dot com 2009-10-30 19:14 --- Sorry, "once per ring" doesn't guarantee more than one pass for k=2 and n odd, or the test case I presented. Better to say there are k passes, although performance should improve for n/k on the order of cache associativity. Details not really important. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #44 from potswa at mac dot com 2009-11-03 03:56 --- When does _GLIBCXX_MOVE3 do the wrong thing? I can see only doing the k=1 optimization #ifdef __GXX_EXPERIMENTAL_CXX0X__ after all, copying is the misbehavior this bug is filed against in the first place! But std::move seems reasonably kosher to me. It's as good as the current RAI implementation using _GLIBCXX_MOVE, although not as compliant as always using std::swap. I apologize for always saying "copy" and not "move." I did include a disclaimer on that code, that it's not really intended for use. Really I was just using std::copy as an alias for memmove for performance testing. I haven't been able to test any C++0x code at all because I'm having trouble building GCC on OS X. Once I can test C++0x code, I'll post to the mailing list -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #47 from potswa at mac dot com 2009-11-03 17:21 --- What is the function of the helper class? I suppose the user could get improved performance by specializing __is_scalar, but that could have unintended consequences (resulting from the class not being scalar), not to mention that the user is then modifying nonstandard internals. Furthermore, we care more about whether it's POD than scalar. Why not adapt or add a general interface to the test used by __copy_move* in stl_algo.h? const bool __simple = (__is_pod(_ValueTypeI) && __is_pointer<_II>::__value && __is_pointer<_OI>::__value && __are_same<_ValueTypeI, _ValueTypeO>::__value); This seems to capture the requirements of memmove although using copy/move instead of swap should also be faster for large PODs in eg linked lists. Anyway, __is_pod being reasonably sufficient for compliant behavior wrt "complexity of a swap" being known, couldn't we just take patch_draft_2 and substitute in if ( __is_pod(_ValueType) && __k == 1) I favor this alternative. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #50 from potswa at mac dot com 2009-11-03 17:53 --- The current RAI algo uses a temporary regardless of size or class. We could put in a "&& sizeof(_ValueType) < __MAX_TEMP_SIZE" or something but stack overflow from a single temporary doesn't seem to have been concern in the past. I don't see how being register-size in particular is important. If we were swapping the temporary every time, we would want it to fit in a reasonable number of registers so the compiler could optimize out read-after-writes. But the __tmp here is only written and read once. The larger it is, the more acceleration. Proposed performance is very good with k small > 1, compared to current. Using memmove is simply even faster. It's not clear such rotate operations are popular enough to warrant a framework for optimization, though. If we assure it's a non-move type then I also favor reverting out the _GLIBCXX_MOVE[3](). -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #54 from potswa at mac dot com 2009-11-03 20:43 --- Created an attachment (id=18959) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18959&action=view) A couple benchmarks for 32-bit mode and updated fwd+copy Yikes. Just a second: yesterday I played around with the forward iterator algorithm a little more, and discovered that the reason it benchmarked slower in rotate_speed.txt was that I had changed it to use std::iter_swap instead of std::swap. I don't know if 4.5.0 has whatever compilation issue caused the difference (I'm still testing in 4.2.1), but the new benchmarks show it as being the same speed as my rewrite in -m64 mode. Previous data showing my algo being faster resulted from testing in -m32 mode. Attached are updated benchmarks showing that the only significant advantage to my rewrite is a 12% speedup in -m32 mode for the general case. The advantage to an improved forward/bidirectional iterator version is that it should also help sequences in containers besides std::vector. Also it would be lower impact as the only code added would be the special cases calling std::copy, and the separate bidirectional and RAI algos would go away completely. -- potswa at mac dot com changed: What|Removed |Added Attachment #18934|0 |1 is obsolete|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/41351] std::rotate on RAI does not conform to ISO complexity requirement
--- Comment #56 from potswa at mac dot com 2009-11-03 21:01 --- Okay I'm doing my best, anyway. I'll be holding off on other contributions until I get a compiler capable of testing my code. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41351
[Bug libstdc++/57350] New: std::align missing
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350 Bug ID: 57350 Summary: std::align missing Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com C++11 §20.6.5 [ptr.align] remains unimplemented. Several years ago I published what now appears to be a compliant implementation, but it was under the MIT license. Does that disqualify that code, or me, from submitting a patch? As pure, relatively agnostic pointer arithmetic it doesn't seem to fit into the other groups of functions specified for , which are implemented in various separate files.
[Bug libstdc++/57350] std::align missing
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57350 --- Comment #1 from David Krauss --- Oh, here's a link to my version: http://code.google.com/p/c-plus/source/browse/src/util.h#50
[Bug c++/57419] New: Access control doesn't stop referring to a deleted function
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57419 Bug ID: 57419 Summary: Access control doesn't stop referring to a deleted function Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com Using reference-to-member syntax on a private, deleted function in a SFINAE context fails as a hard error as a use of a deleted function. But it can't be accessed in the first place due to the access control. Calling the function instead produces the desired result. Clang 3.2 accepts this TU but GCC 4.9 rejects: template< typename q > decltype( &q::f ) t( q ) {} char t( ... ) { return {}; } class c { void f() = delete; }; class d { static void f() = delete; }; static_assert( sizeof( t( c() ) ), "c" ); static_assert( sizeof( t( d() ) ), "d" );
[Bug c++/57429] New: Dependent function call with one visible declaration, deleted
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57429 Bug ID: 57429 Summary: Dependent function call with one visible declaration, deleted Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com A dependent function call can't be resolved until instantiation time, but if there's only one candidate visible from the template definition, that candidate is accessed such as to produce an error if deleted, even if it would be eliminated by the first stages of overload resolution. Clang accepts this valid TU but GCC produces two errors. Also a good idea to test in a SFINAE context, which is where this cropped up. void f() = delete; template< typename t > void ft() { f( t() ); } template< typename t > struct ct { decltype( f( t() ) ) m; }; The workaround is to define another overload, which may also be deleted.
[Bug c++/57433] New: Local classes have an associated namespace
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57433 Bug ID: 57433 Summary: Local classes have an associated namespace Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com The example below should fail with access to a deleted function, but is accepted by GCC 4.9. Clang correctly rejects it. The issue is that [basic.lookup.argdep] §3.4.2/2 is defined in terms of namespace membership, but a local class (such as a lambda) is not a member of a namespace. "If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the namespaces of which its associated classes are members." template< typename t, typename u > void f( t, u ) = delete; template< typename t > void c( t o ) { f( o, 5 ); } namespace n { template< typename t > void f( t, int ) {} void p() { c( []{} ); } } For the sake of argument, the same Standardese forbids the following example because n2 is only associated with n1, not s. None of its associated classes are members of a namespace so it is not associated. Such behavior is ridiculous. GCC and Clang accept this… it would be surprising if any implementation didn't. namespace n { struct s { struct n1 { struct n2 {}; }; }; int f( s::n1::n2 ) { return 3; } } int i = f( n::s::n1::n2() );
[Bug c++/57419] Access control doesn't stop referring to a deleted function
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57419 --- Comment #2 from David Krauss --- I guess the proper terminology would be taking its pointer. Nonstatic members don't really have addresses. Anyway what I was doing was determining the argument of a functor with one operator() overload using &ftor::operator() . Calling or otherwise referencing a deleted function does not result in substitution failure; it results in an error. Access control applies to the name rather than the referent so it should stop before it sees the =delete definition. This makes sense because the inaccessible name is part of the immediate context of the declaration under substitution but =delete is not.
[Bug c++/57419] Access control doesn't stop referring to a deleted function
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57419 --- Comment #5 from David Krauss --- Does this also fix #57429?
[Bug c++/57429] Dependent function call with one visible declaration, deleted
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57429 --- Comment #1 from David Krauss --- To clarify the example, it's failing at definition time. There are two separate failures illustrated, a function template and a class template.
[Bug c++/57593] New: Friendship not extended into friend member-declaration
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57593 Bug ID: 57593 Summary: Friendship not extended into friend member-declaration Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com The access granted by friendship extends into the "member declarations of the befriended class" (11.3/2). Friend declarations are member-declarations but not member declarations per se, so the standard is ambiguous. But GCC is inconsistent. class c { class n {}; friend struct s; }; struct s { friend class c::n; // OK friend c::n g(); // OK friend void f() { c::n(); } // Error }; All three should go the same way, if access is granted per declaration. If the first two were invalid, private nested classes and related functions would be impossible to befriend. Rejection of the third case impedes use of a friend as part of a class implementation, akin to members, such as the common case of operator <<. Clang does accept it. A defect report has been submitted.
[Bug c++/57593] Friendship not extended into friend member-declaration
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57593 --- Comment #2 from David Krauss --- The maintainer (Mike Miller at EDG) said simply that he will add it to the list, but as far as I know a number isn't assigned until the new list is drafted. The title is "access granted by friendship to class-scope friend declaration." (But I suppose he could take a liberty and remove the redundant "class-scope".) Regardless of any possible defect, GCC is inconsistent. The change in access applies to certain declarations, not others, but GCC is applying it to parts of certain declarations (seemingly only the function body is excluded). To be consistent with the current standard, the only choices are to allow all 3 examples or disallow all 3. The latter choice would be a nasty breaking change. If it helps, here is the text of DR submission. Friendship is not transitive, but it does grant access to "member declarations of the befriended class." ([class.friend]/2) And a friend is declared by a member-declaration. Is a grammatical member-declaration with the friend specifier still a member declaration? class c { class n {}; friend struct s; }; struct s { friend class c::n; // 1 friend c::n g(); // 2 friend void f() { c::n(); } // 3 }; If a friend member-declaration is not a member declaration, then it is impossible to grant access to a private nested class (1) or a function composed from a type specified using a private nested class (2). Both GCC and Clang allow these examples. If a friend member-declaration is a member declaration, then it implements one degree of transitive friendship, if it is also a definition (3). Clang accepts this example, but GCC rejects it. Friends are enough like members that the access should apply. One common application is operator<< . A manipulator proxy class may need access from its insertion operator to its client's restricted members. Another application is to define a function that would otherwise be a nonstatic member but receives a container or smart pointer, not a direct reference to the object. These are the most common cases for the inline friend definition syntax. They are found by ADL so the namespace-scope declaration may be omitted. Working around by befriending the pseudo-member friend may be troublesome as it may violate separation of concerns, form undesired associated classes for ADL, or require forming a declaration which may use inconvenient nested types or reduplicated SFINAE. Although access control isn't really a security mechanism, no "exploit" would be opened by granting access because a friend can always delegate to a static member anyway. Proposed resolution: Modify [class.friend]: … can be accessed in the base-specifiers, member-declarations, and definitions of members of the befriended class. Is there any context within a class-specifier where access control is performed besides its base-specifiers and member-declarations? It doesn't seem to apply to name lookup in the template-name of a partial or explicit specialization, but I can't find the spec. Perhaps it should be: … can be accessed in the class-specifier and definitions of members of the befriended class.
[Bug c++/57673] New: pack sizeof ... groups ellipsis with preceding expression
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57673 Bug ID: 57673 Summary: pack sizeof ... groups ellipsis with preceding expression Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com In this example, template g compiles without issue but each member in d chokes the parser. The only difference is grouping parentheses, which shouldn't be significant. There may be more than one issue. A left paren seems to get the parser into a good state to accept sizeof ... , but it starts in a bad state at the beginning of an initializer, and seeing a qualified-id puts it into a bad state. (Reversing the order of subexpressions and writing ( sizeof ... ( p ) - i::m ) does not produce an error.) struct i { static constexpr int m = 5; }; template< int ... p > struct g { static constexpr int m = i::m - ( sizeof ... ( p ) ); int n = ( sizeof ... ( p ) ); }; template< int ... p > struct d { static constexpr int m = ( i::m - sizeof ... ( p ) ); int n = sizeof ... ( p ); };
[Bug c++/57673] pack sizeof ... groups ellipsis with preceding expression
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57673 --- Comment #1 from David Krauss --- Oops, g::m does not need to be static constexpr to produce an error; the specifiers should be removed to produce a minimal test.
[Bug preprocessor/57714] New: Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 Bug ID: 57714 Summary: Newline rendered incorrectly in output Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: preprocessor Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com main(){\ return 0; } preprocesses to main(){return 0; } The problem only appears in output from the -E option; observing the newline within the program as with #define main(){\ return 0; } main() produces the correct result } {return 0; This is a regression since 4.2.1; the GCC version included with Mac OS X does not exhibit the problem.
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #2 from David Krauss --- Andrew, are you sure? The zero should remain on the same line as the "return" token.
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #3 from David Krauss --- See section 9 of the manual: http://gcc.gnu.org/onlinedocs/gcc-4.8.1/cpp/Preprocessor-Output.html#Preprocessor-Output The output from the C preprocessor looks much like the input, except that all preprocessing directive lines have been replaced with blank lines and all comments with spaces. Long runs of blank lines are discarded. ... CPP does not insert any whitespace where there was none in the original source, except where necessary to prevent an accidental token paste.
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #5 from David Krauss --- What? That makes even less sense. Are you guys familiar with the concept of line splicing? See "phases of translation" in the Standard, namely phase 2.
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #6 from David Krauss --- Just to clarify the last comments, the input main(){\ return 0; } translates via cpp to main(){ return 0; } i.e. no splicing is apparent in the output.
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #7 from David Krauss --- Oh, OK, now I followed that link. Splicing is supposed to be transparent unless you specify -P. This still qualifies as a bug.
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #8 from David Krauss --- Probably what happened: 1. In preserving visual appearance, tokens not separated by spaces are kept together. 2. Line splicing happens before spaces are identified for the above. 3. The { and return tokens are grouped into the same visual block. 4. 0 follows a space and its location on the next line is duly noted.
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #10 from David Krauss --- I don't plan on fixing this in GCC, but I did implement the feature today in my own preprocessor, http://code.google.com/p/c-plus/source/list . It does require a handshake between phases 2 and 3, because a token divided over two lines needs to go into the earlier line, and then the extra newlines are flushed once the token is complete. But a newline inside a whitespace "token" is not postponed. OK, on to bigger and better things :)
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #14 from David Krauss --- Harald's comment #10 is almost accurate, but for two things: 1. Actually the C standard does care whether whitespace is added. Whitespace is visible in the result of stringizing, and when comparing duplicate macro definitions. 2. Whitespace does not need to be added to cause the visual formatting of the output to match the input. The trick is to output a backslash character in the output. Of course this would disturb clients who don't expect backslashes in their pretty-printed output. But pretty-printed output shouldn't be used for automatic translation in the first place — that is what the -P option is for. And to reconcile #2 with #1, the stringize operator and macro definition comparison need to track splices in preserved whitespace, and treat whitespace composed entirely of splices as nonexistent. That is exactly what I implemented in my own preprocessor. See edits subsequent to the one linked above. Such changes must be done internally even if you choose not to print backslashes to the final output stream. If someone wants to fix this in GCC, let this be a guide…
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #15 from David Krauss --- Corrections to previous: Harald's comment is #11, and I meant to refer to the commits in my repo from http://code.google.com/p/c-plus/source/detail?r=d462b650c355b606545158f4da7365180b699752 up through http://code.google.com/p/c-plus/source/detail?r=2849f0f6d0677ed2679e39aad2c85e87f9b7ebd4 .
[Bug preprocessor/57714] Newline rendered incorrectly in output
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57714 --- Comment #17 from David Krauss --- Yes, my preprocessor classifies the backslash-after-preprocessing as a whitespace token. I simply don't intend to make textual preprocessing output. With raw strings, UCNs, and user-defined literals, there's just no way a user would handle it all properly. GCC avoids inserting whitespace except where "necessary," where a token boundary would be invisible, but tokenizing has gotten harder than it was. My preprocessor doesn't bother with any artificial whitespace. Pretty mode is for user display only, and robust processing needs out-of-band non-text data.
[Bug c++/57857] New: argument of decltype used by no return value warning
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57857 Bug ID: 57857 Summary: argument of decltype used by no return value warning Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com The following program complains that "declval() must not be used!" in a static assertion if -Wall is passed. But declval() is only present in the unevaluated context of a decltype specifier. The issue seems to be linked to the generation of the warning message. But the warning message will be present without the static_assert if the function has more than one exit point, such as if(0) throw; or if(0) return; (the latter using -fpermissive). #include template auto foo() -> decltype(std::declval() + std::declval()); template decltype(foo()) bar(T) { // if ( 0 ) throw; } int main() { bar(1); }
[Bug c++/57857] argument of decltype used by no return value warning
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57857 --- Comment #1 from David Krauss --- Narrowing down the cause, the statement { 0; } silences the error but { void(0); } does not.
[Bug libstdc++/57898] New: std::bind incompatible with ref-qualified ptmf
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57898 Bug ID: 57898 Summary: std::bind incompatible with ref-qualified ptmf Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com #include struct s { void f() &; }; s *p; auto b = std::bind( &s::f, p ); Resulting error: error: forming reference to qualified function type ‘void() &’ The original case produced an overload resolution failure for std::bind, with a complaint like "no known conversion for argument 1 from void(t::*)(arg&&) to void(t::*&&)(arg&&)", i.e. it's having trouble binding the ptmf reference. However I have isolated that problem. It seems there may an underlying issue in the compiler though.
[Bug c++/57905] New: braced-init-list allowed in default template-argument
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57905 Bug ID: 57905 Summary: braced-init-list allowed in default template-argument Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com [dcl.fct.default] 8.3.6/3 says A default argument shall be specified … in a template-parameter (14.1); in the latter case, the initializer-clause shall be an assignment-expression. So a default template-argument cannot be a braced-init-list, yet this is accepted without warning when using -Wall: template< int i = {} > struct s; Clang rejects it outright. I thought it was their bug but just happened to be reading now about default arguments.
[Bug c++/58147] New: Template template parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58147 Bug ID: 58147 Summary: Template template parameter Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com Although the usage is a bit dubious, name lookup of the identifier after a nested-name-specifier should not find a template parameter name. But it does, seemingly only for a template template parameter. template< typename > struct b {}; template< template< typename > class b > struct d : b< int > { using d::b< int >::b; }; template struct d< b >;
[Bug c++/58147] Template template parameter name found after nested-name-specifier
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58147 David Krauss changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #1 from David Krauss --- Never mind; I was missing a template keyword after the nested-name-specifier. NEEDS MOAR TEMPLATE!
[Bug c++/53251] New: template keyword ignored between -> and member under name collision with non-member
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53251 Bug #: 53251 Summary: template keyword ignored between -> and member under name collision with non-member Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com Minimal testcase: template< typename > class set; template< typename > struct b { template void set(); }; template struct d : b { d() { this->template set(); } }; int main() { d s; } Diagnostic: In constructor ‘d::d()’: 12:17: error: invalid use of ‘class set’ The name "set" is looked up in the context of the expression, outside the class, perhaps per §3.4.5/1 [basic.lookup.classref]. Furthermore, a class found by lookup in expression scope per 3.4.5/1 must agree with lookup in class scope anyway (i.e. it must be a base class if class scope lookup succeeds) or the program is ill-formed. 3.4.5/1 does not apply because the template keyword is used to mark a dependent object expression. I suspect that somehow the hint carried by the keyword isn't properly restricting name lookup. For deeper discussion see http://stackoverflow.com/questions/10426428 .
[Bug c++/53618] New: segfault on self-referential class partial specialization argument
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53618 Bug #: 53618 Summary: segfault on self-referential class partial specialization argument Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com I was trying a new approach to SFINAE on 4.7.0 and ICEd instead. Not sure if this is valid. The idea is to check whether the specialization is already a complete class while forming the partial specialization arguments. (http://stackoverflow.com/questions/10958435) --- template< int > struct ic; template< typename t, typename c = ic< 0 > > struct is_dereferenceable; template< typename t > struct is_dereferenceable< t, ic< true? 0 : * t() > > {}; template< typename t > struct is_dereferenceable< t, ic< sizeof (is_dereferenceable< t >) > > {}; is_dereferenceable< char * > i;
[Bug c++/53618] segfault on self-referential class partial specialization argument
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53618 David Krauss changed: What|Removed |Added Severity|normal |minor --- Comment #1 from David Krauss 2012-06-09 05:47:53 UTC --- I have been alerted to the fact that the sizeof expression is invalid because it can't be applied to an incomplete type. So this is crashes on invalid code. And the crashing specialization is extraneous anyway, such a case should be handled by the primary template. (Which can be said in general of such a mechanism, should anyone want it.)
[Bug c++/53660] New: function pointer conversion function template with nested-name-specifier ignored
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53660 Bug #: 53660 Summary: function pointer conversion function template with nested-name-specifier ignored Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com template< bool > struct enable_if { typedef void (*t)(); }; struct c { template< bool t = true > operator typename enable_if< t >::t () { return []{}; } }; int main() { c()(); // error: no match for call to ‘(c) ()’ } http://stackoverflow.com/questions/11018810 In C++03 it seems that it was impossible to define a conversion function template that would render its class Callable. Yet there is a function add_template_conv_candidate (cp/call.c) which seems to be used only for this purpose. It was added back in 1997 and it's not clear that it's been tested in a while. Now with default function template arguments the above construct is possible, and it should be called but isn't. The problem is that the test for function pointer type (etc.) is applied before instantiation in build_op_call_1. The test probably belongs in add_conv_candidate.
[Bug c++/53815] New: Explicit specialization of member enumeration of a class template
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53815 Bug #: 53815 Summary: Explicit specialization of member enumeration of a class template Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: minor Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com C++11 quietly added a bullet point to the middle of the list of things that can be explicitly specialized (14.7.3/1 [templ.expl.spec]): - member enumeration of a class template So, this should compile: template struct Foo { int getX(x *p) { return(0); } enum E12 { a }; }; template <> int Foo::getX(int*) { return(-15); } template <> enum Foo::E12 { a, b, c }; It fails with "redeclaration of ‘Foo::E12 Foo::a’". Deleting "a" from the primary template results in "enumerator value 2 is too large for underlying type ‘unsigned int’". Adding an explicit underlying type of "int" to the specialization results in "underlying type mismatch in enum ‘enum Foo::E12’". Then, adding the same underlying type to the primary template results in successful compilation. The enumerators of the specialization can be accessed from outside the class scope, but the enumerators of the hidden primary template are visible as well. The feature is rather bizarre, IMHO. This was caught by a StackOverflow user, although it's not clear he's even aware of C++11 but may have just always expected it to be legal. http://stackoverflow.com/q/11271553/153285
[Bug c/51437] GCC should warn on the use of reserved identifier/macro names
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51437 --- Comment #11 from David Krauss 2012-02-19 11:09:28 UTC --- (In reply to comment #10) > (In reply to comment #9) > > However, note that the standards also reserve various other classes of > > names, > > such as types ending in _t, for which GCC should only flag definitions, not > > uses. Only system headers should define new _t types, but user code can > > *use* > > types like time_t or pid_t without warning. > > These are only reserved for POSIX, and should not always be warned about! Yes, respecting POSIX would be overkill. In particular, it's OK and common to define such types in C++ outside the global namespace. > > (Some of the other reserved identifier categories, such as E[A-Z0-9].*, > > is[a-z].*, to[a-z].*, and mem[a-z].* should go under some separate, more > > pedantic warning option.) > > I don't see why this should happen at all. There's nothing special about these > general names? See comment #3, they are reserved in C99 §7.26 "Future library directions" (although those patterns aren't quite right).
[Bug c++/52809] New: Template non-dependent static_assert diagnostics may confuse
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52809 Bug #: 52809 Summary: Template non-dependent static_assert diagnostics may confuse Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: minor Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com A static_assert declaration that does not depend on template parameters will be detected and reported while parsing the template, before any instantiation. This is OK because such a template would have no valid instantiation, which immediately renders the program ill-formed. In terms of cosmetic QOI, however, it would be better to clarify the messages for users who don't know all the rules. Intuitively, the assertion shouldn't be evaluated until instantiation, regardless of dependence. The user might expect an uninstantiated template to pass through. We should add something like "error: template MyTemplate cannot have a valid instantiation" after the static_assert diagnostic. Example code and result, as currently implemented: template< bool b > struct s { static_assert( b, "uhoh" ); static_assert( false, "yikes" ); }; s< false > q; depassert.cpp:4:1: error: static assertion failed: yikes depassert.cpp: In instantiation of ‘struct s’: depassert.cpp:7:12: required from here depassert.cpp:3:1: error: static assertion failed: uhoh
[Bug c++/57520] alias template substitution/deduction failure
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57520 David Krauss changed: What|Removed |Added CC||potswa at mac dot com --- Comment #3 from David Krauss --- To summarize the above, template template argument deduction finds an alias template used to declare an object instead of the template type the alias resolved to. This is wrong because alias template specializations are not distinct types. The f1/g1 examples are extraneous. f2 matches the alias (wrong) and g2 matches the type generated by the alias (correct). One workaround is to simply add a typedef, this fixes overload resolution of both functions. typedef Vec vit; vit v; I still reproduce this in a 4.9 trunk build from mid October.
[Bug c++/59186] New: decltype(this) treated specially in trailing-return-specifier
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59186 Bug ID: 59186 Summary: decltype(this) treated specially in trailing-return-specifier Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com In the following TU, GCC 4.9 accepts the "error" line and rejects the "Same as previous" line. The "this" keyword is well-defined inside the body of a nonstatic member function, not in a trailing-return-type. The program illustrates that decltype(this) has one well-defined meaning in a member declaration of a local class inside a nonstatic member function, but another meaning when the same function is written with a trailing-return-type. struct s { auto f() -> decltype(this) { return this; } // error: this inaccessible void g() { struct t { decltype(this) g() { return static_cast(nullptr); } // OK auto h() -> decltype(this) { return static_cast(nullptr); } // Same as previous. }; } };
[Bug c++/59186] decltype(this) treated specially in trailing-return-specifier
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59186 --- Comment #1 from David Krauss --- Just to clarify, in the last paragraph, decltype(this) has the same meaning in both cases according to the standard but the bug causes it to refer to the inner type instead of the outer type.
[Bug c++/59186] decltype(this) treated specially in trailing-return-specifier
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59186 David Krauss changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #3 from David Krauss --- Ah, you are correct. I missed that because I expected to find it in [class.this].
[Bug c/51437] GCC should warn on the use of reserved identifier/macro names
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51437 David Krauss changed: What|Removed |Added CC||potswa at mac dot com --- Comment #4 from David Krauss 2011-12-16 11:27:45 UTC --- The #pragma GCC system_header directive helps here by tagging places where reserved names are OK, but accommodating headers from the operating system which may lack that directive might require something else.
[Bug libstdc++/52040] New: TR1 is not accessible using compiler flags alone
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52040 Bug #: 52040 Summary: TR1 is not accessible using compiler flags alone Classification: Unclassified Product: gcc Version: 4.7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com C++ TR1 (N1836) §1.3/3-4 says 3. … Users should be required to take explicit action to have access to library extensions. 4. It is recommended either that additional declarations in standard headers be protected with a macro that is not defined by default, or else that all extended headers, including both new headers and parallel versions of standard headers with nonstandard declarations, be placed in a separate directory that is not part of the default search path. The "explicit action" is left open-ended, but the document suggests that mere inclusion of a nonstandard header should fail. GCC interprets the explicit action to be prefixing the header name with "tr1/". This is a change to source code, whereas other platforms such as MSVC allow TR1 to be used without altering the header names. An alternative way to use GCC would be to pass "-isystem /usr/include/c++/.../tr1" — instead of modifying the header name, modify the search path. This fails because, for example, includes the line #include There are two ways to fix this. One was actually used in some other headers circa GCC 4.2, and would read: #include "../cfloat" The other is perhaps less clean, but opinions may differ: #include_next Applying either of these fixes across the tr1/ directory should improve source compatibility.
[Bug c++/55986] New: RHS of logical operators may render LHS unevaluated in constant-expression
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55986 Bug #: 55986 Summary: RHS of logical operators may render LHS unevaluated in constant-expression Classification: Unclassified Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: pot...@mac.com This compiles without incident, despite using a non-constant object in a constant-expression: int i; static_assert( i || true, "" ); static_assert( ! ( i && false ), "" ); It appears to be assuming that || and && are commutative, but short-circuiting only works in one direction.
[Bug c++/55986] RHS of logical operators may render LHS unevaluated in constant-expression
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55986 --- Comment #1 from David Krauss 2013-01-15 04:47:53 UTC --- Passing `-O2` additionally causes it to skip a condition like `(i == 0 || i != 0)`, so it looks like a general issue with expression simplification bypassing ODR-use.
[Bug c++/55986] RHS of logical operators may render LHS unevaluated in constant-expression
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55986 --- Comment #2 from David Krauss 2013-01-15 04:48:47 UTC --- Passing `-O2` additionally causes it to skip a condition like `(i == 0 || i != 0)`, so it looks like a general issue with expression simplification bypassing use.
[Bug c++/55986] RHS of logical operators may render LHS unevaluated in constant-expression
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55986 --- Comment #3 from David Krauss 2013-01-15 08:02:55 UTC --- Likewise this is allowed: switch( 0 ) case i-i: ; I think this is a purposeful language extension, which could use a switch to disable. It would be nice if static_assert were always strict.
[Bug c++/70608] New: Braced initializer in default argument misses friendship
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70608 Bug ID: 70608 Summary: Braced initializer in default argument misses friendship Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com Target Milestone: --- A braced-init-list in a default function argument does not receive friendship as it should. class A { A() {} friend int ok(A); friend int f(A); friend int g(A); }; int ok(A = A()); // OK. int f(A = {}); // Error. Should be same as previous. int g(A (&&)[1] = { A() }); // Error.
[Bug libstdc++/66284] std::reference_wrapper is transparent to std::function::target_type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66284 --- Comment #2 from David Krauss --- The converting constructor requirements also say more explicitly, shall not throw exceptions when f is a function pointer or a reference_wrapper for some T. Probably the copy constructor should be worded similarly. In any case, the exception guarantee isn't affected, as sizeof(reference_wrapper) == sizeof(T*).
[Bug libstdc++/66284] std::reference_wrapper is transparent to std::function::target_type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66284 --- Comment #3 from David Krauss --- … Woops, that f is the function parameter, not the target. So it's not a conflicting requirement, but it could be a template for fixing the the copy constructor constraint.
[Bug c++/60859] New: Value-initialization of scalar in aggregate yields "braces around scalar initializer"
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60859 Bug ID: 60859 Summary: Value-initialization of scalar in aggregate yields "braces around scalar initializer" Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com GCC incorrectly rejects this value-initialization of an array element: int a[] = { {} }; // error: braces around scalar initializer for type ‘int’ Clang accepts it, and furthermore if the error is realized by changing the code to {0}, only emits a warning. Generating a warning seems more reasonable than a hard error.
[Bug c++/61492] New: Nested-name-specifier lookup finds function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61492 Bug ID: 61492 Summary: Nested-name-specifier lookup finds function Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com Name lookup of a nested-name-specifier should only find entities with associated scopes: namespaces, classes, and enumerators. GCC allows a function name to hide an enumerator. (Classes and namespaces are correctly not hidden.) enum e { m }; e e(), q = e::m; // Error: ‘e’ is not a class, namespace, or enumeration
[Bug c++/61492] Nested-name-specifier lookup finds function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61492 --- Comment #1 from David Krauss --- Oops, objects hide enumerations in this context too. enum e { m } e = e::m; // Same error I neglected to check this because I thought I'd used it a while ago, but it turns out I'd worked around the problem. Clang accepts the examples.
[Bug c++/61584] New: What defines std::underlying_type?
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61584 Bug ID: 61584 Summary: What defines std::underlying_type? Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com This is not a library bug because std::underlying_type simply wraps the __underlying_type() intrinsic. enum x {}; static_assert( std::is_same< std::underlying_type< x >::type, int >::value, "enum does not default to int." ); The x64 ABI, Figure 3.1, suggests that enumeration types are usually considered identical to [signed] int, except "C++ and some implementations of C permit enums larger than an int. The underlying type is bumped to an unsigned int, long int or unsigned long int, in that order." This is the only mention of "underlying type" in the ABI, and the Itanium C++ gABI has nothing to add. However, common sense dictates the same rule because unscoped, unfixed enumerations promote to the integer type of least rank that can represent any enumerator. The underlying type of such an enumeration does *not* affect its conversions, and can only be observed by underlying_type introspection. (A std-discussion request to require promotion to match underlying_type spurred this report.) By the most relevant available specification, int should be the default underlying type for unscoped, unfixed enumerations. Scoped, unfixed enumerations might follow suit, according to the spirit of the ABI, but there's more wiggle room because they do not implicitly convert to the underlying type. (However, users are likely to use underlying_type for explicit conversions, so the same issues arise.)
[Bug c++/61584] What defines std::underlying_type?
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61584 --- Comment #2 from David Krauss --- C "compatible type" determines integer conversion rank (C11 §6.3.1.1). C++ fixes the rank by a heuristic which the implementation cannot decide (C++11 §4.5/3). Currently, enum promotions are incompatible between C and C++ modes. Furthermore, when C++ requires promotion to signed int but the underlying type is unsigned int, integer overflow may occur. I think this adds up to a bug and the C++ behavior should get its own bullet at the end of that manual page.
[Bug c++/29615] Class can't be friends of itself?
--- Comment #4 from potswa at mac dot com 2010-03-26 21:08 --- The error doesn't occur if the friend is a template instance, so it really doesn't hurt anyone. But it's weird. template< int z > class F { friend class F<0>; // error only if <0> removed }; template class F<0>; -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29615
[Bug libstdc++/43595] New: std::unique incorrectly assumes transitive property on functor, operator==
According to the standard §25.2.8, std::unique has behavior defined in terms of *i == *(i - 1) or pred(*i, *(i - 1)) != false however the current implementation compares each successive element to the first in the "equal" range. This is only equivalent if the transitive property holds. This is certainly wrong if a functor is passed, and it may be wrong for the other case as well. The non-functor version is defined to evaluate *i == *(i - 1) but does not require EqualityComparable elements. C++0x does impose this requirement: "The comparison function shall be an equivalence relation." -- Summary: std::unique incorrectly assumes transitive property on functor, operator== Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: potswa at mac dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43595
[Bug c++/65159] Linker forgets definition of type_info::__is_pointer_p
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65159 --- Comment #8 from David Krauss --- It was an updated tree. I'm not sure what revision it was updated from, but it was probably late January. Sorry for the delay, my machine got completely hosed by a bad RAM chip. Took the filesystem with it. So, bit rot and disk corruption can't be ruled out either. Jonathan, what does the "confirmed" mean, were you able to reproduce it at all?
[Bug c++/65159] Linker forgets definition of type_info::__is_pointer_p
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65159 --- Comment #10 from David Krauss --- I made a clean build of r220825, and it succeeded. Then I downgraded to r22, and it produced similar link errors, although not in type_info.
[Bug c++/65159] Linker forgets definition of type_info::__is_pointer_p
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65159 --- Comment #12 from David Krauss --- I did exactly the steps that I mentioned: cleanly build r220825, update to r22, and build again without cleaning first. The object being to roughly replicate the conditions when the bug was originally observed — except originally the update was in the other direction, r22-ish to r220825. Is it always an error to do a non-clean build? The problem seems to happen pretty regularly.
[Bug c++/59766] c++1y: declaring friend function with 'auto' return type deduction is rejected with bogus reason
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59766 --- Comment #9 from David Krauss --- I didn't send it to gcc-patches. It's never been necessary for me before. I suppose I can collect the examples here into a testcase file. In the meantime, anyone else is free to take charge and submit it on their own. The change is just a matter of "don't do that."
[Bug c++/66001] New: [5.1/6 regression] ICE when NSDMI in a literal class uses a destructor
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66001 Bug ID: 66001 Summary: [5.1/6 regression] ICE when NSDMI in a literal class uses a destructor Product: gcc Version: 5.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: potswa at mac dot com Target Milestone: --- Works in 4.9.2, broken in 5.1. Not sure about 5. struct x { struct dt { ~ dt() {} } const & m = {}; } cx; in constexpr expansion of ‘cx.x::x()’ internal compiler error: unexpected expression ‘’ of kind try_finally
[Bug c++/66001] [5.1/6 regression] ICE when NSDMI in a literal class uses a destructor
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66001 --- Comment #1 from David Krauss --- If a non-constexpr constructor is addend to struct dt, the behavior is different, and inconsistent between a bound temporary and an initializer_list sequence. #include struct dt { dt() {} ~ dt() {} }; struct x { std::initializer_list< dt > f = { {} }; } cx; Result: In constructor ‘constexpr x::x()’: sorry, unimplemented: unexpected AST of kind try_block This program is accepted, though: struct dt { dt() {} ~ dt() {} }; struct x { dt && m = {}; } cx;