From: Rafael Espindola Date: Tue, 31 Jul 2012 01:54:04 +0000 (+0000) Subject: Attributes preceding a function declaration are first applied to the return X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a78a640c5f59720f2c2b8034eca4fbf8525d9026;p=clang Attributes preceding a function declaration are first applied to the return type and then propagated to the function. This was failing for destructors, constructors and constructors templates since they don't have a return type. Fix that by directly calling processTypeAttrs on the dummy type we use as the return type in these cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161020 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index e018a5bb37..31a87dc8a0 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1812,6 +1812,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // Constructors and destructors don't have return types. Use // "void" instead. T = SemaRef.Context.VoidTy; + if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList()) + processTypeAttrs(state, T, true, attrs); break; case UnqualifiedId::IK_ConversionFunctionId: diff --git a/test/CodeGenCXX/pr13396.cpp b/test/CodeGenCXX/pr13396.cpp new file mode 100644 index 0000000000..b390eea009 --- /dev/null +++ b/test/CodeGenCXX/pr13396.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s +struct foo { + template + __attribute__ ((regparm (3))) foo(T x) {} + __attribute__ ((regparm (3))) foo(); + __attribute__ ((regparm (3))) ~foo(); +}; + +foo::foo() { + // CHECK: define void @_ZN3fooC1Ev(%struct.foo* inreg %this) + // CHECK: define void @_ZN3fooC2Ev(%struct.foo* inreg %this) +} + +foo::~foo() { + // CHECK: define void @_ZN3fooD1Ev(%struct.foo* inreg %this) + // CHECK: define void @_ZN3fooD2Ev(%struct.foo* inreg %this) +} + +void dummy() { + // FIXME: how can we explicitly instantiate a template constructor? Gcc and + // older clangs accept: + // template foo::foo(int x); + foo x(10); + // CHECK: define linkonce_odr void @_ZN3fooC1IiEET_(%struct.foo* inreg %this, i32 inreg %x) + // CHECK: define linkonce_odr void @_ZN3fooC2IiEET_(%struct.foo* inreg %this, i32 inreg %x) +}