From: Rafael Espindola Date: Tue, 10 Dec 2013 00:59:31 +0000 (+0000) Subject: Take into consideration calling convention when processing specializations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=03c4e28678b6608eeefb3fcb1a2bdba03823807c;p=clang Take into consideration calling convention when processing specializations. This fixes pr18141. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196855 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 0778b1b235..67ad469c1c 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2570,6 +2570,11 @@ public: /// function type typedefs and typename template arguments. void adjustMemberFunctionCC(QualType &T, bool IsStatic); + // Check if there is an explicit attribute, but only look through parens. + // The intent is to look for an attribute on the current declarator, but not + // one that came from a typedef. + bool hasExplicitCallingConv(QualType &T); + /// Get the outermost AttributedType node that sets a calling convention. /// Valid types should not have multiple attributes with different CCs. const AttributedType *getCallingConvAttributedType(QualType T) const; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 20a3d28331..b134f6ea51 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -6654,7 +6654,10 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); if (CXXMethodDecl *Method = dyn_cast(D)) { - if (Context.hasSameType(Function->getType(), Method->getType())) { + QualType Adjusted = Function->getType(); + if (!hasExplicitCallingConv(Adjusted)) + Adjusted = adjustCCAndNoReturn(Adjusted, Method->getType()); + if (Context.hasSameType(Adjusted, Method->getType())) { Instantiation = Method; InstantiatedFrom = Method->getInstantiatedFromMemberFunction(); MSInfo = Method->getMemberSpecializationInfo(); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 514a0fa30d..e6a49f5d3f 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -4595,6 +4595,16 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } +bool Sema::hasExplicitCallingConv(QualType &T) { + QualType R = T.IgnoreParens(); + while (const AttributedType *AT = dyn_cast(R)) { + if (AT->isCallingConv()) + return true; + R = AT->getModifiedType().IgnoreParens(); + } + return false; +} + void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) { FunctionTypeUnwrapper Unwrapped(*this, T); const FunctionType *FT = Unwrapped.get(); @@ -4611,15 +4621,8 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic) { if (CurCC != FromCC || FromCC == ToCC) return; - // Check if there was an explicit attribute, but only look through parens. - // The intent is to look for an attribute on the current declarator, but not - // one that came from a typedef. - QualType R = T.IgnoreParens(); - while (const AttributedType *AT = dyn_cast(R)) { - if (AT->isCallingConv()) - return; - R = AT->getModifiedType().IgnoreParens(); - } + if (hasExplicitCallingConv(T)) + return; FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(ToCC)); QualType Wrapped = Unwrapped.wrap(*this, FT); diff --git a/test/SemaCXX/decl-microsoft-call-conv.cpp b/test/SemaCXX/decl-microsoft-call-conv.cpp index fd20ae234e..fa782ead34 100644 --- a/test/SemaCXX/decl-microsoft-call-conv.cpp +++ b/test/SemaCXX/decl-microsoft-call-conv.cpp @@ -203,3 +203,29 @@ namespace test6 { zed(&foo::bar); } } + +namespace test7 { + template + struct S { + void f(T t) { + t = 42; + } + }; + template<> void S::f(void*); + void g(S s, void* p) { + s.f(p); + } +} + +namespace test8 { + template + struct S { + void f(T t) { // expected-note {{previous declaration is here}} + t = 42; // expected-error {{assigning to 'void *' from incompatible type 'int'}} + } + }; + template<> void __cdecl S::f(void*); // expected-error {{function declared 'cdecl' here was previously declared without calling convention}} + void g(S s, void* p) { + s.f(p); // expected-note {{in instantiation of member function 'test8::S::f' requested here}} + } +}