diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 46 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 |
2 files changed, 30 insertions, 24 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ac1b1ec0ee..c1d828fe45 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -691,6 +691,26 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Previous.begin() != Previous.end()) PrevDecl = *Previous.begin(); + // If there is a previous declaration with the same name, check + // whether this is a valid redeclaration. + ClassTemplateDecl *PrevClassTemplate + = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl); + + // We may have found the injected-class-name of a class template, + // class template partial specialization, or class template specialization. + // In these cases, grab the template that is being defined or specialized. + if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) && + cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) { + PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext()); + PrevClassTemplate + = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate(); + if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) { + PrevClassTemplate + = cast<ClassTemplateSpecializationDecl>(PrevDecl) + ->getSpecializedTemplate(); + } + } + if (PrevDecl && TUK == TUK_Friend) { // C++ [namespace.memdef]p3: // [...] When looking for a prior declaration of a class or a function @@ -708,7 +728,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // Declarations in outer scopes don't matter. However, the outermost // context we computed is the semantic context for our new // declaration. - PrevDecl = 0; + PrevDecl = PrevClassTemplate = 0; SemanticContext = OutermostContext; } @@ -717,30 +737,10 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // class template to the template in scope, because that would perform // checking of the template parameter lists that can't be performed // until the outer context is instantiated. - PrevDecl = 0; + PrevDecl = PrevClassTemplate = 0; } } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S)) - PrevDecl = 0; - - // If there is a previous declaration with the same name, check - // whether this is a valid redeclaration. - ClassTemplateDecl *PrevClassTemplate - = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl); - - // We may have found the injected-class-name of a class template, - // class template partial specialization, or class template specialization. - // In these cases, grab the template that is being defined or specialized. - if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) && - cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) { - PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext()); - PrevClassTemplate - = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate(); - if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) { - PrevClassTemplate - = cast<ClassTemplateSpecializationDecl>(PrevDecl) - ->getSpecializedTemplate(); - } - } + PrevDecl = PrevClassTemplate = 0; if (PrevClassTemplate) { // Ensure that the template parameter lists are compatible. diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 69982be84b..2ca4810055 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -396,7 +396,13 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // FIXME: We have a problem here, because the nested call to Visit(ND) // will inject the thing that the friend references into the current // owner, which is wrong. - Decl *NewND = Visit(ND); + Decl *NewND; + + // Hack to make this work almost well pending a rewrite. + if (ND->getDeclContext()->isRecord()) + NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs); + else + NewND = Visit(ND); if (!NewND) return 0; FU = cast<NamedDecl>(NewND); |