r332291 - Fix regression in r332076.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon May 14 13:52:48 PDT 2018


Author: rsmith
Date: Mon May 14 13:52:48 2018
New Revision: 332291

URL: http://llvm.org/viewvc/llvm-project?rev=332291&view=rev
Log:
Fix regression in r332076.

If the name after 'template' is an unresolved using declaration (not containing
'typename'), then we don't yet know if it's a valid template-name, so don't
reject it prior to instantiation. Instead, treat it as naming a dependent
member of the current instantiation.

Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/drs/dr1xx.cpp
    cfe/trunk/test/SemaTemplate/dependent-names.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=332291&r1=332290&r2=332291&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon May 14 13:52:48 2018
@@ -105,6 +105,12 @@ static NamedDecl *isAcceptableTemplateNa
     return nullptr;
   }
 
+  // 'using Dependent::foo;' can resolve to a template name.
+  // 'using typename Dependent::foo;' cannot (not even if 'foo' is an
+  // injected-class-name).
+  if (isa<UnresolvedUsingValueDecl>(D))
+    return D;
+
   return nullptr;
 }
 
@@ -214,6 +220,10 @@ TemplateNameKind Sema::isTemplateName(Sc
 
     // We'll do this lookup again later.
     R.suppressDiagnostics();
+  } else if (isa<UnresolvedUsingValueDecl>((*R.begin())->getUnderlyingDecl())) {
+    // We don't yet know whether this is a template-name or not.
+    MemberOfUnknownSpecialization = true;
+    return TNK_Non_template;
   } else {
     TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl());
 
@@ -429,7 +439,7 @@ bool Sema::LookupTemplateName(LookupResu
     if (ExampleLookupResult && TemplateKWLoc.isValid()) {
       Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template)
         << Found.getLookupName() << SS.getRange();
-      Diag(ExampleLookupResult->getLocation(),
+      Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(),
            diag::note_template_kw_refers_to_non_template)
           << Found.getLookupName();
       return true;

Modified: cfe/trunk/test/CXX/drs/dr1xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr1xx.cpp?rev=332291&r1=332290&r2=332291&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr1xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr1xx.cpp Mon May 14 13:52:48 2018
@@ -71,8 +71,7 @@ namespace dr109 { // dr109: yes
     using T::template f<int>; // expected-error {{'template' keyword not permitted here}} expected-error {{using declaration cannot refer to a template specialization}}
     // FIXME: We shouldn't suggest using the 'template' keyword in a location where it's not valid.
     using T::f<int>; // expected-error {{use 'template' keyword}} expected-error {{using declaration cannot refer to a template specialization}}
-    // FIXME: The first 'using' above introduces 'f' as a non-template member of 'B', leading to bad recovery:
-    void g() { this->f<int>(123); } // expected-error {{expected '('}}
+    void g() { this->f<int>(123); } // expected-error {{use 'template' keyword}}
   };
 }
 

Modified: cfe/trunk/test/SemaTemplate/dependent-names.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-names.cpp?rev=332291&r1=332290&r2=332291&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/dependent-names.cpp (original)
+++ cfe/trunk/test/SemaTemplate/dependent-names.cpp Mon May 14 13:52:48 2018
@@ -427,3 +427,23 @@ namespace DependentTemplateIdWithNoArgs
   };
   void g() { f<X>(); }
 }
+
+namespace DependentUnresolvedUsingTemplate {
+  template<typename T>
+  struct X : T {
+    using T::foo;
+    void f() { this->template foo(); } // expected-error {{does not refer to a template}}
+    void g() { this->template foo<>(); } // expected-error {{does not refer to a template}}
+    void h() { this->template foo<int>(); } // expected-error {{does not refer to a template}}
+  };
+  struct A { template<typename = int> int foo(); };
+  struct B { int foo(); }; // expected-note 3{{non-template here}}
+  void test(X<A> xa, X<B> xb) {
+    xa.f();
+    xa.g();
+    xa.h();
+    xb.f(); // expected-note {{instantiation of}}
+    xb.g(); // expected-note {{instantiation of}}
+    xb.h(); // expected-note {{instantiation of}}
+  }
+}




More information about the cfe-commits mailing list