<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 1, 2015 at 9:23 AM, Reid Kleckner <span dir="ltr"><<a href="mailto:reid@kleckner.net" target="_blank">reid@kleckner.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Wed Apr  1 11:23:44 2015<br>
New Revision: 233817<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=233817&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=233817&view=rev</a><br>
Log:<br>
Mark instantiated function decls as inline specified if any pattern is<br>
<br>
A function template pattern can be declared without the 'inline'<br>
specifier and defined later with the 'inline' specifier. However, during<br>
instantiation, we were only looking at the canonical decl to see if we<br>
should mark the instantiated decl as inline specified. Since the<br>
instantiated decl actually represents many pattern declarations, put the<br>
inline specifier on the instantiation decl if any of the pattern decls<br>
have it.<br>
<br>
Added:<br>
    cfe/trunk/test/CodeGenCXX/inlinehint.cpp<br>
Modified:<br>
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=233817&r1=233816&r2=233817&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=233817&r1=233816&r2=233817&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Apr  1 11:23:44 2015<br>
@@ -1304,6 +1304,15 @@ static QualType adjustFunctionTypeForIns<br>
                                  NewFunc->getParamTypes(), NewEPI);<br>
 }<br>
<br>
+/// Return true if any redeclaration of FD was inline specified. Useful for<br>
+/// propagating the 'inline' specifier onto function template instantiations.<br>
+static bool isAnyRedeclInlineSpecified(const FunctionDecl *FD) {<br>
+  for (const auto *R : FD->redecls())<br>
+    if (R->isInlineSpecified())<br></blockquote><div><br>This could be written with std::any_of, if you like. (yeah, it's not a strict win, between not having range-based algorithms and not having polymorphic lambdas)<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      return true;<br>
+  return false;<br>
+}<br>
+<br>
 /// Normal class members are of more specific types and therefore<br>
 /// don't make it here.  This function serves two purposes:<br>
 ///   1) instantiating function templates<br>
@@ -1372,7 +1381,8 @@ Decl *TemplateDeclInstantiator::VisitFun<br>
       FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),<br>
                            D->getNameInfo(), T, TInfo,<br>
                            D->getCanonicalDecl()->getStorageClass(),<br>
-                           D->isInlineSpecified(), D->hasWrittenPrototype(),<br>
+                           isAnyRedeclInlineSpecified(D),<br>
+                           D->hasWrittenPrototype(),<br>
                            D->isConstexpr());<br>
   Function->setRangeEnd(D->getSourceRange().getEnd());<br>
<br>
@@ -1669,7 +1679,7 @@ TemplateDeclInstantiator::VisitCXXMethod<br>
     Method = CXXConstructorDecl::Create(SemaRef.Context, Record,<br>
                                         StartLoc, NameInfo, T, TInfo,<br>
                                         Constructor->isExplicit(),<br>
-                                        Constructor->isInlineSpecified(),<br>
+                                        isAnyRedeclInlineSpecified(Constructor),<br>
                                         false, Constructor->isConstexpr());<br>
<br>
     // Claim that the instantiation of a constructor or constructor template<br>
@@ -1704,12 +1714,12 @@ TemplateDeclInstantiator::VisitCXXMethod<br>
   } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {<br>
     Method = CXXDestructorDecl::Create(SemaRef.Context, Record,<br>
                                        StartLoc, NameInfo, T, TInfo,<br>
-                                       Destructor->isInlineSpecified(),<br>
+                                       isAnyRedeclInlineSpecified(Destructor),<br>
                                        false);<br>
   } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {<br>
     Method = CXXConversionDecl::Create(SemaRef.Context, Record,<br>
                                        StartLoc, NameInfo, T, TInfo,<br>
-                                       Conversion->isInlineSpecified(),<br>
+                                       isAnyRedeclInlineSpecified(Conversion),<br>
                                        Conversion->isExplicit(),<br>
                                        Conversion->isConstexpr(),<br>
                                        Conversion->getLocEnd());<br>
@@ -1717,7 +1727,7 @@ TemplateDeclInstantiator::VisitCXXMethod<br>
     StorageClass SC = D->isStatic() ? SC_Static : SC_None;<br>
     Method = CXXMethodDecl::Create(SemaRef.Context, Record,<br>
                                    StartLoc, NameInfo, T, TInfo,<br>
-                                   SC, D->isInlineSpecified(),<br>
+                                   SC, isAnyRedeclInlineSpecified(D),<br>
                                    D->isConstexpr(), D->getLocEnd());<br>
   }<br>
<br>
<br>
Added: cfe/trunk/test/CodeGenCXX/inlinehint.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/inlinehint.cpp?rev=233817&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/inlinehint.cpp?rev=233817&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/inlinehint.cpp (added)<br>
+++ cfe/trunk/test/CodeGenCXX/inlinehint.cpp Wed Apr  1 11:23:44 2015<br>
@@ -0,0 +1,33 @@<br>
+// RUN: %clang_cc1 -triple %itanium_abi_triple %s -emit-llvm -o - | FileCheck %s<br>
+<br>
+inline void InlineFunc() {}<br>
+// CHECK: define linkonce_odr void @_Z10InlineFuncv() #[[INLINEHINTATTR:[0-9]+]] comdat {<br>
+<br>
+struct MyClass {<br>
+  static void InlineStaticMethod();<br>
+  void InlineInstanceMethod();<br>
+};<br>
+inline void MyClass::InlineStaticMethod() {}<br>
+// CHECK: define linkonce_odr void @_ZN7MyClass18InlineStaticMethodEv() #[[INLINEHINTATTR]] comdat<br>
+inline void MyClass::InlineInstanceMethod() {}<br>
+// CHECK: define linkonce_odr void @_ZN7MyClass20InlineInstanceMethodEv(%struct.MyClass* %this) #[[INLINEHINTATTR]] comdat<br>
+<br>
+template <typename T><br>
+struct MyTemplate {<br>
+  static void InlineStaticMethod();<br>
+  void InlineInstanceMethod();<br>
+};<br>
+template <typename T> inline void MyTemplate<T>::InlineStaticMethod() {}<br>
+// CHECK: define linkonce_odr void @_ZN10MyTemplateIiE18InlineStaticMethodEv() #[[INLINEHINTATTR]] comdat<br>
+template <typename T> inline void MyTemplate<T>::InlineInstanceMethod() {}<br>
+// CHECK: define linkonce_odr void @_ZN10MyTemplateIiE20InlineInstanceMethodEv(%struct.MyTemplate* %this) #[[INLINEHINTATTR]] comdat<br>
+<br>
+void UseThem() {<br>
+  InlineFunc();<br>
+  MyClass::InlineStaticMethod();<br>
+  MyClass().InlineInstanceMethod();<br>
+  MyTemplate<int>::InlineStaticMethod();<br>
+  MyTemplate<int>().InlineInstanceMethod();<br>
+}<br>
+<br>
+// CHECK: attributes #[[INLINEHINTATTR]] = { {{.*}}inlinehint{{.*}} }<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>