r180707 - Implement DR580: access checks for template parameters of a class template are

Richard Smith richard-llvm at metafoo.co.uk
Mon Apr 29 03:13:55 PDT 2013


Author: rsmith
Date: Mon Apr 29 05:13:55 2013
New Revision: 180707

URL: http://llvm.org/viewvc/llvm-project?rev=180707&view=rev
Log:
Implement DR580: access checks for template parameters of a class template are
performed within the context of that class template. Patch by Ismail Pazarbasi!

Modified:
    cfe/trunk/lib/Sema/SemaAccess.cpp
    cfe/trunk/test/SemaCXX/access.cpp

Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=180707&r1=180706&r2=180707&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Mon Apr 29 05:13:55 2013
@@ -84,10 +84,10 @@ struct EffectiveContext {
     : Inner(DC),
       Dependent(DC->isDependentContext()) {
 
-    // C++ [class.access.nest]p1:
+    // C++11 [class.access.nest]p1:
     //   A nested class is a member and as such has the same access
     //   rights as any other member.
-    // C++ [class.access]p2:
+    // C++11 [class.access]p2:
     //   A member of a class can also access all the names to which
     //   the class has access.  A local class of a member function
     //   may access the same names that the member function itself
@@ -1476,18 +1476,18 @@ static Sema::AccessResult CheckAccess(Se
   llvm_unreachable("falling off end");
 }
 
-void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) {
+void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *D) {
   // Access control for names used in the declarations of functions
   // and function templates should normally be evaluated in the context
   // of the declaration, just in case it's a friend of something.
   // However, this does not apply to local extern declarations.
 
-  DeclContext *DC = decl->getDeclContext();
-  if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
-    if (!DC->isFunctionOrMethod()) DC = fn;
-  } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) {
-    // Never a local declaration.
-    DC = fnt->getTemplatedDecl();
+  DeclContext *DC = D->getDeclContext();
+  if (FunctionDecl *FN = dyn_cast<FunctionDecl>(D)) {
+    if (!DC->isFunctionOrMethod())
+      DC = FN;
+  } else if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) {
+    DC = cast<DeclContext>(TD->getTemplatedDecl());
   }
 
   EffectiveContext EC(DC);

Modified: cfe/trunk/test/SemaCXX/access.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/access.cpp?rev=180707&r1=180706&r2=180707&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/access.cpp (original)
+++ cfe/trunk/test/SemaCXX/access.cpp Mon Apr 29 05:13:55 2013
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
 
 class C {
     struct S; // expected-note {{previously declared 'private' here}}
@@ -32,3 +32,77 @@ namespace test1 {
     class X {};
   };
 }
+
+// PR15209
+namespace PR15209 {
+  namespace alias_templates {
+    template<typename T1, typename T2> struct U { };
+    template<typename T1> using W = U<T1, float>;
+
+    class A {
+      typedef int I;
+      static constexpr I x = 0; // expected-note {{implicitly declared private here}}
+      static constexpr I y = 42; // expected-note {{implicitly declared private here}}
+      friend W<int>;
+    };
+
+    template<typename T1>
+    struct U<T1, float>  {
+      int v_;
+      // the following will trigger for U<float, float> instantiation, via W<float>
+      U() : v_(A::x) { } // expected-error {{'x' is a private member of 'PR15209::alias_templates::A'}}
+    };
+
+    template<typename T1>
+    struct U<T1, int> {
+      int v_;
+      U() : v_(A::y) { } // expected-error {{'y' is a private member of 'PR15209::alias_templates::A'}}
+    };
+
+    template struct U<int, int>; // expected-note {{in instantiation of member function 'PR15209::alias_templates::U<int, int>::U' requested here}}
+
+    void f()
+    {
+      W<int>();
+      // we should issue diagnostics for the following
+      W<float>(); // expected-note {{in instantiation of member function 'PR15209::alias_templates::U<float, float>::U' requested here}}
+    }
+  }
+
+  namespace templates {
+    class A {
+      typedef int I;  // expected-note {{implicitly declared private here}}
+      static constexpr I x = 0; // expected-note {{implicitly declared private here}}
+
+      template<int> friend struct B;
+      template<int> struct C;
+      template<template<int> class T> friend struct TT;
+      template<typename T> friend void funct(T);
+    };
+    template<A::I> struct B { };
+
+    template<A::I> struct A::C { };
+
+    template<template<A::I> class T> struct TT {
+      T<A::x> t;
+    };
+
+    template struct TT<B>;
+    template<A::I> struct D { };  // expected-error {{'I' is a private member of 'PR15209::templates::A'}}
+    template struct TT<D>;
+
+    // function template case
+    template<typename T>
+    void funct(T)
+    {
+      (void)A::x;
+    }
+
+    template void funct<int>(int);
+
+    void f()
+    {
+      (void)A::x;  // expected-error {{'x' is a private member of 'PR15209::templates::A'}}
+    }
+  }
+}





More information about the cfe-commits mailing list