On Thu, Oct 17, 2013 at 4:15 PM, Richard Smith <[email protected]>wrote:
> On Wed, Oct 16, 2013 at 10:10 PM, SENTHIL KUMAR THANGAVELU < > [email protected]> wrote: > >> Resending mail in txt format. >> >> ------- Original Message ------- >> Sender : SENTHIL KUMAR THANGAVELU<[email protected]> ./Senior >> Technical Manager/SRI-Bangalore-Native Framework/Samsung Electronics >> Date : Oct 16, 2013 19:38 (GMT+05:30) >> Title : [PATCH] Template argument deduction gcc testsuite test case >> sfinae-dr657.C >> >> Hello all, >> Found a test case sfinae-dr657.C in gcc 4.8.1 testsuite. This is >> related to c++ standard section "14.8.2 Template argument deduction" which >> states type deduction may fail for "Attempting to create a function type in >> which a parameter type or the return type is an abstract class type". This >> is a DR in >> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3027.htmlsection >> "657. Abstract class parameter in synthesized declaration" >> >> Following test case should compile with -c option as per test case. With >> gcc 4.8.1 and intel x64 compiler 13.1.3 this test case is accepted for >> compilation whereas clang throws "call to 'declval' is ambiguous" error >> during compilation. Problem seems to be call candidate which ends up >> returning abstract type is considered instead of being rejected. As per >> test case abstract type returning call should result in deduction failure >> and only elipsis version should be considered for call candidate list. >> >> test case sfinae-dr657.C >> // DR 657 >> // Test that a return or parameter type with abstract class type causes a >> // deduction failure. >> struct A >> { >> A(); >> virtual void f() = 0; >> }; >> template<class T> T declval(); >> template<class T> int declval(...); >> int main() >> { >> int i = declval<A>(); >> } >> >> I have added a patch for the issue as follows based on 3.3 base code. >> This patch works and passed LLVM regression. I am looking for comments on >> the patch. Based on comments I will rework the patch and send it. >> > > The relevant language rule is completely broken. Consider: > > template<typename T> T declval(int); > template<typename T> int declval(...); > > struct A; > using T = decltype(declval<A>(0)); // what type is this? > > struct A { virtual void f() = 0; }; > using T = decltype(declval<A>(0)); // what type is it now? > > ... and worse: > > template<typename T> struct X { virtual void f() = 0; }; > using U = decltype(declval<X<int>>(0)); // does this cause the > instantiation of X<int>? > > The rules for decltype were crafted such that the type would not be > completed here. If the type depends on whether X<int> is abstract, then we > would need to complete it. > > GCC gives U the type 'X<int>', not 'int'. But it changes its mind if you > trigger the instantiation of X<int> before the declaration of U. > > => I believe this to be a bug in the standard, not a bug in Clang. > ... and it's already been filed. This is core issue 1646. > --- /home/camel/orig/llvm_3.3_src/tools/clang/lib/Sema/SemaOverload.cpp >> +++ /home/camel/llvm_3.3_src/tools/clang/lib/Sema/SemaOverload.cpp >> @@ -9534,6 +9534,51 @@ >> return true; >> } >> >> +/// \brief Reject a call candidate if abstract type is returned >> +static bool IsRejectAbstractReturningCallCandidate( >> + FunctionTemplateDecl *FuncTemplate, >> + TemplateArgumentListInfo *ExplicitTemplateArgs) { return >> false; >> + if(!FuncTemplate || !ExplicitTemplateArgs) >> + return false; >> + >> + TemplateParameterList *TemplateParams = >> FuncTemplate->getTemplateParameters(); >> + FunctionDecl * FD = FuncTemplate->getTemplatedDecl(); >> + if (!FD || !TemplateParams) >> + return false; >> + >> + // Check if atleast one of the template param is used as return type >> + const Type * RetType = (FD) ? FD->getResultType().getTypePtr() : 0; >> + unsigned MatchedIdx = 0; >> + bool RetDependsOnTemplateArg = false; >> + for (TemplateParameterList::iterator I = TemplateParams->begin(), >> + E = TemplateParams->end(); I != E ; ++I) { >> + NamedDecl * ND = *I; >> + TemplateTypeParmDecl * TmpParamDecl = >> dyn_cast<TemplateTypeParmDecl>(ND); >> + if (TmpParamDecl) { >> + const Type * TemplateParamType = TmpParamDecl->getTypeForDecl(); >> + if (TemplateParamType == RetType) { >> + RetDependsOnTemplateArg = true; >> + break; >> + } >> + } >> + MatchedIdx++; >> + } >> + >> + if (RetDependsOnTemplateArg) { >> + TemplateArgumentListInfo ArgList = *ExplicitTemplateArgs; >> + if(MatchedIdx >= ArgList.size()) >> + return false; >> + >> + TemplateArgumentLoc TAL = ArgList[MatchedIdx]; >> + CXXRecordDecl * RD = >> + (TAL.getArgument().getKind() == TemplateArgument::Type) ? >> + TAL.getArgument().getAsType().getTypePtr()->getAsCXXRecordDecl() : >> 0; >> + >> + return (RD) ? (RD->getDefinition() && RD->isAbstract()) : false; >> + } >> + return false; >> +} >> + >> /// \brief Add a single candidate to the overload set. >> static void AddOverloadedCallCandidate(Sema &S, >> DeclAccessPair FoundDecl, >> @@ -9558,6 +9603,11 @@ >> >> if (FunctionTemplateDecl *FuncTemplate >> = dyn_cast<FunctionTemplateDecl>(Callee)) { >> + >> + if(IsRejectAbstractReturningCallCandidate(FuncTemplate, >> + ExplicitTemplateArgs)) >> + return; >> + >> S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl, >> ExplicitTemplateArgs, Args, >> CandidateSet); >> return; >> >> >> >> Regards >> Senthil Kumar >> >> _______________________________________________ >> cfe-commits mailing list >> [email protected] >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> > >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
