diff --git a/clang/include/clang/AST/DeclFriend.h b/clang/include/clang/AST/DeclFriend.h index 5022ad018f4f..99ef738980cc 100644 --- a/clang/include/clang/AST/DeclFriend.h +++ b/clang/include/clang/AST/DeclFriend.h @@ -36,7 +36,7 @@ namespace clang { /// The semantic context of a friend decl is its declaring class. class FriendDecl : public Decl { public: - typedef llvm::PointerUnion FriendUnion; + typedef llvm::PointerUnion FriendUnion; private: // The declaration that's a friend of this class. @@ -73,8 +73,8 @@ public: /// 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(); + TypeSourceInfo *getFriendType() const { + return Friend.dyn_cast(); } /// If this friend declaration doesn't name an unelaborated diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 560ce46ede7c..8d1a4caccb23 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1238,7 +1238,7 @@ public: /// template friend class Foo::Nested; // friend template class FriendTemplateDecl : public Decl { public: - typedef llvm::PointerUnion FriendUnion; + typedef llvm::PointerUnion FriendUnion; private: // The number of template parameters; always non-zero. @@ -1277,8 +1277,8 @@ public: /// 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(); + TypeSourceInfo *getFriendType() const { + return Friend.dyn_cast(); } /// If this friend declaration names a templated function (or diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 62b13d4e95bd..196bc117791f 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -330,8 +330,8 @@ static Sema::AccessResult MatchesFriend(Sema &S, 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(FriendD->getFriendDecl()->getCanonicalDecl()); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 76875c977393..9a68f472e679 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5372,7 +5372,8 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // 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 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // 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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 504b513b2c7c..5a1bec927c4f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3644,7 +3644,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, 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/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index de6fff7bb914..cbd9086dfb27 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -480,13 +480,17 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // 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 {