r190377 - Ignore calling conventions when checking function template specializations

Reid Kleckner reid at kleckner.net
Mon Sep 9 18:04:45 PDT 2013


Author: rnk
Date: Mon Sep  9 20:04:45 2013
New Revision: 190377

URL: http://llvm.org/viewvc/llvm-project?rev=190377&view=rev
Log:
Ignore calling conventions when checking function template specializations

Summary:
Calling conventions are inherited during decl merging.  Before this
change, deduction would fail due to a type mismatch between the template
and the specialization.  This change adjusts the CCs to match before
deduction, and lets the decl merging logic diagnose mismatch or inherit
the CC from the template.

This allows specializations of static member function templates in the
Microsoft C++ ABI.

Reviewers: rsmith

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D1570

Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=190377&r1=190376&r2=190377&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Sep  9 20:04:45 2013
@@ -6403,11 +6403,11 @@ bool Sema::CheckFunctionTemplateSpeciali
       // it will be a static member function until we know which template it
       // specializes), so adjust it now assuming it specializes this template.
       QualType FT = FD->getType();
+      const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
+      FunctionDecl *TmplFD = FunTmpl->getTemplatedDecl();
       if (FD->isConstexpr()) {
-        CXXMethodDecl *OldMD =
-          dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+        CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(TmplFD);
         if (OldMD && OldMD->isConst()) {
-          const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>();
           FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
           EPI.TypeQuals |= Qualifiers::Const;
           FT = Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(),
@@ -6415,6 +6415,16 @@ bool Sema::CheckFunctionTemplateSpeciali
         }
       }
 
+      // Ignore differences in calling convention until decl merging.
+      const FunctionProtoType *TmplFT =
+          TmplFD->getType()->castAs<FunctionProtoType>();
+      if (FPT->getCallConv() != TmplFT->getCallConv()) {
+        FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+        EPI.ExtInfo = EPI.ExtInfo.withCallingConv(TmplFT->getCallConv());
+        FT = Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(),
+                                     EPI);
+      }
+
       // C++ [temp.expl.spec]p11:
       //   A trailing template-argument can be left unspecified in the
       //   template-id naming an explicit function template specialization

Modified: cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp?rev=190377&r1=190376&r2=190377&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp (original)
+++ cfe/trunk/test/SemaCXX/decl-microsoft-call-conv.cpp Mon Sep  9 20:04:45 2013
@@ -144,3 +144,19 @@ void multi_attribute(int x) { __builtin_
 // expected-error at +2 {{stdcall and cdecl attributes are not compatible}}
 // expected-error at +1 {{fastcall and cdecl attributes are not compatible}}
 void __cdecl __cdecl __stdcall __cdecl __fastcall multi_cc(int x);
+
+template <typename T> void __stdcall StdcallTemplate(T) {}
+template <> void StdcallTemplate<int>(int) {}
+template <> void __stdcall StdcallTemplate<short>(short) {}
+
+// FIXME: Note the template, not the implicit instantiation.
+// expected-error at +2 {{function declared 'cdecl' here was previously declared 'stdcall}}
+// expected-note at +1 {{previous declaration is here}}
+template <> void __cdecl StdcallTemplate<long>(long) {}
+
+struct ExactlyInt {
+  template <typename T> static int cast_to_int(T) {
+    return T::this_is_not_an_int();
+  }
+};
+template <> inline int ExactlyInt::cast_to_int<int>(int x) { return x; }





More information about the cfe-commits mailing list