Hi rsmith,

Hi Richard,
I attempted to implement a patch to fix [temp.local] p7 which states as -
"In the definition of a member of a class template that appears outside of the 
class template definition, the
name of a member of the class template hides the name of a template-parameter 
of any enclosing class
templates (but not a template-parameter of the member if the member is a class 
or function template)."

Clang incorrectly compiles the test code updated in this revision as the name 
lookup finds the 'U' as member of the template class instead of taking it as 
the template parameter.

This was also discussed at 
http://clang-developers.42468.n3.nabble.com/Name-lookup-of-class-member-vs-template-parameter-td4036312.html

What we have tried to do here is detect if we are inside a class scope in 
member of a class template and set the semacontext to the same so that  name 
lookup should continue searching in this semantic context.

I also had a doubt here it would be great if you could clarify the same -
Isnt the above rule applicable even if we have something like -

  template<class B> struct C {
    struct U { typedef int X; };
    template<class U>
        struct D;
  };

  template<class B>
  template<class U>
  struct C<B>::D {
    void f() {
      typename U::X r; // expected-error {{type 'double' cannot be used prior 
to '::' because it has no members}}
    }
  };
  C<int>::D<double> y; // expected-note {{in instantiation of template class 
'C<int>::D<double>' requested here}}


i.e. we have a definition outside of the class template and a function defined 
inside it which uses the parameter 'U' in this case shouldnt we take 'U' as the 
template parameter? Both clang and gcc 4.8.1 compiles this code. But as per 
standard this seems wrong. Am i correct here or i'm missing something?


I'm a bit new to template implementation in compilers. It would be great if you 
could let me know if this is the right direction to fix this issue and guide us 
through this bug. 


Thanks
Karthik


http://llvm-reviews.chandlerc.com/D2327

Files:
  lib/Sema/SemaLookup.cpp
  test/CXX/temp/temp.res/temp.local/p7.cpp

Index: lib/Sema/SemaLookup.cpp
===================================================================
--- lib/Sema/SemaLookup.cpp
+++ lib/Sema/SemaLookup.cpp
@@ -849,8 +849,11 @@
   // Find the namespace context in which the original scope occurs. In
   // the example, this is namespace N.
   DeclContext *Semantic = DC;
-  while (!Semantic->isFileContext())
+  while (!Semantic->isFileContext()) {
     Semantic = Semantic->getParent();
+    if (S->isClassScope())
+      break;
+  }
 
   // Find the declaration context just outside of the template
   // parameter scope. This is the context in which the template is
Index: test/CXX/temp/temp.res/temp.local/p7.cpp
===================================================================
--- test/CXX/temp/temp.res/temp.local/p7.cpp
+++ test/CXX/temp/temp.res/temp.local/p7.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
 
 template<class T> struct A { 
   int B;
@@ -9,3 +8,22 @@
 template<class B> int A<B>::f() {
   return B;
 }
+
+struct A1 {
+    struct B { typedef int X; };
+};
+
+template<class B> struct C : A1 {
+    B::X q; // Ok: A1::B.
+    struct U { typedef int X; };
+    template<class U>
+        struct D;
+};
+
+template<class B>
+template<class U>
+struct C<B>::D {
+    typename U::X r; // expected-error {{type 'double' cannot be used prior to 
'::' because it has no members}}
+};
+
+C<int>::D<double> y; // expected-note {{in instantiation of template class 
'C<int>::D<double>' requested here}}
Index: lib/Sema/SemaLookup.cpp
===================================================================
--- lib/Sema/SemaLookup.cpp
+++ lib/Sema/SemaLookup.cpp
@@ -849,8 +849,11 @@
   // Find the namespace context in which the original scope occurs. In
   // the example, this is namespace N.
   DeclContext *Semantic = DC;
-  while (!Semantic->isFileContext())
+  while (!Semantic->isFileContext()) {
     Semantic = Semantic->getParent();
+    if (S->isClassScope())
+      break;
+  }
 
   // Find the declaration context just outside of the template
   // parameter scope. This is the context in which the template is
Index: test/CXX/temp/temp.res/temp.local/p7.cpp
===================================================================
--- test/CXX/temp/temp.res/temp.local/p7.cpp
+++ test/CXX/temp/temp.res/temp.local/p7.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-// expected-no-diagnostics
 
 template<class T> struct A { 
   int B;
@@ -9,3 +8,22 @@
 template<class B> int A<B>::f() {
   return B;
 }
+
+struct A1 {
+    struct B { typedef int X; };
+};
+
+template<class B> struct C : A1 {
+    B::X q; // Ok: A1::B.
+    struct U { typedef int X; };
+    template<class U>
+        struct D;
+};
+
+template<class B>
+template<class U>
+struct C<B>::D {
+    typename U::X r; // expected-error {{type 'double' cannot be used prior to '::' because it has no members}}
+};
+
+C<int>::D<double> y; // expected-note {{in instantiation of template class 'C<int>::D<double>' requested here}}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to