diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-07-08 07:51:57 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-07-08 07:51:57 +0000 |
commit | 69be8d60ded8bbfbd30facf0590c97920a074f46 (patch) | |
tree | 711ac237226760947be9371cdfcd8281ea335162 | |
parent | bbb3128b449b6c5e7822e8b781445e348a9117dc (diff) |
Improve argument-dependent lookup to find associated classes and
namespaces based on the template arguments of a class template
specialization type.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74993 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 105 | ||||
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp | 16 | ||||
-rw-r--r-- | test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp (renamed from test/SemaCXX/basic_lookup_argdep.cpp) | 0 | ||||
-rw-r--r-- | www/cxx_status.html | 2 |
4 files changed, 119 insertions, 4 deletions
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 6f2fc5e0c4..343cbae673 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1241,6 +1241,74 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name, return true; } +static void +addAssociatedClassesAndNamespaces(QualType T, + ASTContext &Context, + Sema::AssociatedNamespaceSet &AssociatedNamespaces, + Sema::AssociatedClassSet &AssociatedClasses, + bool &GlobalScope); + +// \brief Add the associated classes and namespaces for argument-dependent +// lookup that involves a template argument (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, + ASTContext &Context, + Sema::AssociatedNamespaceSet &AssociatedNamespaces, + Sema::AssociatedClassSet &AssociatedClasses, + bool &GlobalScope) { + // C++ [basic.lookup.koenig]p2, last bullet: + // -- [...] ; + switch (Arg.getKind()) { + case TemplateArgument::Null: + break; + + case TemplateArgument::Type: + // [...] the namespaces and classes associated with the types of the + // template arguments provided for template type parameters (excluding + // template template parameters) + addAssociatedClassesAndNamespaces(Arg.getAsType(), Context, + AssociatedNamespaces, + AssociatedClasses, + GlobalScope); + break; + + case TemplateArgument::Declaration: + // [...] the namespaces in which any template template arguments are + // defined; and the classes in which any member templates used as + // template template arguments are defined. + if (ClassTemplateDecl *ClassTemplate + = dyn_cast<ClassTemplateDecl>(Arg.getAsDecl())) { + DeclContext *Ctx = ClassTemplate->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + AssociatedClasses.insert(EnclosingClass); + // Add the associated namespace for this class. + while (Ctx->isRecord()) + Ctx = Ctx->getParent(); + if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx)) + AssociatedNamespaces.insert(EnclosingNamespace); + else if (Ctx->isTranslationUnit()) + GlobalScope = true; + } + break; + + case TemplateArgument::Integral: + case TemplateArgument::Expression: + // [Note: non-type template arguments do not contribute to the set of + // associated namespaces. ] + break; + + case TemplateArgument::Pack: + for (TemplateArgument::pack_iterator P = Arg.pack_begin(), + PEnd = Arg.pack_end(); + P != PEnd; ++P) + addAssociatedClassesAndNamespaces(*P, Context, + AssociatedNamespaces, + AssociatedClasses, + GlobalScope); + break; + } +} + // \brief Add the associated classes and namespaces for // argument-dependent lookup with an argument of class type // (C++ [basic.lookup.koenig]p2). @@ -1275,8 +1343,36 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, if (!AssociatedClasses.insert(Class)) return; - // FIXME: Handle class template specializations - + // -- If T is a template-id, its associated namespaces and classes are + // the namespace in which the template is defined; for member + // templates, the member template’s class; the namespaces and classes + // associated with the types of the template arguments provided for + // template type parameters (excluding template template parameters); the + // namespaces in which any template template arguments are defined; and + // the classes in which any member templates used as template template + // arguments are defined. [Note: non-type template arguments do not + // contribute to the set of associated namespaces. ] + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Class)) { + DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + AssociatedClasses.insert(EnclosingClass); + // Add the associated namespace for this class. + while (Ctx->isRecord()) + Ctx = Ctx->getParent(); + if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx)) + AssociatedNamespaces.insert(EnclosingNamespace); + else if (Ctx->isTranslationUnit()) + GlobalScope = true; + + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + addAssociatedClassesAndNamespaces(TemplateArgs[I], Context, + AssociatedNamespaces, + AssociatedClasses, + GlobalScope); + } + // Add direct and indirect base classes along with their associated // namespaces. llvm::SmallVector<CXXRecordDecl *, 32> Bases; @@ -1297,7 +1393,8 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, DeclContext *BaseCtx = BaseDecl->getDeclContext(); while (BaseCtx->isRecord()) BaseCtx = BaseCtx->getParent(); - if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(BaseCtx)) + if (NamespaceDecl *EnclosingNamespace + = dyn_cast<NamespaceDecl>(BaseCtx)) AssociatedNamespaces.insert(EnclosingNamespace); else if (BaseCtx->isTranslationUnit()) GlobalScope = true; @@ -1490,6 +1587,8 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, if (!DRE) continue; + // FIXME: The declaration might be a FunctionTemplateDecl (by itself) + // or might be buried in a TemplateIdRefExpr. OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(DRE->getDecl()); if (!Ovl) diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp new file mode 100644 index 0000000000..525afd89ec --- /dev/null +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N1 { + struct X { }; + int& f(void*); +} + +namespace N2 { + template<typename T> struct Y { }; +} + +namespace N3 { + void test() { + int &ir = f((N2::Y<N1::X>*)0); + } +} diff --git a/test/SemaCXX/basic_lookup_argdep.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp index 677df8284a..677df8284a 100644 --- a/test/SemaCXX/basic_lookup_argdep.cpp +++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp diff --git a/www/cxx_status.html b/www/cxx_status.html index 389427e0aa..9156370286 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -353,7 +353,7 @@ welcome!</p> <td class="advanced" align="center"></td> <td class="advanced" align="center"></td> <td class="na">N/A</td> - <td>Missing support for templates, friend functions.</td> + <td>Missing support for friend functions.</td> </tr> <tr> <td> 3.4.3 [basic.lookup.qual]</td> |