diff options
author | John McCall <rjmccall@apple.com> | 2012-08-10 03:15:35 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2012-08-10 03:15:35 +0000 |
commit | 1f2e1a96bec2ba6418ae7f2d2b525a3575203b6a (patch) | |
tree | 4186ca57ea4f54df5ac62a3528a8ab089fe75f65 /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | 7c304f56eecbd03db7d222a05dfcd593750d50d3 (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.cpp | 48 |
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()) { |