diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-18 17:37:40 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-18 17:37:40 +0000 |
commit | b74b1038bb5b62f18f9171d74ff915ec703d0749 (patch) | |
tree | 4b5b3b972f56a05d9ca483cf772053eaeb0bba82 | |
parent | d3db453d151b686822cff972d77e4cb947d3a9fe (diff) | |
download | bcm5719-llvm-b74b1038bb5b62f18f9171d74ff915ec703d0749.tar.gz bcm5719-llvm-b74b1038bb5b62f18f9171d74ff915ec703d0749.zip |
C++ [namespace.memdef]p3 only applies when the friend is not named via
a qualified name. We weren't checking for an empty
nested-name-specifier when dealing with friend class templates
(although we were checking in the other places where we deal with this
paragraph). Fixes a Boost.Serialization showstopper.
llvm-svn: 101724
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 32 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp | 12 |
2 files changed, 29 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index fbe331b6b26..a239a41e4ef 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -801,22 +801,24 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // declared as a friend, and when the name of the friend class or // function is neither a qualified name nor a template-id, scopes outside // the innermost enclosing namespace scope are not considered. - DeclContext *OutermostContext = CurContext; - while (!OutermostContext->isFileContext()) - OutermostContext = OutermostContext->getLookupParent(); - - if (PrevDecl && - (OutermostContext->Equals(PrevDecl->getDeclContext()) || - OutermostContext->Encloses(PrevDecl->getDeclContext()))) { - SemanticContext = PrevDecl->getDeclContext(); - } else { - // Declarations in outer scopes don't matter. However, the outermost - // context we computed is the semantic context for our new - // declaration. - PrevDecl = PrevClassTemplate = 0; - SemanticContext = OutermostContext; + if (!SS.isSet()) { + DeclContext *OutermostContext = CurContext; + while (!OutermostContext->isFileContext()) + OutermostContext = OutermostContext->getLookupParent(); + + if (PrevDecl && + (OutermostContext->Equals(PrevDecl->getDeclContext()) || + OutermostContext->Encloses(PrevDecl->getDeclContext()))) { + SemanticContext = PrevDecl->getDeclContext(); + } else { + // Declarations in outer scopes don't matter. However, the outermost + // context we computed is the semantic context for our new + // declaration. + PrevDecl = PrevClassTemplate = 0; + SemanticContext = OutermostContext; + } } - + if (CurContext->isDependentContext()) { // If this is a dependent context, we don't want to link the friend // class template to the template in scope, because that would perform diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp index a5f314dac23..ddcbe785a73 100644 --- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp @@ -53,4 +53,16 @@ struct Y { friend union X1; }; +namespace N { + namespace M { + template<typename T> class X; + } +} + +namespace N3 { + class Y { + template<typename T> friend class N::M::X; + }; +} + // FIXME: Woefully inadequate for testing |