[cfe-commits] r102572 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateInstantiate.cpp test/CXX/class.access/p6.cpp
John McCall
rjmccall at apple.com
Wed Apr 28 17:35:03 PDT 2010
Author: rjmccall
Date: Wed Apr 28 19:35:03 2010
New Revision: 102572
URL: http://llvm.org/viewvc/llvm-project?rev=102572&view=rev
Log:
Properly switch into the declaring scope of a template when performing
template argument deduction or (more importantly) the final substitution
required by such deduction. Makes access control magically work in these
cases.
Fixes PR6967.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/test/CXX/class.access/p6.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=102572&r1=102571&r2=102572&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Apr 28 19:35:03 2010
@@ -233,6 +233,30 @@
/// CurContext - This is the current declaration context of parsing.
DeclContext *CurContext;
+ /// A RAII object to temporarily push a declaration context.
+ class ContextRAII {
+ private:
+ Sema &S;
+ DeclContext *SavedContext;
+
+ public:
+ ContextRAII(Sema &S, DeclContext *ContextToPush)
+ : S(S), SavedContext(S.CurContext) {
+ assert(ContextToPush && "pushing null context");
+ S.CurContext = ContextToPush;
+ }
+
+ void pop() {
+ if (!SavedContext) return;
+ S.CurContext = SavedContext;
+ SavedContext = 0;
+ }
+
+ ~ContextRAII() {
+ pop();
+ }
+ };
+
/// PackContext - Manages the stack for #pragma pack. An alignment
/// of 0 indicates default alignment.
void *PackContext; // Really a "PragmaPackStack*"
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=102572&r1=102571&r2=102572&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Apr 28 19:35:03 2010
@@ -988,6 +988,8 @@
if (Inst)
return TDK_InstantiationDepth;
+ ContextRAII SavedContext(*this, Partial->getDeclContext());
+
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
@@ -1163,6 +1165,8 @@
if (Inst)
return TDK_InstantiationDepth;
+ ContextRAII SavedContext(*this, FunctionTemplate->getDeclContext());
+
if (CheckTemplateArgumentList(FunctionTemplate,
SourceLocation(),
ExplicitTemplateArgs,
@@ -1311,6 +1315,8 @@
if (Inst)
return TDK_InstantiationDepth;
+ ContextRAII SavedContext(*this, FunctionTemplate->getDeclContext());
+
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=102572&r1=102571&r2=102572&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Apr 28 19:35:03 2010
@@ -1167,8 +1167,7 @@
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
- DeclContext *PreviousContext = CurContext;
- CurContext = Instantiation;
+ ContextRAII SavedContext(*this, Instantiation);
// If this is an instantiation of a local class, merge this local
// instantiation scope with the enclosing scope. Otherwise, every
@@ -1209,7 +1208,7 @@
Invalid = true;
// Exit the scope of this instantiation.
- CurContext = PreviousContext;
+ SavedContext.pop();
// If this is a polymorphic C++ class without a key function, we'll
// have to mark all of the virtual members to allow emission of a vtable
Modified: cfe/trunk/test/CXX/class.access/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/p6.cpp?rev=102572&r1=102571&r2=102572&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/p6.cpp (original)
+++ cfe/trunk/test/CXX/class.access/p6.cpp Wed Apr 28 19:35:03 2010
@@ -52,3 +52,56 @@
A apriv = priv; // expected-error {{private constructor}}
}
}
+
+// PR6967
+namespace test2 {
+ class A {
+ public:
+ template <class T> static void set(T &t, typename T::type v) {
+ t.value = v;
+ }
+ template <class T> static typename T::type get(const T &t) {
+ return t.value;
+ }
+ };
+
+ class B {
+ friend class A;
+
+ private:
+ typedef int type;
+ type value;
+ };
+
+ int test() {
+ B b;
+ A::set(b, 0);
+ return A::get(b);
+ }
+}
+
+namespace test3 {
+ class Green {}; class Blue {};
+
+ // We have to wrap this in a class because a partial specialization
+ // isn't actually in the context of the template.
+ struct Outer {
+ template <class T, class Nat> class A {
+ };
+ };
+
+ template <class T> class Outer::A<T, typename T::nature> {
+ public:
+ static void foo();
+ };
+
+ class B {
+ private: typedef Green nature;
+ friend class Outer;
+ };
+
+ void test() {
+ Outer::A<B, Green>::foo();
+ Outer::A<B, Blue>::foo(); // expected-error {{no member named 'foo'}}
+ }
+}
More information about the cfe-commits
mailing list