From ea0a0a9b3f9a8cd518fb698e2a70a78dbfdffe33 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 11 Jan 2010 18:40:55 +0000 Subject: Implement name lookup for conversion function template specializations (C++ [temp.mem]p5-6), which involves template argument deduction based on the type named, e.g., given struct X { template operator T*(); } x; when we call x.operator int*(); we perform template argument deduction to determine that T=int. This template argument deduction is needed for template specialization and explicit instantiation, e.g., template<> X::operator float*() { /* ... */ } and when calling or otherwise naming a conversion function (as in the first example). This fixes PR5742 and PR5762, although there's some remaining ugliness that's causing out-of-line definitions of conversion function templates to fail. I'll look into that separately. llvm-svn: 93162 --- clang/lib/Sema/SemaLookup.cpp | 77 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) (limited to 'clang/lib/Sema/SemaLookup.cpp') diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 897ce200758..a8c2366c59b 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -444,10 +444,81 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) { bool Found = false; DeclContext::lookup_const_iterator I, E; - for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) - if (R.isAcceptableDecl(*I)) - R.addDecl(*I), Found = true; + for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) { + if (R.isAcceptableDecl(*I)) { + R.addDecl(*I); + Found = true; + } + } + if (R.getLookupName().getNameKind() + == DeclarationName::CXXConversionFunctionName && + !R.getLookupName().getCXXNameType()->isDependentType() && + isa(DC)) { + // C++ [temp.mem]p6: + // A specialization of a conversion function template is not found by + // name lookup. Instead, any conversion function templates visible in the + // context of the use are considered. [...] + const CXXRecordDecl *Record = cast(DC); + + const UnresolvedSet *Unresolved = Record->getConversionFunctions(); + for (UnresolvedSet::iterator U = Unresolved->begin(), + UEnd = Unresolved->end(); + U != UEnd; ++U) { + FunctionTemplateDecl *ConvTemplate = dyn_cast(*U); + if (!ConvTemplate) + continue; + + // When we're performing lookup for the purposes of redeclaration, just + // add the conversion function template. When we deduce template + // arguments for specializations, we'll end up unifying the return + // type of the new declaration with the type of the function template. + if (R.isForRedeclaration()) { + R.addDecl(ConvTemplate); + Found = true; + continue; + } + + // C++ [temp.mem]p6: + // [...] For each such operator, if argument deduction succeeds + // (14.9.2.3), the resulting specialization is used as if found by + // name lookup. + // + // When referencing a conversion function for any purpose other than + // a redeclaration (such that we'll be building an expression with the + // result), perform template argument deduction and place the + // specialization into the result set. We do this to avoid forcing all + // callers to perform special deduction for conversion functions. + Sema::TemplateDeductionInfo Info(R.getSema().Context); + FunctionDecl *Specialization = 0; + + const FunctionProtoType *ConvProto + = ConvTemplate->getTemplatedDecl()->getType() + ->getAs(); + assert(ConvProto && "Nonsensical conversion function template type"); + + // Compute the type of the function that we would expect the conversion + // function to have, if it were to match the name given. + // FIXME: Calling convention! + QualType ExpectedType + = R.getSema().Context.getFunctionType( + R.getLookupName().getCXXNameType(), + 0, 0, ConvProto->isVariadic(), + ConvProto->getTypeQuals(), + false, false, 0, 0, + ConvProto->getNoReturnAttr()); + + // Perform template argument deduction against the type that we would + // expect the function to have. + if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType, + Specialization, Info) + == Sema::TDK_Success) { + R.addDecl(Specialization); + Found = true; + } + } + } + return Found; } -- cgit v1.2.3