[cfe-commits] r148896 - in /cfe/trunk: lib/Parse/ParseTentative.cpp test/SemaCXX/PR11358.cpp
Nick Lewycky
nicholas at mxc.ca
Tue Jan 24 17:19:14 PST 2012
Author: nicholas
Date: Tue Jan 24 19:19:14 2012
New Revision: 148896
URL: http://llvm.org/viewvc/llvm-project?rev=148896&view=rev
Log:
With a little more work in the tentative parse determining whether a statement
is a declaration-stmt or an expression, we can discern a subset of cases where
the user erred in omitting the typename keyword before a dependent type name.
Fixes PR11358!
Added:
cfe/trunk/test/SemaCXX/PR11358.cpp
Modified:
cfe/trunk/lib/Parse/ParseTentative.cpp
Modified: cfe/trunk/lib/Parse/ParseTentative.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=148896&r1=148895&r2=148896&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTentative.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTentative.cpp Tue Jan 24 19:19:14 2012
@@ -864,7 +864,7 @@
if (TryAnnotateTypeOrScopeToken())
return TPResult::Error();
return isCXXDeclarationSpecifier();
-
+
// decl-specifier:
// storage-class-specifier
// type-specifier
@@ -950,8 +950,31 @@
// We've already annotated a scope; try to annotate a type.
if (TryAnnotateTypeOrScopeToken())
return TPResult::Error();
- if (!Tok.is(tok::annot_typename))
+ if (!Tok.is(tok::annot_typename)) {
+ // If the next token is an identifier or a type qualifier, then this
+ // can't possibly be a valid expression either.
+ if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) {
+ CXXScopeSpec SS;
+ Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
+ Tok.getAnnotationRange(),
+ SS);
+ if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
+ TentativeParsingAction PA(*this);
+ ConsumeToken();
+ ConsumeToken();
+ bool isIdentifier = Tok.is(tok::identifier);
+ TPResult TPR = TPResult::False();
+ if (!isIdentifier)
+ TPR = isCXXDeclarationSpecifier();
+ PA.Revert();
+
+ if (isIdentifier ||
+ TPR == TPResult::True() || TPR == TPResult::Error())
+ return TPResult::Error();
+ }
+ }
return TPResult::False();
+ }
// If that succeeded, fallthrough into the generic simple-type-id case.
// The ambiguity resides in a simple-type-specifier/typename-specifier
Added: cfe/trunk/test/SemaCXX/PR11358.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR11358.cpp?rev=148896&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/PR11358.cpp (added)
+++ cfe/trunk/test/SemaCXX/PR11358.cpp Tue Jan 24 19:19:14 2012
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 %s -verify
+// PR11358
+
+namespace test1 {
+ template<typename T>
+ struct container {
+ class iterator {};
+ iterator begin() { return iterator(); }
+ };
+
+ template<typename T>
+ struct Test {
+ typedef container<T> Container;
+ void test() {
+ Container::iterator i = c.begin(); // expected-error{{missing 'typename'}}
+ }
+ Container c;
+ };
+}
+
+namespace test2 {
+ template <typename Key, typename Value>
+ class hash_map {
+ class const_iterator { void operator++(); };
+ const_iterator begin() const;
+ const_iterator end() const;
+ };
+
+ template <typename KeyType, typename ValueType>
+ void MapTest(hash_map<KeyType, ValueType> map) {
+ for (hash_map<KeyType, ValueType>::const_iterator it = map.begin(); // expected-error{{missing 'typename'}}
+ it != map.end(); it++) {
+ }
+ }
+}
+
+namespace test3 {
+ template<typename T>
+ struct container {
+ class iterator {};
+ };
+
+ template<typename T>
+ struct Test {
+ typedef container<T> Container;
+ void test() {
+ Container::iterator const i; // expected-error{{missing 'typename'}}
+ }
+ Container c;
+ };
+}
More information about the cfe-commits
mailing list