Ping! Sorry for the <1 week ping, but I just got another bug report about this issue. Testcase:<div><br></div><div><div>#include <hash_map></div><div>using namespace std;</div><div>using namespace __gnu_cxx;</div>

<div>template <typename KeyType, typename ValueType></div><div>void MapTest(hash_map<KeyType, ValueType> map) {</div><div>  for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); it != map.end(); it++) {</div>

<div>  }</div><div>}</div><div><br></div><div>without this patch produces:</div><div><br></div><div><div><div>z.cc:6:53: error: expected ';' in 'for' statement specifier</div><div>  for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); ...</div>

<div>                                                    ^</div><div>z.cc:6:53: error: use of undeclared identifier 'it'</div><div>z.cc:6:71: error: use of undeclared identifier 'it'</div><div>  for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); it ...</div>

<div>                                                                      ^</div><div>z.cc:6:86: error: expected ')'</div><div>  ...ValueType>::const_iterator it = map.begin(); it != map.end(); it++) {</div><div>

                                                                 ^</div><div>z.cc:6:7: note: to match this '('</div><div>  for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); ...</div><div>      ^</div>

<div>z.cc:6:88: error: use of undeclared identifier 'it'</div><div>  ...ValueType>::const_iterator it = map.begin(); it != map.end(); it++) {</div><div>                                                                   ^</div>

</div></div><div><br></div><div>but with this patch produces:</div><div><br></div><div><div><div>z.cc:6:8: error: missing 'typename' prior to dependent type name</div><div>      'hash_map<KeyType, ValueType>::const_iterator'</div>

<div>  for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); ...</div><div>       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</div><div>       typename                                                       </div>

</div></div><div><br></div><div>Same patch attached again. Please review!</div><div><br></div><div>Nick</div><div><br></div><br><div class="gmail_quote">On 20 January 2012 17:54, Nick Lewycky <span dir="ltr"><<a href="mailto:nlewycky@google.com">nlewycky@google.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The attached patch fixes PR11358:<div><br></div><div><div>pr11358.cc:11:5: error: missing 'typename' prior to dependent type name</div>

<div>      'Container::iterator'</div><div>    Container::iterator i = c.begin();</div>
<div>    ^~~~~~~~~~~~~~~~~~~</div><div>    typename </div></div><div><br></div><div>It works by teaching Parser::isCXXDeclarationSpecifier() to, in the event of a cxxscope annotation followed by an identifier, ("Container::" and "iterator" in the above example), look at the next token. Yes, this means doing two-tokens of look-ahead. If that next token is an identifier or cvr-qualifier, we conclude that this can't possibly be an expression and return a parse error.</div>


<div><br></div><div>This is pretty important because some developers don't seem to understand the rule for where they need to put typename, and Clang has exacerbated this by teaching them that they only need to put typename where the compiler tells them to put typename. Consequently, when we don't tell them to put typename there, that isn't one of the things they'll try any more.</div>


<div><br></div><div>The condition under which we'll do an extra token of look-ahead is when we see a dependent nested-name-specifier followed by an identifier while doing the tentative parse to determine whether the statement is a declaration or an expression. This is reasonably rare. Here's some build times of boost:</div>


<div><br></div><div>run of "bootstrap"</div><div>with patch: 0m26.460s 0m26.530s</div><div>without patch: 0m25.510s 0m26.110s</div><div>run of "b2"</div><div><div>with patch: 13m12.050s 12m58.670s</div>


</div><div>without patch: 12m26.260s 13m9.030s</div><div><br></div><div>So we conclude that my testing machine is crazy noisy, but at least the patch doesn't cause a horrible performance regression. To give you another statistic, the number of times we need to look ahead by one more token is slightly less than 250,000 times across all translation units in an llvm+clang build. I haven't checked how many of those are unique.</div>


<div><br></div><div>Please review!</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>Nick</div><div><br></div>
</font></span></blockquote></div><br></div>