efriedma created this revision.
efriedma added a reviewer: rsmith.
Herald added a project: clang.

When we see something like `i<i`, we try to check whether the second "i" refers 
to a type.  However, when we do this, we can end up creating an expression in 
the wrong context: the "<" has different parse priority if it's actually a 
relational operator.

To fix the issue, just remove the check.  This makes diagnostics slightly 
worse, but avoids the crash.  I'm not really happy with this, but I don't see 
another way to fix this without implementing a giant refactoring.

Fixes https://bugs.llvm.org/show_bug.cgi?id=43080 (but not the issues currently 
marked as "duplicate"; I haven't dug deeply into the causes of those issues).


Repository:
  rC Clang

https://reviews.llvm.org/D68849

Files:
  lib/Parse/ParseTemplate.cpp
  test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
  test/CodeGenCXX/odr-use.cpp
  test/SemaCXX/cxx1y-variable-templates_top_level.cpp
  test/SemaTemplate/typo-template-name.cpp

Index: test/SemaTemplate/typo-template-name.cpp
===================================================================
--- test/SemaTemplate/typo-template-name.cpp
+++ test/SemaTemplate/typo-template-name.cpp
@@ -5,14 +5,14 @@
     void typo_first_a(); // expected-note {{found}}
     template<typename T> void typo_first_b(); // expected-note 2{{declared here}}
   }
-  void testA() { A::typo_first_a<int>(); } // expected-error {{'typo_first_a' does not name a template but is followed by template arguments; did you mean 'typo_first_b'?}}
+  void testA() { A::typo_first_a<int>(); } // expected-error {{expected '(' for function-style cast or type construction}} expected-error {{'typo_first_a' does not name a template but is followed by template arguments; did you mean 'typo_first_b'?}}
 
   namespace B {
     void typo_first_b(); // expected-note {{found}}
   }
-  void testB() { B::typo_first_b<int>(); } // expected-error {{'typo_first_b' does not name a template but is followed by template arguments; did you mean 'A::typo_first_b'?}}
+  void testB() { B::typo_first_b<int>(); } // expected-error {{expected '(' for function-style cast or type construction}} expected-error {{'typo_first_b' does not name a template but is followed by template arguments; did you mean 'A::typo_first_b'?}}
 
-  struct Base {
+  struct Base { // expected-note {{declared here}}
     template<typename T> static void foo(); // expected-note 4{{declared here}}
     int n;
   };
@@ -20,19 +20,19 @@
     void foo(); // expected-note {{found}}
   };
   // We probably don't want to suggest correcting to .Base::foo<int>
-  void testMember() { Derived().foo<int>(); } // expected-error-re {{does not name a template but is followed by template arguments{{$}}}}
+  void testMember() { Derived().foo<int>(); } // expected-error {{expected '(' for function-style cast or type construction}} expected-error-re {{does not name a template but is followed by template arguments{{$}}}}
 
   struct Derived2 : Base {
     void goo(); // expected-note {{found}}
   };
-  void testMember2() { Derived2().goo<int>(); } // expected-error {{member 'goo' of 'InExpr::Derived2' is not a template; did you mean 'foo'?}}
+  void testMember2() { Derived2().goo<int>(); } // expected-error {{expected '(' for function-style cast or type construction}} expected-error {{member 'goo' of 'InExpr::Derived2' is not a template; did you mean 'foo'?}}
 
   void no_correction() {
     int foo; // expected-note 3{{found}}
 
-    foo<int>(); // expected-error {{'foo' does not name a template but is followed by template arguments; did you mean 'Base::foo'?}}
+    foo<int>(); // expected-error {{expected '(' for function-style cast or type construction}} expected-error {{'foo' does not name a template but is followed by template arguments; did you mean 'Base::foo'?}}
     foo<>(); // expected-error {{'foo' does not name a template but is followed by template arguments; did you mean 'Base::foo'?}}
-    foo<Base *>(); // expected-error {{'foo' does not name a template but is followed by template arguments; did you mean 'Base::foo'?}}
+    foo<Base *>(); //  expected-error {{'Base' does not refer to a value}} expected-error {{expected expression}} expected-error {{'foo' does not name a template but is followed by template arguments; did you mean 'Base::foo'?}}
 
     // These are valid expressions.
     foo<foo; // expected-warning {{self-comparison}}
Index: test/SemaCXX/cxx1y-variable-templates_top_level.cpp
===================================================================
--- test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -9,7 +9,7 @@
 #endif
 
 template<typename T> 
-T pi = T(3.1415926535897932385); // expected-note 2{{declared here}}
+T pi = T(3.1415926535897932385); // expected-note {{declared here}}
 
 template<typename T> 
 CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}}
