<div dir="ltr">On Wed, Oct 16, 2013 at 10:10 PM, SENTHIL KUMAR THANGAVELU <span dir="ltr"><<a href="mailto:senthil.t@samsung.com" target="_blank">senthil.t@samsung.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Resending mail in txt format.<br>
<br>
------- Original Message -------<br>
Sender : SENTHIL KUMAR THANGAVELU<<a href="mailto:senthil.t@samsung.com">senthil.t@samsung.com</a>> ./Senior Technical Manager/SRI-Bangalore-Native Framework/Samsung Electronics<br>
Date : Oct 16, 2013 19:38 (GMT+05:30)<br>
Title : [PATCH] Template argument deduction gcc testsuite test case sfinae-dr657.C<br>
<br>
Hello all,<br>
    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<br>

<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3027.html" target="_blank">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3027.html</a> section "657. Abstract class parameter in synthesized declaration"<br>

<br>
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.<br>

<br>
test case sfinae-dr657.C<br>
// DR 657<br>
// Test that a return or parameter type with abstract class type causes a<br>
// deduction failure.<br>
struct A<br>
{<br>
  A();<br>
  virtual void f() = 0;<br>
};<br>
template<class T> T declval();<br>
template<class T> int declval(...);<br>
int main()<br>
{<br>
  int i = declval<A>();<br>
}<br>
<br>
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.<br></blockquote>
<div><br></div><div>The relevant language rule is completely broken. Consider:</div><div><br></div><div>template<typename T> T declval(int);</div><div>template<typename T> int declval(...);</div><div><br></div>
<div>struct A;</div><div>using T = decltype(declval<A>(0)); // what type is this?</div><div><br></div><div>struct A { virtual void f() = 0; };</div><div>using T = decltype(declval<A>(0)); // what type is it now?<br>
</div><div><br></div><div>... and worse:</div><div><br></div><div>template<typename T> struct X { virtual void f() = 0; };</div><div>using U = decltype(declval<X<int>>(0)); // does this cause the instantiation of X<int>?</div>
<div><br></div><div>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.</div><div><br></div><div>
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.</div><div><br></div><div>=> I believe this to be a bug in the standard, not a bug in Clang.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
--- /home/camel/orig/llvm_3.3_src/tools/clang/lib/Sema/SemaOverload.cpp<br>
+++ /home/camel/llvm_3.3_src/tools/clang/lib/Sema/SemaOverload.cpp<br>
@@ -9534,6 +9534,51 @@<br>
   return true;<br>
 }<br>
<br>
+/// \brief Reject a call candidate if abstract type is returned<br>
+static bool IsRejectAbstractReturningCallCandidate(<br>
+               FunctionTemplateDecl *FuncTemplate,<br>
+               TemplateArgumentListInfo *ExplicitTemplateArgs) { return false;<br>
+  if(!FuncTemplate || !ExplicitTemplateArgs)<br>
+    return false;<br>
+<br>
+  TemplateParameterList *TemplateParams = FuncTemplate->getTemplateParameters();<br>
+  FunctionDecl * FD = FuncTemplate->getTemplatedDecl();<br>
+  if (!FD || !TemplateParams)<br>
+    return false;<br>
+<br>
+  // Check if atleast one of the template param is used as return type<br>
+  const Type * RetType = (FD) ? FD->getResultType().getTypePtr() : 0;<br>
+  unsigned MatchedIdx = 0;<br>
+  bool RetDependsOnTemplateArg = false;<br>
+  for (TemplateParameterList::iterator I = TemplateParams->begin(),<br>
+         E = TemplateParams->end(); I != E ; ++I) {<br>
+    NamedDecl * ND = *I;<br>
+    TemplateTypeParmDecl  * TmpParamDecl = dyn_cast<TemplateTypeParmDecl>(ND);<br>
+    if (TmpParamDecl) {<br>
+        const Type * TemplateParamType = TmpParamDecl->getTypeForDecl();<br>
+        if (TemplateParamType == RetType) {<br>
+          RetDependsOnTemplateArg = true;<br>
+          break;<br>
+        }<br>
+    }<br>
+    MatchedIdx++;<br>
+  }<br>
+<br>
+  if (RetDependsOnTemplateArg) {<br>
+    TemplateArgumentListInfo ArgList = *ExplicitTemplateArgs;<br>
+    if(MatchedIdx >= ArgList.size())<br>
+        return false;<br>
+<br>
+    TemplateArgumentLoc TAL = ArgList[MatchedIdx];<br>
+    CXXRecordDecl * RD =<br>
+      (TAL.getArgument().getKind() == TemplateArgument::Type) ?<br>
+      TAL.getArgument().getAsType().getTypePtr()->getAsCXXRecordDecl() : 0;<br>
+<br>
+    return (RD) ? (RD->getDefinition() && RD->isAbstract()) : false;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
 /// \brief Add a single candidate to the overload set.<br>
 static void AddOverloadedCallCandidate(Sema &S,<br>
                                        DeclAccessPair FoundDecl,<br>
@@ -9558,6 +9603,11 @@<br>
<br>
   if (FunctionTemplateDecl *FuncTemplate<br>
       = dyn_cast<FunctionTemplateDecl>(Callee)) {<br>
+<br>
+    if(IsRejectAbstractReturningCallCandidate(FuncTemplate,<br>
+                                              ExplicitTemplateArgs))<br>
+      return;<br>
+<br>
     S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl,<br>
                                    ExplicitTemplateArgs, Args, CandidateSet);<br>
     return;<br>
<br>
<br>
<br>
Regards<br>
Senthil Kumar<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>