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
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());
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
} 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());
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());
}
--- /dev/null
+// 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{{.*}} }