diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-07 17:57:12 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-07 17:57:12 +0000 |
commit | 06245bfb3ae40bb24a8bfb17eafeb266a4daf5ca (patch) | |
tree | b54ded0e960a2b8df3e3c66a2b2dfabdddb2baa8 /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | 1d8693580133d6c783b9a56808e61f98005e0be1 (diff) |
Improve handling of friend types in several ways:
- When instantiating a friend type template, perform semantic
analysis on the resulting type.
- Downgrade the errors concerning friend type declarations that do
not refer to classes to ExtWarns in C++98/03. C++0x allows
practically any type to be befriended, and ignores the friend
declaration if the type is not a class.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100635 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 55 |
1 files changed, 26 insertions, 29 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3375ccc0eb..69f183c706 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -476,47 +476,44 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { } Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { - FriendDecl::FriendUnion FU; - // Handle friend type expressions by simply substituting template - // parameters into the pattern type. + // parameters into the pattern type and checking the result. if (TypeSourceInfo *Ty = D->getFriendType()) { TypeSourceInfo *InstTy = SemaRef.SubstType(Ty, TemplateArgs, D->getLocation(), DeclarationName()); - if (!InstTy) return 0; + if (!InstTy) + return 0; - // This assertion is valid because the source type was necessarily - // an elaborated-type-specifier with a record tag. - assert(getLangOptions().CPlusPlus0x || InstTy->getType()->isRecordType()); + FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy); + if (!FD) + return 0; + + FD->setAccess(AS_public); + Owner->addDecl(FD); + return FD; + } + + NamedDecl *ND = D->getFriendDecl(); + assert(ND && "friend decl must be a decl or a type!"); - FU = InstTy; + // FIXME: We have a problem here, because the nested call to Visit(ND) + // will inject the thing that the friend references into the current + // owner, which is wrong. + Decl *NewND; - // Handle everything else by appropriate substitution. + // Hack to make this work almost well pending a rewrite. + if (D->wasSpecialization()) { + // Totally egregious hack to work around PR5866 + return 0; } else { - NamedDecl *ND = D->getFriendDecl(); - assert(ND && "friend decl must be a decl or a type!"); - - // FIXME: We have a problem here, because the nested call to Visit(ND) - // will inject the thing that the friend references into the current - // owner, which is wrong. - Decl *NewND; - - // Hack to make this work almost well pending a rewrite. - if (D->wasSpecialization()) { - // Totally egregious hack to work around PR5866 - return 0; - } else { - NewND = Visit(ND); - } - if (!NewND) return 0; - - FU = cast<NamedDecl>(NewND); + NewND = Visit(ND); } + if (!NewND) return 0; FriendDecl *FD = - FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), FU, - D->getFriendLoc()); + FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), + cast<NamedDecl>(NewND), D->getFriendLoc()); FD->setAccess(AS_public); Owner->addDecl(FD); return FD; |