diff options
author | John McCall <rjmccall@apple.com> | 2009-08-14 02:03:10 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-08-14 02:03:10 +0000 |
commit | fd810b1386ed29b250e7d522ea826a65c815e49d (patch) | |
tree | 303aa97b6aade9df7395a00ca908434d028661a5 /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | 929742338206eec29caa7c20e3c484cc79f18240 (diff) |
Support friend declarations in templates and test that argdep lookup
still works.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78979 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 62 |
1 files changed, 56 insertions, 6 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 86505ee8b0..3212923194 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -44,6 +44,7 @@ namespace { Decl *VisitStaticAssertDecl(StaticAssertDecl *D); Decl *VisitEnumDecl(EnumDecl *D); Decl *VisitEnumConstantDecl(EnumConstantDecl *D); + Decl *VisitFriendClassDecl(FriendClassDecl *D); Decl *VisitFunctionDecl(FunctionDecl *D); Decl *VisitCXXRecordDecl(CXXRecordDecl *D); Decl *VisitCXXMethodDecl(CXXMethodDecl *D); @@ -59,6 +60,10 @@ namespace { return 0; } + const LangOptions &getLangOptions() { + return SemaRef.getLangOptions(); + } + // Helper functions for instantiating methods. QualType InstantiateFunctionType(FunctionDecl *D, llvm::SmallVectorImpl<ParmVarDecl *> &Params); @@ -211,6 +216,25 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { return Field; } +Decl *TemplateDeclInstantiator::VisitFriendClassDecl(FriendClassDecl *D) { + QualType T = D->getFriendType(); + if (T->isDependentType()) { + T = SemaRef.InstantiateType(T, TemplateArgs, D->getLocation(), + DeclarationName()); + assert(T.isNull() || getLangOptions().CPlusPlus0x || T->isRecordType()); + } + + // FIXME: the target context might be dependent. + DeclContext *DC = D->getDeclContext(); + assert(DC->isFileContext()); + + FriendClassDecl *NewD = + FriendClassDecl::Create(SemaRef.Context, DC, D->getLocation(), T, + D->getFriendLoc()); + Owner->addDecl(NewD); + return NewD; +} + Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { Expr *AssertExpr = D->getAssertExpr(); @@ -342,15 +366,30 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { QualType T = InstantiateFunctionType(D, Params); if (T.isNull()) return 0; - + // Build the instantiated method declaration. - FunctionDecl *Function - = FunctionDecl::Create(SemaRef.Context, Owner, D->getLocation(), + FunctionDecl *Function; + if (FriendFunctionDecl* FFD = dyn_cast<FriendFunctionDecl>(D)) { + // The new decl's semantic context. FIXME: this might need + // to be instantiated. + DeclContext *DC = D->getDeclContext(); + + // This assert is bogus and exists only to catch cases we don't + // handle yet. + assert(!DC->isDependentContext()); + + Function = + FriendFunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), + D->getDeclName(), T, D->isInline(), + FFD->getFriendLoc()); + Function->setLexicalDeclContext(Owner); + } else { + Function = + FunctionDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getDeclName(), T, D->getStorageClass(), D->isInline(), D->hasWrittenPrototype(), D->getTypeSpecStartLoc()); - - // FIXME: friend functions + } // Attach the parameters for (unsigned P = 0; P < Params.size(); ++P) @@ -372,7 +411,18 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { FunctionTemplate, &TemplateArgs, InsertPos); - } + } + + // If this was a friend function decl, it's a member which + // needs to be added. + if (isa<FriendFunctionDecl>(Function)) { + // If the new context is still dependent, this declaration + // needs to remain hidden. + if (Owner->isDependentContext()) + Owner->addHiddenDecl(Function); + else + Owner->addDecl(Function); + } return Function; } |