]> granicus.if.org Git - clang/commitdiff
Revert 99477 since it appears to be breaking the clang-x86_64-darwin10-fnt
authorBob Wilson <bob.wilson@apple.com>
Thu, 25 Mar 2010 04:40:43 +0000 (04:40 +0000)
committerBob Wilson <bob.wilson@apple.com>
Thu, 25 Mar 2010 04:40:43 +0000 (04:40 +0000)
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

lib/Sema/SemaAccess.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/CXX/temp/temp.decls/temp.friend/p1.cpp
test/SemaTemplate/friend-template.cpp

index 62b13d4e95bddc4d5eaadbc44bba064235691f9f..7e2520c9eeeb152538186d8513a5d4b613f8dafe 100644 (file)
@@ -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<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 @@ 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())
index 93eb1525ff0038b5d537fddd096efe5ea77465c9..7b0e88d16347fcb93c93e7e37dc3566d075c1f42 100644 (file)
@@ -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<NamedDecl>(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<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;
   }
   
index 1bf16de8f8a8d1c6237002a759cddb1f4567b31a..277106c2bd945bb6fe19384e1797216cdfb70ea7 100644 (file)
@@ -114,21 +114,7 @@ namespace test3 {
 
   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 {
index 6ee30aa7775a5733e5b5216667dd7ac93b689014..8bc2631e119f31d217ef55a8a470278e6a69f34b 100644 (file)
@@ -74,16 +74,12 @@ namespace test3 {
   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