[PATCH] Template argument deduction gcc testsuite test case sfinae-dr657.C

SENTHIL KUMAR THANGAVELU senthil.t at samsung.com
Wed Oct 16 22:10:54 PDT 2013


Resending mail in txt format.

------- Original Message -------
Sender : SENTHIL KUMAR THANGAVELU<senthil.t at samsung.com> ./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.html section "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.

--- /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




More information about the cfe-commits mailing list