/// 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*"
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.
if (Inst)
return TDK_InstantiationDepth;
+ ContextRAII SavedContext(*this, FunctionTemplate->getDeclContext());
+
if (CheckTemplateArgumentList(FunctionTemplate,
SourceLocation(),
ExplicitTemplateArgs,
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.
// 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
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
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'}}
+ }
+}