rafauler created this revision. rafauler added reviewers: rsmith, ldionne, aaron.ballman. Herald added a subscriber: jdoerfert. Herald added a project: clang.
As PR17480 describes, clang does not support the used attribute for member functions of class templates. This means that if the member function is not used, its definition is never instantiated. This patch changes clang to emit the definition if it has the used attribute. This is a second attempt after the revert of D56928 <https://reviews.llvm.org/D56928>. The original diff broke the swift toolchain because its source contained the attribute used in a member function that was later explictly specialized. A check for C++14 [temp.expl.spec]p6 was mistakenly firing here: D56928 <https://reviews.llvm.org/D56928> set the point of instantiation of member functions with attribute used at the same point of instantiation of its containing class template. When a explicit specialization was done, Clang was complaining that a explicit specialization cannot occur after the use recorded to be at the instantiation of the class template. The problem is that the use was not real, but induced by the attribute used. To avoid running into this check, I no longer pass a valid SourceLocation to MarkFunctionReferenced. The goal is to cause the function to be instantiated at the end of the TU, but without a valid point of instantiation, making this use not interfere anymore with the check for C++14 [temp.expl.spec]p6. Test Plan: Kept the original testcase and added another one to cover the swift runtime issue. Also tested this diff in the swift build and verified it is working. Repository: rC Clang https://reviews.llvm.org/D58216 Files: lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGenCXX/attr-used-member-function-implicit-instantiation.cpp test/SemaTemplate/attr-used-member-function-implicit-instantiation.cpp Index: test/SemaTemplate/attr-used-member-function-implicit-instantiation.cpp =================================================================== --- /dev/null +++ test/SemaTemplate/attr-used-member-function-implicit-instantiation.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Check that __attribute__((used)) in member functions of templated classes +// does not break explicit specializations of those functions + +// expected-no-diagnostics +template <typename> +struct a { + void verify() __attribute__((__used__)); +}; +using b = a<int>; +template<> void b::verify() {} Index: test/CodeGenCXX/attr-used-member-function-implicit-instantiation.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/attr-used-member-function-implicit-instantiation.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// Check that PR17480 is fixed: __attribute__((used)) ignored in templated +// classes +namespace InstantiateUsedMemberDefinition { +template <typename T> +struct S { + int __attribute__((used)) f() { + return 0; + } +}; + +void test() { + // Check that InstantiateUsedMemberDefinition::S<int>::f() is defined + // as a result of the S class template implicit instantiation + // CHECK: define linkonce_odr i32 @_ZN31InstantiateUsedMemberDefinition1SIiE1fEv + S<int> inst; +} +} // namespace InstantiateUsedMemberDefinition Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2175,6 +2175,11 @@ Owner->addDecl(Method); } + // PR17480: Honor the used attribute to instantiate member function + // definitions + if (Method->hasAttr<UsedAttr>()) + SemaRef.MarkFunctionReferenced(SourceLocation(), Method); + return Method; }
Index: test/SemaTemplate/attr-used-member-function-implicit-instantiation.cpp =================================================================== --- /dev/null +++ test/SemaTemplate/attr-used-member-function-implicit-instantiation.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Check that __attribute__((used)) in member functions of templated classes +// does not break explicit specializations of those functions + +// expected-no-diagnostics +template <typename> +struct a { + void verify() __attribute__((__used__)); +}; +using b = a<int>; +template<> void b::verify() {} Index: test/CodeGenCXX/attr-used-member-function-implicit-instantiation.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/attr-used-member-function-implicit-instantiation.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// Check that PR17480 is fixed: __attribute__((used)) ignored in templated +// classes +namespace InstantiateUsedMemberDefinition { +template <typename T> +struct S { + int __attribute__((used)) f() { + return 0; + } +}; + +void test() { + // Check that InstantiateUsedMemberDefinition::S<int>::f() is defined + // as a result of the S class template implicit instantiation + // CHECK: define linkonce_odr i32 @_ZN31InstantiateUsedMemberDefinition1SIiE1fEv + S<int> inst; +} +} // namespace InstantiateUsedMemberDefinition Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2175,6 +2175,11 @@ Owner->addDecl(Method); } + // PR17480: Honor the used attribute to instantiate member function + // definitions + if (Method->hasAttr<UsedAttr>()) + SemaRef.MarkFunctionReferenced(SourceLocation(), Method); + return Method; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits