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

llvm-svn: 99481
This commit is contained in:
Bob Wilson 2010-03-25 04:40:43 +00:00
parent 4d745dd5cb
commit 63d45e51fb
4 changed files with 28 additions and 111 deletions

View File

@ -240,13 +240,13 @@ static Sema::AccessResult MatchesFriend(Sema &S,
ClassTemplateDecl *Friend) { ClassTemplateDecl *Friend) {
Sema::AccessResult OnFailure = Sema::AR_inaccessible; Sema::AccessResult OnFailure = Sema::AR_inaccessible;
// Check whether the friend is the template of a class in the
// context chain.
for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator
I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {
CXXRecordDecl *Record = *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; ClassTemplateDecl *CTD;
// A specialization of the template... // A specialization of the template...
@ -264,10 +264,6 @@ static Sema::AccessResult MatchesFriend(Sema &S,
if (Friend == CTD->getCanonicalDecl()) if (Friend == CTD->getCanonicalDecl())
return Sema::AR_accessible; 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 // 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. // match. This isn't true in C++0x because of template aliases.
if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName()) if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())

View File

@ -500,17 +500,21 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
// Hack to make this work almost well pending a rewrite. // Hack to make this work almost well pending a rewrite.
if (ND->getDeclContext()->isRecord()) { if (ND->getDeclContext()->isRecord()) {
// FIXME: Hack to avoid crashing when incorrectly trying to instantiate if (!ND->getDeclContext()->isDependentContext()) {
// templated friend declarations. This doesn't produce a correct AST; NewND = SemaRef.FindInstantiatedDecl(D->getLocation(), ND,
// however this is sufficient for some AST analysis. The real solution TemplateArgs);
// must be put in place during the pending rewrite. See PR5848. } else {
return 0; // 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()) { } else if (D->wasSpecialization()) {
// Totally egregious hack to work around PR5866 // Totally egregious hack to work around PR5866
return 0; return 0;
} else { } else
NewND = Visit(ND); NewND = Visit(ND);
}
if (!NewND) return 0; if (!NewND) return 0;
FU = cast<NamedDecl>(NewND); FU = cast<NamedDecl>(NewND);
@ -637,8 +641,6 @@ namespace {
} }
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
// Create a local instantiation scope for this class template, which // Create a local instantiation scope for this class template, which
// will contain the instantiations of the template parameters. // will contain the instantiations of the template parameters.
Sema::LocalInstantiationScope Scope(SemaRef); Sema::LocalInstantiationScope Scope(SemaRef);
@ -648,95 +650,32 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
return NULL; return NULL;
CXXRecordDecl *Pattern = D->getTemplatedDecl(); 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<ClassTemplateDecl>();
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 *RecordInst
= CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC, = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), Owner,
Pattern->getLocation(), Pattern->getIdentifier(), Pattern->getLocation(), Pattern->getIdentifier(),
Pattern->getTagKeywordLoc(), PrevDecl, Pattern->getTagKeywordLoc(), /*PrevDecl=*/ NULL,
/*DelayTypeCreation=*/true); /*DelayTypeCreation=*/true);
if (Qualifier) // Substitute the nested name specifier, if any.
RecordInst->setQualifierInfo(Qualifier, Pattern->getQualifierRange()); if (SubstQualifier(Pattern, RecordInst))
return 0;
ClassTemplateDecl *Inst ClassTemplateDecl *Inst
= ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), = ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),
D->getIdentifier(), InstParams, RecordInst, D->getIdentifier(), InstParams, RecordInst, 0);
PrevClassTemplate);
RecordInst->setDescribedClassTemplate(Inst); RecordInst->setDescribedClassTemplate(Inst);
if (isFriend) { if (D->getFriendObjectKind())
Inst->setObjectOfFriendDecl(PrevClassTemplate != 0); Inst->setObjectOfFriendDecl(true);
// TODO: do we want to track the instantiation progeny of this else
// friend target decl?
} else {
Inst->setAccess(D->getAccess()); Inst->setAccess(D->getAccess());
Inst->setInstantiatedFromMemberTemplate(D); Inst->setInstantiatedFromMemberTemplate(D);
}
// Trigger creation of the type for the instantiation. // Trigger creation of the type for the instantiation.
SemaRef.Context.getInjectedClassNameType(RecordInst, SemaRef.Context.getInjectedClassNameType(RecordInst,
Inst->getInjectedClassNameSpecialization(SemaRef.Context)); Inst->getInjectedClassNameSpecialization(SemaRef.Context));
// Finish handling of friends. // Finish handling of friends.
if (isFriend) { if (Inst->getFriendObjectKind()) {
DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false);
return Inst; return Inst;
} }

View File

@ -114,21 +114,7 @@ namespace test3 {
template class User<bool>; template class User<bool>;
template class User<int>; // expected-note {{requested here}} template class User<int>; // expected-note {{requested here}}
}
namespace test4 {
template <class T> class A {
template <class T0> friend class B;
bool foo(const A<T> *) const;
};
template <class T> class B {
bool bar(const A<T> *a, const A<T> *b) {
return a->foo(b);
}
};
template class B<int>;
} }
namespace Dependent { namespace Dependent {

View File

@ -74,16 +74,12 @@ namespace test3 {
template<typename T> template<typename T>
class X3 { class X3 {
template<typename U, U Value> friend struct X2a; template<typename U, U Value> friend struct X2a;
template<typename U, T Value> friend struct X2b;
// FIXME: the redeclaration note ends up here because redeclaration
// lookup ends up finding the friend target from X3<int>.
template<typename U, T Value> 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}}
}; };
X3<int> x3i; // okay X3<int> x3i; // okay
X3<long> x3l; // expected-note {{in instantiation}} X3<long> x3l; // FIXME: should cause an instantiation-time failure
} }
// PR5716 // PR5716