<div>On Thu Jan 30 2014 at 2:38:44 PM, Ismail Pazarbasi <<a href="mailto:ismail.pazarbasi@gmail.com">ismail.pazarbasi@gmail.com</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi rsmith,<br>
<br>
PR18127: misparse of 'new struct S < ...' where S is not a template-name<br>
<br>
If clang sees '<' token after an elaborated-type-specifier, it assumes elaborated-type-specifier refers to a template name, and then issues diagnostics concerning missing '>'.<br>
<br>
We try to find corresponding '>' for diagnostics location purpose, and perform name lookup. Parser knows that it is not parsing a template. If name lookup doesn't find a name, we will keep issuing `explicit instantiation/specialization of non-template class` error.<br>

<br>
<a href="http://llvm-reviews.chandlerc.com/D2662" target="_blank">http://llvm-reviews.chandlerc.<u></u>com/D2662</a><br>
<br>
Files:<br>
  lib/Parse/ParseDeclCXX.cpp<br>
  test/Parser/cxx-template-<u></u>argument.cpp<br>
<br>
Index: lib/Parse/ParseDeclCXX.cpp<br>
==============================<u></u>==============================<u></u>=======<br>
--- lib/Parse/ParseDeclCXX.cpp<br>
+++ lib/Parse/ParseDeclCXX.cpp<br>
@@ -24,6 +24,8 @@<br>
 #include "clang/Sema/Scope.h"<br>
 #include "clang/Sema/SemaDiagnostic.h"<br>
 #include "llvm/ADT/SmallString.h"<br>
+#include "clang/Sema/Lookup.h"<br>
+<br>
 using namespace clang;<br>
<br>
 /// ParseNamespace - We know that the current token is a namespace keyword. This<br>
@@ -1230,38 +1232,39 @@<br>
       // a class (or template thereof).<br>
       TemplateArgList TemplateArgs;<br>
       SourceLocation LAngleLoc, RAngleLoc;<br>
-      if (<u></u>ParseTemplateIdAfterTemplateNa<u></u>me(TemplateTy(), NameLoc, SS,<br>
-                                           true, LAngleLoc,<br>
-                                           TemplateArgs, RAngleLoc)) {<br>
-        // We couldn't parse the template argument list at all, so don't<br>
-        // try to give any location information for the list.<br>
-        LAngleLoc = RAngleLoc = SourceLocation();<br>
-      }<br>
-<br>
-      Diag(NameLoc, diag::err_explicit_spec_non_<u></u>template)<br>
-          << (TemplateInfo.Kind == ParsedTemplateInfo::<u></u>ExplicitInstantiation)<br>
-          << TagTokKind << Name << SourceRange(LAngleLoc, RAngleLoc);<br>
+      LAngleLoc = ConsumeToken();<br>
+      if (SkipUntil(tok::greater, StopBeforeMatch | StopAtSemi))<br>
+        RAngleLoc = ConsumeToken();<br>
+      // If a name was not found, this might be an explicit instantiation or<br>
+      // specialization attempt. If a name was found, that name does not refer<br>
+      // to a template name.<br>
+      LookupResult Result(Actions, Name, NameLoc, Sema::LookupTagName);<br>
+      Actions.LookupName(Result, getCurScope());<br></blockquote><div><br></div><div>This is using too low-level an interface from the Parser into Sema. Also, I'm not convinced this'll do the right thing if it finds an injected-class-name for a class template.</div>
<div><br></div><div>Can you use Sema::isTemplateName here?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      if (Result.getResultKind() != LookupResult::Found)<br>
+        Diag(NameLoc, diag::err_explicit_spec_non_<u></u>template)<br></blockquote><div><br></div><div>This is the wrong diagnostic in many cases (including the "new X < blah" case). This is fine if you have TemplateInfo telling you that we had template-parameter-lists, but otherwise, you should stop parsing before the '<'. In particular:</div>
<div><br></div><div>  bool k = new struct IDontExist < 0;</div><div><br></div><div>... should only diagnose allocation of an incomplete type, and</div><div><br></div><div>  struct A {</div><div>    template<typename T> operator T();</div>
<div>  };</div><div><div>  bool b = sizeof &A::operator struct Foo < 8;</div></div><div><br></div><div>... should be accepted without any diagnostics.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

