summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2010-06-28 08:39:25 +0000
committerChandler Carruth <chandlerc@gmail.com>2010-06-28 08:39:25 +0000
commit2d69ec7a7232aa9fd804c3392650f74a8d65c55d (patch)
treedf74cd13e2630f21c5610b2e83214ad33070db51 /clang
parent61176897bac13ed98d566b1cc0f8d0451ec3926b (diff)
downloadbcm5719-llvm-2d69ec7a7232aa9fd804c3392650f74a8d65c55d.tar.gz
bcm5719-llvm-2d69ec7a7232aa9fd804c3392650f74a8d65c55d.zip
Partial fix for PR7267 based on comments by John McCall on an earlier patch.
This is more targeted, as it simply provides toggle actions for the parser to turn access checking on and off. We then use these to suppress access checking only while we parse the template-id (included scope specifier) of an explicit instantiation and explicit specialization of a class template. The specialization behavior is an extension, as it seems likely a defect that the standard did not exempt them as it does explicit instantiations. This allows the very common practice of specializing trait classes to work for private, internal types. This doesn't address instantiating or specializing function templates, although those apparently already partially work. The naming and style for the Action layer isn't my favorite, comments and suggestions would be appreciated there. llvm-svn: 106993
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Parse/Action.h10
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp22
-rw-r--r--clang/lib/Sema/Sema.cpp4
-rw-r--r--clang/lib/Sema/Sema.h6
-rw-r--r--clang/lib/Sema/SemaAccess.cpp15
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp18
6 files changed, 73 insertions, 2 deletions
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h
index d8bb8a5b615..fed4361f1ae 100644
--- a/clang/include/clang/Parse/Action.h
+++ b/clang/include/clang/Parse/Action.h
@@ -2278,6 +2278,16 @@ public:
return TypeResult();
}
+ /// \brief Called when the parser begins parsing a construct which should not
+ /// have access control applied to it.
+ virtual void ActOnStartSuppressingAccessChecks() {
+ }
+
+ /// \brief Called when the parser finishes parsing a construct which should
+ /// not have access control applied to it.
+ virtual void ActOnStopSuppressingAccessChecks() {
+ }
+
//===----------------------- Obj-C Declarations -------------------------===//
// ActOnStartClassInterface - this action is called immediately after parsing
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 53fc3405bb3..ffef288e71e 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -613,6 +613,20 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ConsumeCodeCompletionToken();
}
+ // C++03 [temp.explicit] 14.7.2/8:
+ // The usual access checking rules do not apply to names used to specify
+ // explicit instantiations.
+ //
+ // As an extension we do not perform access checking on the names used to
+ // specify explicit specializations either. This is important to allow
+ // specializing traits classes for private types.
+ bool SuppressingAccessChecks = false;
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
+ TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) {
+ Actions.ActOnStartSuppressingAccessChecks();
+ SuppressingAccessChecks = true;
+ }
+
AttributeList *AttrList = 0;
// If attributes exist after tag, parse them.
if (Tok.is(tok::kw___attribute))
@@ -732,10 +746,18 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
DS.SetTypeSpecError();
SkipUntil(tok::semi, false, true);
TemplateId->Destroy();
+ if (SuppressingAccessChecks)
+ Actions.ActOnStopSuppressingAccessChecks();
+
return;
}
}
+ // As soon as we're finished parsing the class's template-id, turn access
+ // checking back on.
+ if (SuppressingAccessChecks)
+ Actions.ActOnStopSuppressingAccessChecks();
+
// There are four options here. If we have 'struct foo;', then this
// is either a forward declaration or a friend declaration, which
// have to be treated differently. If we have 'struct foo {...' or
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index eadc2ad253d..d520a78abec 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -125,8 +125,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
GlobalNewDeleteDeclared(false),
CompleteTranslationUnit(CompleteTranslationUnit),
- NumSFINAEErrors(0), NonInstantiationEntries(0),
- CurrentInstantiationScope(0), TyposCorrected(0),
+ NumSFINAEErrors(0), SuppressAccessChecking(false),
+ NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0),
AnalysisWarnings(*this)
{
TUScope = 0;
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 9d5e290b2f6..fcf5e94149f 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2797,6 +2797,12 @@ public:
void HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx);
+ /// A flag to suppress access checking.
+ bool SuppressAccessChecking;
+
+ void ActOnStartSuppressingAccessChecks();
+ void ActOnStopSuppressingAccessChecks();
+
enum AbstractDiagSelID {
AbstractNone = -1,
AbstractReturnType,
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index 7845f6d0a94..e110e3dfa47 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1024,6 +1024,9 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
if (Entity.getAccess() == AS_public)
return Sema::AR_accessible;
+ if (S.SuppressAccessChecking)
+ return Sema::AR_accessible;
+
// If we're currently parsing a top-level declaration, delay
// diagnostics. This is the only case where parsing a declaration
// can actually change our effective context for the purposes of
@@ -1334,3 +1337,15 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
}
}
}
+
+void Sema::ActOnStartSuppressingAccessChecks() {
+ assert(!SuppressAccessChecking &&
+ "Tried to start access check suppression when already started.");
+ SuppressAccessChecking = true;
+}
+
+void Sema::ActOnStopSuppressingAccessChecks() {
+ assert(SuppressAccessChecking &&
+ "Tried to stop access check suprression when already stopped.");
+ SuppressAccessChecking = false;
+}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp
new file mode 100644
index 00000000000..4ca54283157
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+class X {
+ template <typename T> class Y {};
+};
+
+class A {
+ class B {};
+ class C {};
+};
+
+// C++0x [temp.explicit] 14.7.2/11:
+// The usual access checking rules do not apply to names used to specify
+// explicit instantiations.
+template class X::Y<A::B>;
+
+// As an extension, this rule is applied to explicit specializations as well.
+template <> class X::Y<A::C> {};
OpenPOWER on IntegriCloud