Skip to content

Commit 197e5f7

Browse files
committed
Improve argument-dependent lookup to find associated classes and
namespaces based on the template arguments of a class template specialization type. llvm-svn: 74993
1 parent 16019aa commit 197e5f7

File tree

4 files changed

+119
-4
lines changed

4 files changed

+119
-4
lines changed

clang/lib/Sema/SemaLookup.cpp

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,74 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
12411241
return true;
12421242
}
12431243

1244+
static void
1245+
addAssociatedClassesAndNamespaces(QualType T,
1246+
ASTContext &Context,
1247+
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
1248+
Sema::AssociatedClassSet &AssociatedClasses,
1249+
bool &GlobalScope);
1250+
1251+
// \brief Add the associated classes and namespaces for argument-dependent
1252+
// lookup that involves a template argument (C++ [basic.lookup.koenig]p2).
1253+
static void
1254+
addAssociatedClassesAndNamespaces(const TemplateArgument &Arg,
1255+
ASTContext &Context,
1256+
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
1257+
Sema::AssociatedClassSet &AssociatedClasses,
1258+
bool &GlobalScope) {
1259+
// C++ [basic.lookup.koenig]p2, last bullet:
1260+
// -- [...] ;
1261+
switch (Arg.getKind()) {
1262+
case TemplateArgument::Null:
1263+
break;
1264+
1265+
case TemplateArgument::Type:
1266+
// [...] the namespaces and classes associated with the types of the
1267+
// template arguments provided for template type parameters (excluding
1268+
// template template parameters)
1269+
addAssociatedClassesAndNamespaces(Arg.getAsType(), Context,
1270+
AssociatedNamespaces,
1271+
AssociatedClasses,
1272+
GlobalScope);
1273+
break;
1274+
1275+
case TemplateArgument::Declaration:
1276+
// [...] the namespaces in which any template template arguments are
1277+
// defined; and the classes in which any member templates used as
1278+
// template template arguments are defined.
1279+
if (ClassTemplateDecl *ClassTemplate
1280+
= dyn_cast<ClassTemplateDecl>(Arg.getAsDecl())) {
1281+
DeclContext *Ctx = ClassTemplate->getDeclContext();
1282+
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
1283+
AssociatedClasses.insert(EnclosingClass);
1284+
// Add the associated namespace for this class.
1285+
while (Ctx->isRecord())
1286+
Ctx = Ctx->getParent();
1287+
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
1288+
AssociatedNamespaces.insert(EnclosingNamespace);
1289+
else if (Ctx->isTranslationUnit())
1290+
GlobalScope = true;
1291+
}
1292+
break;
1293+
1294+
case TemplateArgument::Integral:
1295+
case TemplateArgument::Expression:
1296+
// [Note: non-type template arguments do not contribute to the set of
1297+
// associated namespaces. ]
1298+
break;
1299+
1300+
case TemplateArgument::Pack:
1301+
for (TemplateArgument::pack_iterator P = Arg.pack_begin(),
1302+
PEnd = Arg.pack_end();
1303+
P != PEnd; ++P)
1304+
addAssociatedClassesAndNamespaces(*P, Context,
1305+
AssociatedNamespaces,
1306+
AssociatedClasses,
1307+
GlobalScope);
1308+
break;
1309+
}
1310+
}
1311+
12441312
// \brief Add the associated classes and namespaces for
12451313
// argument-dependent lookup with an argument of class type
12461314
// (C++ [basic.lookup.koenig]p2).
@@ -1275,8 +1343,36 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
12751343
if (!AssociatedClasses.insert(Class))
12761344
return;
12771345

1278-
// FIXME: Handle class template specializations
1279-
1346+
// -- If T is a template-id, its associated namespaces and classes are
1347+
// the namespace in which the template is defined; for member
1348+
// templates, the member template’s class; the namespaces and classes
1349+
// associated with the types of the template arguments provided for
1350+
// template type parameters (excluding template template parameters); the
1351+
// namespaces in which any template template arguments are defined; and
1352+
// the classes in which any member templates used as template template
1353+
// arguments are defined. [Note: non-type template arguments do not
1354+
// contribute to the set of associated namespaces. ]
1355+
if (ClassTemplateSpecializationDecl *Spec
1356+
= dyn_cast<ClassTemplateSpecializationDecl>(Class)) {
1357+
DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext();
1358+
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
1359+
AssociatedClasses.insert(EnclosingClass);
1360+
// Add the associated namespace for this class.
1361+
while (Ctx->isRecord())
1362+
Ctx = Ctx->getParent();
1363+
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
1364+
AssociatedNamespaces.insert(EnclosingNamespace);
1365+
else if (Ctx->isTranslationUnit())
1366+
GlobalScope = true;
1367+
1368+
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
1369+
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
1370+
addAssociatedClassesAndNamespaces(TemplateArgs[I], Context,
1371+
AssociatedNamespaces,
1372+
AssociatedClasses,
1373+
GlobalScope);
1374+
}
1375+
12801376
// Add direct and indirect base classes along with their associated
12811377
// namespaces.
12821378
llvm::SmallVector<CXXRecordDecl *, 32> Bases;
@@ -1297,7 +1393,8 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
12971393
DeclContext *BaseCtx = BaseDecl->getDeclContext();
12981394
while (BaseCtx->isRecord())
12991395
BaseCtx = BaseCtx->getParent();
1300-
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(BaseCtx))
1396+
if (NamespaceDecl *EnclosingNamespace
1397+
= dyn_cast<NamespaceDecl>(BaseCtx))
13011398
AssociatedNamespaces.insert(EnclosingNamespace);
13021399
else if (BaseCtx->isTranslationUnit())
13031400
GlobalScope = true;
@@ -1490,6 +1587,8 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
14901587
if (!DRE)
14911588
continue;
14921589

1590+
// FIXME: The declaration might be a FunctionTemplateDecl (by itself)
1591+
// or might be buried in a TemplateIdRefExpr.
14931592
OverloadedFunctionDecl *Ovl
14941593
= dyn_cast<OverloadedFunctionDecl>(DRE->getDecl());
14951594
if (!Ovl)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: clang-cc -fsyntax-only -verify %s
2+
3+
namespace N1 {
4+
struct X { };
5+
int& f(void*);
6+
}
7+
8+
namespace N2 {
9+
template<typename T> struct Y { };
10+
}
11+
12+
namespace N3 {
13+
void test() {
14+
int &ir = f((N2::Y<N1::X>*)0);
15+
}
16+
}

clang/www/cxx_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ <h1>C++ Support in Clang</h1>
353353
<td class="advanced" align="center"></td>
354354
<td class="advanced" align="center"></td>
355355
<td class="na">N/A</td>
356-
<td>Missing support for templates, friend functions.</td>
356+
<td>Missing support for friend functions.</td>
357357
</tr>
358358
<tr>
359359
<td>&nbsp;&nbsp;&nbsp;&nbsp;3.4.3 [basic.lookup.qual]</td>

0 commit comments

Comments
 (0)