diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10072,6 +10072,7 @@ const Decl *Pattern, Decl *Inst, LateInstantiatedAttrVec *LateAttrs = nullptr, LocalInstantiationScope *OuterMostScope = nullptr); + void updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst); void InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs, diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -834,6 +834,22 @@ } } +/// Update instantiation attributes after template was late parsed. +/// +/// Some attributes are evaluated based on the body of template. If it is +/// late parsed, such attributes cannot be evaluated when declaration is +/// instantiated. This function is used to update instantiation attributes when +/// template definition is ready. +void Sema::updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst) { + for (const auto *Attr : Pattern->attrs()) { + if (auto *A = dyn_cast(Attr)) { + if (!Inst->hasAttr()) + Inst->addAttr(A->clone(getASTContext())); + continue; + } + } +} + /// In the MS ABI, we need to instantiate default arguments of dllexported /// default constructors along with the constructor definition. This allows IR /// gen to emit a constructor closure which calls the default constructor with @@ -4916,6 +4932,7 @@ "missing LateParsedTemplate"); LateTemplateParser(OpaqueParser, *LPTIter->second); Pattern = PatternDecl->getBody(PatternDecl); + updateAttrsForLateParsedTemplate(PatternDecl, Function); } // Note, we should never try to instantiate a deleted function template. diff --git a/clang/test/CodeGen/fp-template.cpp b/clang/test/CodeGen/fp-template.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/fp-template.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -fdelayed-template-parsing -o - %s | FileCheck %s + +template +T templ_01(T x, T y) { +#pragma STDC FENV_ACCESS ON + return x + y; +} + +float func_01(float x, float y) { + return templ_01(x, y); +} + +// CHECK-LABEL: define {{.*}} @_Z8templ_01IfET_S0_S0_ +// CHECK-SAME: (float noundef %{{.*}}, float noundef %{{.*}}) #[[ATTR01:[0-9]+]]{{.*}} { +// CHECK: call float @llvm.experimental.constrained.fadd.f32 + +// CHECK: attributes #[[ATTR01]] = { {{.*}}strictfp