[cfe-commits] r99481 - in /cfe/trunk: lib/Sema/SemaAccess.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.decls/temp.friend/p1.cpp test/SemaTemplate/friend-template.cpp
Bob Wilson
bob.wilson at apple.com
Wed Mar 24 21:40:43 PDT 2010
Author: bwilson
Date: Wed Mar 24 23:40:43 2010
New Revision: 99481
URL: http://llvm.org/viewvc/llvm-project?rev=99481&view=rev
Log:
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
Modified:
cfe/trunk/lib/Sema/SemaAccess.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp
cfe/trunk/test/SemaTemplate/friend-template.cpp
Modified: cfe/trunk/lib/Sema/SemaAccess.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAccess.cpp?rev=99481&r1=99480&r2=99481&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAccess.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAccess.cpp Wed Mar 24 23:40:43 2010
@@ -240,13 +240,13 @@
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<CXXRecordDecl*>::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 @@
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())
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=99481&r1=99480&r2=99481&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Mar 24 23:40:43 2010
@@ -500,17 +500,21 @@
// 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<NamedDecl>(NewND);
@@ -637,8 +641,6 @@
}
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 @@
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<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::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;
}
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp?rev=99481&r1=99480&r2=99481&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp Wed Mar 24 23:40:43 2010
@@ -114,21 +114,7 @@
template class User<bool>;
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 {
Modified: cfe/trunk/test/SemaTemplate/friend-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/friend-template.cpp?rev=99481&r1=99480&r2=99481&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/friend-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/friend-template.cpp Wed Mar 24 23:40:43 2010
@@ -74,16 +74,12 @@
template<typename T>
class X3 {
template<typename U, U Value> friend struct X2a;
-
- // 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}}
+ template<typename U, T Value> friend struct X2b;
};
X3<int> x3i; // okay
- X3<long> x3l; // expected-note {{in instantiation}}
+ X3<long> x3l; // FIXME: should cause an instantiation-time failure
}
// PR5716
More information about the cfe-commits
mailing list