aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2012-08-10 03:15:35 +0000
committerJohn McCall <rjmccall@apple.com>2012-08-10 03:15:35 +0000
commit1f2e1a96bec2ba6418ae7f2d2b525a3575203b6a (patch)
tree4186ca57ea4f54df5ac62a3528a8ab089fe75f65 /lib/Sema/SemaTemplateInstantiateDecl.cpp
parent7c304f56eecbd03db7d222a05dfcd593750d50d3 (diff)
Check access to friend declarations. There's a number of different
things going on here that were problematic: - We were missing the actual access check, or rather, it was suppressed on account of being a redeclaration lookup. - The access check would naturally happen during delay, which isn't appropriate in this case. - We weren't actually emitting dependent diagnostics associated with class templates, which was unfortunate. - Access was being propagated incorrectly for friend method declarations that couldn't be matched at parse-time. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161652 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp48
1 files changed, 34 insertions, 14 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 15ddd7df98..bdbe71dd8a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -935,8 +935,6 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (!Instantiated)
return 0;
- Instantiated->setAccess(D->getAccess());
-
// Link the instantiated function template declaration to the function
// template from which it was instantiated.
FunctionTemplateDecl *InstTemplate
@@ -954,8 +952,12 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
InstTemplate->setInstantiatedFromMemberTemplate(D);
// Make declarations visible in the appropriate context.
- if (!isFriend)
+ if (!isFriend) {
Owner->addDecl(InstTemplate);
+ } else if (InstTemplate->getDeclContext()->isRecord() &&
+ !D->getPreviousDecl()) {
+ SemaRef.CheckFriendAccess(InstTemplate);
+ }
return InstTemplate;
}
@@ -1526,7 +1528,15 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
if (D->isPure())
SemaRef.CheckPureMethod(Method, SourceRange());
- Method->setAccess(D->getAccess());
+ // Propagate access. For a non-friend declaration, the access is
+ // whatever we're propagating from. For a friend, it should be the
+ // previous declaration we just found.
+ if (isFriend && Method->getPreviousDecl())
+ Method->setAccess(Method->getPreviousDecl()->getAccess());
+ else
+ Method->setAccess(D->getAccess());
+ if (FunctionTemplate)
+ FunctionTemplate->setAccess(Method->getAccess());
SemaRef.CheckOverrideControl(Method);
@@ -1536,18 +1546,28 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
if (D->isDeletedAsWritten())
Method->setDeletedAsWritten();
+ // If there's a function template, let our caller handle it.
if (FunctionTemplate) {
- // If there's a function template, let our caller handle it.
+ // do nothing
+
+ // Don't hide a (potentially) valid declaration with an invalid one.
} else if (Method->isInvalidDecl() && !Previous.empty()) {
- // Don't hide a (potentially) valid declaration with an invalid one.
- } else {
- NamedDecl *DeclToAdd = (TemplateParams
- ? cast<NamedDecl>(FunctionTemplate)
- : Method);
- if (isFriend)
- Record->makeDeclVisibleInContext(DeclToAdd);
- else if (!IsClassScopeSpecialization)
- Owner->addDecl(DeclToAdd);
+ // do nothing
+
+ // Otherwise, check access to friends and make them visible.
+ } else if (isFriend) {
+ // We only need to re-check access for methods which we didn't
+ // manage to match during parsing.
+ if (!D->getPreviousDecl())
+ SemaRef.CheckFriendAccess(Method);
+
+ Record->makeDeclVisibleInContext(Method);
+
+ // Otherwise, add the declaration. We don't need to do this for
+ // class-scope specializations because we'll have matched them with
+ // the appropriate template.
+ } else if (!IsClassScopeSpecialization) {
+ Owner->addDecl(Method);
}
if (D->isExplicitlyDefaulted()) {