From: Bob Wilson Date: Thu, 25 Mar 2010 04:40:43 +0000 (+0000) Subject: Revert 99477 since it appears to be breaking the clang-x86_64-darwin10-fnt X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e131c574c7baa28eb0759181478d710a2aa60cb6;p=clang Revert 99477 since it appears to be breaking the clang-x86_64-darwin10-fnt buildbot. The tramp3d test fails. --- Reverse-merging r99477 into '.': U test/SemaTemplate/friend-template.cpp U test/CXX/temp/temp.decls/temp.friend/p1.cpp U lib/Sema/SemaTemplateInstantiateDecl.cpp U lib/Sema/SemaAccess.cpp git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99481 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 62b13d4e95..7e2520c9ee 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -240,13 +240,13 @@ static Sema::AccessResult MatchesFriend(Sema &S, ClassTemplateDecl *Friend) { Sema::AccessResult OnFailure = Sema::AR_inaccessible; - // Check whether the friend is the template of a class in the - // context chain. for (llvm::SmallVectorImpl::const_iterator I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { CXXRecordDecl *Record = *I; - // Figure out whether the current class has a template: + // Check whether the friend is the template of a class in the + // context chain. To do that, we need to figure out whether the + // current class has a template: ClassTemplateDecl *CTD; // A specialization of the template... @@ -264,10 +264,6 @@ static Sema::AccessResult MatchesFriend(Sema &S, if (Friend == CTD->getCanonicalDecl()) return Sema::AR_accessible; - // If the context isn't dependent, it can't be a dependent match. - if (!EC.isDependent()) - continue; - // If the template names don't match, it can't be a dependent // match. This isn't true in C++0x because of template aliases. if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName()) diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 93eb1525ff..7b0e88d163 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -500,17 +500,21 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // Hack to make this work almost well pending a rewrite. if (ND->getDeclContext()->isRecord()) { - // FIXME: Hack to avoid crashing when incorrectly trying to instantiate - // templated friend declarations. This doesn't produce a correct AST; - // however this is sufficient for some AST analysis. The real solution - // must be put in place during the pending rewrite. See PR5848. - return 0; + if (!ND->getDeclContext()->isDependentContext()) { + NewND = SemaRef.FindInstantiatedDecl(D->getLocation(), ND, + TemplateArgs); + } else { + // FIXME: Hack to avoid crashing when incorrectly trying to instantiate + // templated friend declarations. This doesn't produce a correct AST; + // however this is sufficient for some AST analysis. The real solution + // must be put in place during the pending rewrite. See PR5848. + return 0; + } } else if (D->wasSpecialization()) { // Totally egregious hack to work around PR5866 return 0; - } else { + } else NewND = Visit(ND); - } if (!NewND) return 0; FU = cast(NewND); @@ -637,8 +641,6 @@ namespace { } Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { - bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None); - // Create a local instantiation scope for this class template, which // will contain the instantiations of the template parameters. Sema::LocalInstantiationScope Scope(SemaRef); @@ -648,95 +650,32 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { return NULL; CXXRecordDecl *Pattern = D->getTemplatedDecl(); - - // Instantiate the qualifier. We have to do this first in case - // we're a friend declaration, because if we are then we need to put - // the new declaration in the appropriate context. - NestedNameSpecifier *Qualifier = Pattern->getQualifier(); - if (Qualifier) { - Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, - Pattern->getQualifierRange(), - TemplateArgs); - if (!Qualifier) return 0; - } - - CXXRecordDecl *PrevDecl = 0; - ClassTemplateDecl *PrevClassTemplate = 0; - - // If this isn't a friend, then it's a member template, in which - // case we just want to build the instantiation in the - // specialization. If it is a friend, we want to build it in - // the appropriate context. - DeclContext *DC = Owner; - if (isFriend) { - if (Qualifier) { - CXXScopeSpec SS; - SS.setScopeRep(Qualifier); - SS.setRange(Pattern->getQualifierRange()); - DC = SemaRef.computeDeclContext(SS); - if (!DC) return 0; - } else { - DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(), - Pattern->getDeclContext(), - TemplateArgs); - } - - // Look for a previous declaration of the template in the owning - // context. - LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(), - Sema::LookupOrdinaryName, Sema::ForRedeclaration); - SemaRef.LookupQualifiedName(R, DC); - - if (R.isSingleResult()) { - PrevClassTemplate = R.getAsSingle(); - if (PrevClassTemplate) - PrevDecl = PrevClassTemplate->getTemplatedDecl(); - } - - if (!PrevClassTemplate && Qualifier) { - SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) - << Pattern->getDeclName() << Pattern->getQualifierRange(); - return 0; - } - - if (PrevClassTemplate && - !SemaRef.TemplateParameterListsAreEqual(InstParams, - PrevClassTemplate->getTemplateParameters(), - /*Complain=*/true, - Sema::TPL_TemplateMatch)) - return 0; - } - CXXRecordDecl *RecordInst - = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC, + = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), Owner, Pattern->getLocation(), Pattern->getIdentifier(), - Pattern->getTagKeywordLoc(), PrevDecl, + Pattern->getTagKeywordLoc(), /*PrevDecl=*/ NULL, /*DelayTypeCreation=*/true); - if (Qualifier) - RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange()); + // Substitute the nested name specifier, if any. + if (SubstQualifier(Pattern, RecordInst)) + return 0; ClassTemplateDecl *Inst - = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), - D->getIdentifier(), InstParams, RecordInst, - PrevClassTemplate); + = ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier(), InstParams, RecordInst, 0); RecordInst->setDescribedClassTemplate(Inst); - if (isFriend) { - Inst->setObjectOfFriendDecl(PrevClassTemplate != 0); - // TODO: do we want to track the instantiation progeny of this - // friend target decl? - } else { + if (D->getFriendObjectKind()) + Inst->setObjectOfFriendDecl(true); + else Inst->setAccess(D->getAccess()); - Inst->setInstantiatedFromMemberTemplate(D); - } + Inst->setInstantiatedFromMemberTemplate(D); // Trigger creation of the type for the instantiation. SemaRef.Context.getInjectedClassNameType(RecordInst, Inst->getInjectedClassNameSpecialization(SemaRef.Context)); // Finish handling of friends. - if (isFriend) { - DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false); + if (Inst->getFriendObjectKind()) { return Inst; } diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp index 1bf16de8f8..277106c2bd 100644 --- a/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -114,21 +114,7 @@ namespace test3 { template class User; template class User; // expected-note {{requested here}} -} - -namespace test4 { - template class A { - template friend class B; - bool foo(const A *) const; - }; - - template class B { - bool bar(const A *a, const A *b) { - return a->foo(b); - } - }; - template class B; } namespace Dependent { diff --git a/test/SemaTemplate/friend-template.cpp b/test/SemaTemplate/friend-template.cpp index 6ee30aa777..8bc2631e11 100644 --- a/test/SemaTemplate/friend-template.cpp +++ b/test/SemaTemplate/friend-template.cpp @@ -74,16 +74,12 @@ namespace test3 { template class X3 { template friend struct X2a; - - // FIXME: the redeclaration note ends up here because redeclaration - // lookup ends up finding the friend target from X3. - template friend struct X2b; // expected-error {{template non-type parameter has a different type 'long' in template redeclaration}} \ - // expected-note {{previous non-type template parameter with type 'int' is here}} + template friend struct X2b; }; X3 x3i; // okay - X3 x3l; // expected-note {{in instantiation}} + X3 x3l; // FIXME: should cause an instantiation-time failure } // PR5716