[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