@@ -58,9 +58,9 @@
 namespace shadow {
   void foo() {
     int ipi0 = pi<int>;
-    int pi; // expected-note {{found}}
+    int pi;
     int a = pi;
-    int ipi = pi<int>;  // expected-error {{'pi' does not name a template but is followed by template arguments; did you mean '::pi'?}}
+    int ipi = pi<int>;  // expected-error {{expected '(' for function-style cast or type construction}} expected-error {{expected expression}}
   }
 }
 
Index: test/CodeGenCXX/odr-use.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/odr-use.cpp
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - -triple x86_64-linux-gnu %s | FileCheck %s --check-prefixes=CHECK
+
+// Make sure this doesn't crash, and produces reasonable output
+// CHECK: icmp ult i64 4,
+int f(int i) { return sizeof i<i; }
Index: test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
===================================================================
--- test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
+++ test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
@@ -26,19 +26,13 @@
 }
 
 namespace std_example {
-  int h; // expected-note {{non-template declaration}}
+  int h;
   void g();
-#if __cplusplus <= 201703L
-  // expected-note@-2 {{non-template declaration}}
-#endif
   namespace N {
     struct A {};
     template<class T> int f(T);
     template<class T> int g(T);
-#if __cplusplus <= 201703L
-    // expected-note@-2 {{here}}
-#endif
-    template<class T> int h(T); // expected-note {{here}}
+    template<class T> int h(T);
   }
 
   int x = f<N::A>(N::A());
@@ -47,9 +41,9 @@
 #endif
   int y = g<N::A>(N::A());
 #if __cplusplus <= 201703L
-  // expected-error@-2 {{'g' does not name a template but is followed by template arguments; did you mean 'N::g'?}}
+  // expected-error@-2 {{expected '(' for function-style cast or type construction}}
 #endif
-  int z = h<N::A>(N::A()); // expected-error {{'h' does not name a template but is followed by template arguments; did you mean 'N::h'?}}
+  int z = h<N::A>(N::A()); // expected-error {{expected '(' for function-style cast or type construction}}
 }
 
 namespace AnnexD_example {
Index: lib/Parse/ParseTemplate.cpp
===================================================================
--- lib/Parse/ParseTemplate.cpp
+++ lib/Parse/ParseTemplate.cpp
@@ -1609,22 +1609,6 @@
     return;
   }
 
-  // If we have 'potential_template<type-id', assume it's supposed to be a
-  // template-name if there's a matching '>' later on.
-  {
-    // FIXME: Avoid the tentative parse when NextToken() can't begin a type.
-    TentativeParsingAction TPA(*this);
-    SourceLocation Less = ConsumeToken();
-    if (isTypeIdUnambiguously() &&
-        diagnoseUnknownTemplateId(PotentialTemplateName, Less)) {
-      TPA.Commit();
-      // FIXME: Perform error recovery.
-      PotentialTemplateName = ExprError();
-      return;
-    }
-    TPA.Revert();
-  }
-
   // Otherwise, remember that we saw this in case we see a potentially-matching
   // '>' token later on.
   AngleBracketTracker::Priority Priority =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D68849: [... Eli Friedman via Phabricator via cfe-commits

Reply via email to