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 | 3b4abb67921126aefbf67d15bd6cdb7aa7cf47ff (patch) | |
| tree | fb16eb70f22a9eed18042aa5b6c548a5510c5474 /clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | |
| parent | afb9bc10fabd606d6b34a652886ec7f9a76a6cd9 (diff) | |
| download | bcm5719-llvm-3b4abb67921126aefbf67d15bd6cdb7aa7cf47ff.tar.gz bcm5719-llvm-3b4abb67921126aefbf67d15bd6cdb7aa7cf47ff.zip | |
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.
llvm-svn: 100635
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 55 |
1 files changed, 26 insertions, 29 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3375ccc0ebc..69f183c7062 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/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; |

