r233817 - Mark instantiated function decls as inline specified if any pattern is

Reid Kleckner reid at kleckner.net
Wed Apr 1 09:23:44 PDT 2015


Author: rnk
Date: Wed Apr  1 11:23:44 2015
New Revision: 233817

URL: http://llvm.org/viewvc/llvm-project?rev=233817&view=rev
Log:
Mark instantiated function decls as inline specified if any pattern is

A function template pattern can be declared without the 'inline'
specifier and defined later with the 'inline' specifier. However, during
instantiation, we were only looking at the canonical decl to see if we
should mark the instantiated decl as inline specified. Since the
instantiated decl actually represents many pattern declarations, put the
inline specifier on the instantiation decl if any of the pattern decls
have it.

Added:
    cfe/trunk/test/CodeGenCXX/inlinehint.cpp
Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=233817&r1=233816&r2=233817&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Apr  1 11:23:44 2015
@@ -1304,6 +1304,15 @@ static QualType adjustFunctionTypeForIns
                                  NewFunc->getParamTypes(), NewEPI);
 }
 
+/// Return true if any redeclaration of FD was inline specified. Useful for
+/// propagating the 'inline' specifier onto function template instantiations.
+static bool isAnyRedeclInlineSpecified(const FunctionDecl *FD) {
+  for (const auto *R : FD->redecls())
+    if (R->isInlineSpecified())
+      return true;
+  return false;
+}
+
 /// Normal class members are of more specific types and therefore
 /// don't make it here.  This function serves two purposes:
 ///   1) instantiating function templates
@@ -1372,7 +1381,8 @@ Decl *TemplateDeclInstantiator::VisitFun
       FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(),
                            D->getNameInfo(), T, TInfo,
                            D->getCanonicalDecl()->getStorageClass(),
-                           D->isInlineSpecified(), D->hasWrittenPrototype(),
+                           isAnyRedeclInlineSpecified(D),
+                           D->hasWrittenPrototype(),
                            D->isConstexpr());
   Function->setRangeEnd(D->getSourceRange().getEnd());
 
@@ -1669,7 +1679,7 @@ TemplateDeclInstantiator::VisitCXXMethod
     Method = CXXConstructorDecl::Create(SemaRef.Context, Record,
                                         StartLoc, NameInfo, T, TInfo,
                                         Constructor->isExplicit(),
-                                        Constructor->isInlineSpecified(),
+                                        isAnyRedeclInlineSpecified(Constructor),
                                         false, Constructor->isConstexpr());
 
     // Claim that the instantiation of a constructor or constructor template
@@ -1704,12 +1714,12 @@ TemplateDeclInstantiator::VisitCXXMethod
   } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
     Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
                                        StartLoc, NameInfo, T, TInfo,
-                                       Destructor->isInlineSpecified(),
+                                       isAnyRedeclInlineSpecified(Destructor),
                                        false);
   } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) {
     Method = CXXConversionDecl::Create(SemaRef.Context, Record,
                                        StartLoc, NameInfo, T, TInfo,
-                                       Conversion->isInlineSpecified(),
+                                       isAnyRedeclInlineSpecified(Conversion),
                                        Conversion->isExplicit(),
                                        Conversion->isConstexpr(),
                                        Conversion->getLocEnd());
@@ -1717,7 +1727,7 @@ TemplateDeclInstantiator::VisitCXXMethod
     StorageClass SC = D->isStatic() ? SC_Static : SC_None;
     Method = CXXMethodDecl::Create(SemaRef.Context, Record,
                                    StartLoc, NameInfo, T, TInfo,
-                                   SC, D->isInlineSpecified(),
+                                   SC, isAnyRedeclInlineSpecified(D),
                                    D->isConstexpr(), D->getLocEnd());
   }
 

Added: cfe/trunk/test/CodeGenCXX/inlinehint.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/inlinehint.cpp?rev=233817&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/inlinehint.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/inlinehint.cpp Wed Apr  1 11:23:44 2015
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple %s -emit-llvm -o - | FileCheck %s
+
+inline void InlineFunc() {}
+// CHECK: define linkonce_odr void @_Z10InlineFuncv() #[[INLINEHINTATTR:[0-9]+]] comdat {
+
+struct MyClass {
+  static void InlineStaticMethod();
+  void InlineInstanceMethod();
+};
+inline void MyClass::InlineStaticMethod() {}
+// CHECK: define linkonce_odr void @_ZN7MyClass18InlineStaticMethodEv() #[[INLINEHINTATTR]] comdat
+inline void MyClass::InlineInstanceMethod() {}
+// CHECK: define linkonce_odr void @_ZN7MyClass20InlineInstanceMethodEv(%struct.MyClass* %this) #[[INLINEHINTATTR]] comdat
+
+template <typename T>
+struct MyTemplate {
+  static void InlineStaticMethod();
+  void InlineInstanceMethod();
+};
+template <typename T> inline void MyTemplate<T>::InlineStaticMethod() {}
+// CHECK: define linkonce_odr void @_ZN10MyTemplateIiE18InlineStaticMethodEv() #[[INLINEHINTATTR]] comdat
+template <typename T> inline void MyTemplate<T>::InlineInstanceMethod() {}
+// CHECK: define linkonce_odr void @_ZN10MyTemplateIiE20InlineInstanceMethodEv(%struct.MyTemplate* %this) #[[INLINEHINTATTR]] comdat
+
+void UseThem() {
+  InlineFunc();
+  MyClass::InlineStaticMethod();
+  MyClass().InlineInstanceMethod();
+  MyTemplate<int>::InlineStaticMethod();
+  MyTemplate<int>().InlineInstanceMethod();
+}
+
+// CHECK: attributes #[[INLINEHINTATTR]] = { {{.*}}inlinehint{{.*}} }





More information about the cfe-commits mailing list