Preserve type-source information in friend declarations.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99525 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h
index 5022ad0..99ef738 100644
--- a/include/clang/AST/DeclFriend.h
+++ b/include/clang/AST/DeclFriend.h
@@ -36,7 +36,7 @@
 /// The semantic context of a friend decl is its declaring class.
 class FriendDecl : public Decl {
 public:
-  typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
+  typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
 
 private:
   // The declaration that's a friend of this class.
@@ -73,8 +73,8 @@
   /// possibly dependent) type, return the type;  otherwise
   /// return null.  This is used only for C++0x's unelaborated
   /// friend type declarations.
-  Type *getFriendType() const {
-    return Friend.dyn_cast<Type*>();
+  TypeSourceInfo *getFriendType() const {
+    return Friend.dyn_cast<TypeSourceInfo*>();
   }
 
   /// If this friend declaration doesn't name an unelaborated
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 560ce46..8d1a4ca 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -1238,7 +1238,7 @@
 ///   template <typename U> friend class Foo<T>::Nested; // friend template
 class FriendTemplateDecl : public Decl {
 public:
-  typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion;
+  typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
 
 private:
   // The number of template parameters;  always non-zero.
@@ -1277,8 +1277,8 @@
   /// If this friend declaration names a templated type (or
   /// a dependent member type of a templated type), return that
   /// type;  otherwise return null.
-  Type *getFriendType() const {
-    return Friend.dyn_cast<Type*>();
+  TypeSourceInfo *getFriendType() const {
+    return Friend.dyn_cast<TypeSourceInfo*>();
   }
 
   /// If this friend declaration names a templated function (or
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 62b13d4..196bc11 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -330,8 +330,8 @@
 static Sema::AccessResult MatchesFriend(Sema &S,
                                         const EffectiveContext &EC,
                                         FriendDecl *FriendD) {
-  if (Type *T = FriendD->getFriendType())
-    return MatchesFriend(S, EC, T->getCanonicalTypeUnqualified());
+  if (TypeSourceInfo *T = FriendD->getFriendType())
+    return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified());
 
   NamedDecl *Friend
     = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl());
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 76875c9..9a68f47 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5372,7 +5372,8 @@
   // friend templates because ActOnTag never produces a ClassTemplateDecl
   // for a TUK_Friend.
   Declarator TheDeclarator(DS, Declarator::MemberContext);
-  QualType T = GetTypeForDeclarator(TheDeclarator, S);
+  TypeSourceInfo *TSI;
+  QualType T = GetTypeForDeclarator(TheDeclarator, S, &TSI);
   if (TheDeclarator.isInvalidType())
     return DeclPtrTy();
 
@@ -5437,16 +5438,20 @@
   // deadline.  It's also a very silly restriction that seriously
   // affects inner classes and which nobody else seems to implement;
   // thus we never diagnose it, not even in -pedantic.
+  //
+  // But note that we could warn about it: it's always useless to
+  // friend one of your own members (it's not, however, worthless to
+  // friend a member of an arbitrary specialization of your template).
 
   Decl *D;
   if (TempParams.size())
     D = FriendTemplateDecl::Create(Context, CurContext, Loc,
                                    TempParams.size(),
                                  (TemplateParameterList**) TempParams.release(),
-                                   T.getTypePtr(),
+                                   TSI,
                                    DS.getFriendSpecLoc());
   else
-    D = FriendDecl::Create(Context, CurContext, Loc, T.getTypePtr(),
+    D = FriendDecl::Create(Context, CurContext, Loc, TSI,
                            DS.getFriendSpecLoc());
   D->setAccess(AS_public);
   CurContext->addDecl(D);
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 504b513..5a1bec9 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3644,7 +3644,7 @@
   if (TUK == TUK_Friend) {
     FriendDecl *Friend = FriendDecl::Create(Context, CurContext,
                                             TemplateNameLoc,
-                                            WrittenTy->getType().getTypePtr(),
+                                            WrittenTy,
                                             /*FIXME:*/KWLoc);
     Friend->setAccess(AS_public);
     CurContext->addDecl(Friend);
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index de6fff7..cbd9086 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -480,13 +480,17 @@
 
   // Handle friend type expressions by simply substituting template
   // parameters into the pattern type.
-  if (Type *Ty = D->getFriendType()) {
-    QualType T = SemaRef.SubstType(QualType(Ty,0), TemplateArgs,
-                                   D->getLocation(), DeclarationName());
-    if (T.isNull()) return 0;
+  if (TypeSourceInfo *Ty = D->getFriendType()) {
+    TypeSourceInfo *InstTy = 
+      SemaRef.SubstType(Ty, TemplateArgs,
+                        D->getLocation(), DeclarationName());
+    if (!InstTy) return 0;
 
-    assert(getLangOptions().CPlusPlus0x || T->isRecordType());
-    FU = T.getTypePtr();
+    // This assertion is valid because the source type was necessarily
+    // an elaborated-type-specifier with a record tag.
+    assert(getLangOptions().CPlusPlus0x || InstTy->getType()->isRecordType());
+
+    FU = InstTy;
 
   // Handle everything else by appropriate substitution.
   } else {