+            << (TemplateInfo.Kind == ParsedTemplateInfo::<u></u>ExplicitInstantiation)<br>
+            << TagTokKind << Name << SourceRange(LAngleLoc, RAngleLoc);<br>
<br>
       // Strip off the last template parameter list if it was empty, since<br>
       // we've removed its template argument list.<br>
       if (TemplateParams && TemplateInfo.<u></u>LastParameterListWasEmpty) {<br>
         if (TemplateParams && TemplateParams->size() > 1) {<br>
           TemplateParams->pop_back();<br>
         } else {<br>
           TemplateParams = 0;<br>
-          const_cast<ParsedTemplateInfo&<u></u>>(TemplateInfo).Kind<br>
-            = ParsedTemplateInfo::<u></u>NonTemplate;<br>
+          const_cast<ParsedTemplateInfo &>(TemplateInfo).Kind =<br>
+              ParsedTemplateInfo::<u></u>NonTemplate;<br>
         }<br>
-      } else if (TemplateInfo.Kind<br>
-                                == ParsedTemplateInfo::<u></u>ExplicitInstantiation) {<br>
+      } else if (TemplateInfo.Kind ==<br>
+                 ParsedTemplateInfo::<u></u>ExplicitInstantiation) {<br>
         // Pretend this is just a forward declaration.<br>
         TemplateParams = 0;<br>
-        const_cast<ParsedTemplateInfo&<u></u>>(TemplateInfo).Kind<br>
-          = ParsedTemplateInfo::<u></u>NonTemplate;<br>
-        const_cast<ParsedTemplateInfo&<u></u>>(TemplateInfo).TemplateLoc<br>
-          = SourceLocation();<br>
-        const_cast<ParsedTemplateInfo&<u></u>>(TemplateInfo).ExternLoc<br>
-          = SourceLocation();<br>
+        const_cast<ParsedTemplateInfo &>(TemplateInfo).Kind =<br>
+            ParsedTemplateInfo::<u></u>NonTemplate;<br>
+        const_cast<ParsedTemplateInfo &>(TemplateInfo).TemplateLoc =<br>
+            SourceLocation();<br>
+        const_cast<ParsedTemplateInfo &>(TemplateInfo).ExternLoc =<br>
+            SourceLocation();<br>
       }<br>
     }<br>
   } else if (Tok.is(tok::annot_template_<u></u>id)) {<br>
Index: test/Parser/cxx-template-<u></u>argument.cpp<br>
==============================<u></u>==============================<u></u>=======<br>
--- test/Parser/cxx-template-<u></u>argument.cpp<br>
+++ test/Parser/cxx-template-<u></u>argument.cpp<br>
@@ -106,3 +106,21 @@<br>
   { };<br>
<br>
 }<br>
+<br>
+namespace PR18127 {<br>
+    struct A {} *a;<br>
+    bool f = new struct A < 0;<br>
+    bool g = new struct A < a;<br>
+<br>
+    template<typename T><br>
+    struct B { };<br>
+<br>
+    bool h = new struct B < 0;  // expected-error{{expected '>'}}<br>
+    bool i = new struct B<int> < 0;<br>
+    bool operator<(const struct O &, const struct O &);<br>
+    struct O { } *p;<br>
+    bool j = *(new struct O) < *p;<br>
+    bool k = new struct IDontExist < 0;  // expected-error{{explicit specialization of non-template struct 'IDontExist'}}<br>
+    // expected-error@-1{{allocation of incomplete type 'struct IDontExist'}}<br>
+    // expected-note@-2{{forward declaration of 'PR18127::IDontExist'}}<br>
+}<br>
</blockquote>