Author: Serge Pavlov
Date: 2023-06-28T20:11:54+07:00
New Revision: 98390ccb80569e8fbb20e6c996b4b8cff87fbec6

URL: 
https://github.com/llvm/llvm-project/commit/98390ccb80569e8fbb20e6c996b4b8cff87fbec6
DIFF: 
https://github.com/llvm/llvm-project/commit/98390ccb80569e8fbb20e6c996b4b8cff87fbec6.diff

LOG: [Clang] Reset FP options before function instantiations

Previously function template instantiations occurred with FP options
that were in effect at the end of translation unit. It was a problem
for late template parsing as these FP options were used as attributes of
AST nodes and may result in crash. To fix it FP options are set to the
state of the point of template definition.

Differential Revision: https://reviews.llvm.org/D143241

Added: 
    

Modified: 
    clang/include/clang/Sema/Sema.h
    clang/lib/Parse/ParseTemplate.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/test/CodeGen/fp-template.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 55d1dcf6ee0c26..35bd3e253f668c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -710,6 +710,12 @@ class Sema final {
     return result;
   }
 
+  void resetFPOptions(FPOptions FPO) {
+    CurFPFeatures = FPO;
+    FpPragmaStack.Stack.clear();
+    FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
+  }
+
   // RAII object to push / pop sentinel slots for all MS #pragma stacks.
   // Actions should be performed only if we enter / exit a C++ method body.
   class PragmaStackSentinelRAII {
@@ -14001,6 +14007,8 @@ struct LateParsedTemplate {
   CachedTokens Toks;
   /// The template function declaration to be late parsed.
   Decl *D;
+  /// Floating-point options in the point of definition.
+  FPOptions FPO;
 };
 
 template <>

diff  --git a/clang/lib/Parse/ParseTemplate.cpp 
b/clang/lib/Parse/ParseTemplate.cpp
index d2e8a81ad521a9..776c66b436472e 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1742,6 +1742,10 @@ void 
Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
       Actions.PushDeclContext(Actions.getCurScope(), DC);
   }
 
+  // Parsing should occur with empty FP pragma stack and FP options used in the
+  // point of the template definition.
+  Actions.resetFPOptions(LPT.FPO);
+
   assert(!LPT.Toks.empty() && "Empty body!");
 
   // Append the current token at the end of the new token stream so that it

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 063ddb418c4314..cb94edf67af594 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -11342,6 +11342,7 @@ void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, 
Decl *FnD,
   // Take tokens to avoid allocations
   LPT->Toks.swap(Toks);
   LPT->D = FnD;
+  LPT->FPO = getCurFPFeatures();
   LateParsedTemplateMap.insert(std::make_pair(FD, std::move(LPT)));
 
   FD->setLateTemplateParsed(true);

diff  --git a/clang/test/CodeGen/fp-template.cpp 
b/clang/test/CodeGen/fp-template.cpp
index 9e0fc0555e3365..e0ea8e4d12ad34 100644
--- a/clang/test/CodeGen/fp-template.cpp
+++ b/clang/test/CodeGen/fp-template.cpp
@@ -15,4 +15,40 @@ float func_01(float x, float y) {
 // CHECK-SAME:  (float noundef %{{.*}}, float noundef %{{.*}}) 
#[[ATTR01:[0-9]+]]{{.*}} {
 // CHECK:       call float @llvm.experimental.constrained.fadd.f32
 
+
+template <typename Ty>
+Ty templ_02(Ty x, Ty y) {
+  return x + y;
+}
+
+#pragma STDC FENV_ROUND FE_UPWARD
+
+template <typename Ty>
+Ty templ_03(Ty x, Ty y) {
+  return x - y;
+}
+
+#pragma STDC FENV_ROUND FE_TONEAREST
+
+float func_02(float x, float y) {
+  return templ_02(x, y);
+}
+
+// CHECK-LABEL: define {{.*}} float @_Z8templ_02IfET_S0_S0_
+// CHECK:       %add = fadd float %0, %1
+
+float func_03(float x, float y) {
+  return templ_03(x, y);
+}
+
+// CHECK-LABEL: define {{.*}} float @_Z8templ_03IfET_S0_S0_
+// CHECK:       call float @llvm.experimental.constrained.fsub.f32({{.*}}, 
metadata !"round.upward", metadata !"fpexcept.ignore")
+
+
+// This pragma sets non-default rounding mode before delayed parsing occurs. It
+// is used to check that the parsing uses FP options defined by command line
+// options or by pragma before the template definition but not by this pragma.
+#pragma STDC FENV_ROUND FE_TOWARDZERO
+
+
 // CHECK: attributes #[[ATTR01]] = { {{.*}}strictfp


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to