[clang] 2e90370 - [Clang] Reset FP options before function instantiations

Serge Pavlov via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 5 02:35:22 PDT 2023


Author: Serge Pavlov
Date: 2023-07-05T16:34:19+07:00
New Revision: 2e903709de003dc6ae980197f4a0850a158dd9b8

URL: https://github.com/llvm/llvm-project/commit/2e903709de003dc6ae980197f4a0850a158dd9b8
DIFF: https://github.com/llvm/llvm-project/commit/2e903709de003dc6ae980197f4a0850a158dd9b8.diff

LOG: [Clang] Reset FP options before function instantiations

This is recommit of 98390ccb80569e8fbb20e6c996b4b8cff87fbec6, reverted
in 82a3969d710f5fb7a2ee4c9afadb648653923fef, because it caused
https://github.com/llvm/llvm-project/issues/63542. Although the problem
described in the issue is independent of the reverted patch, fail of
PCH/late-parsed-instantiations.cpp indeed obseved on PowerPC and is
likely to be caused by wrong serialization of `LateParsedTemplate`
objects. In this patch the serialization is fixed.

Original commit message is below.

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/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTWriter.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 eed23e5ba99c89..aa4fc8947cbe7d 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 {
@@ -14028,6 +14034,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 7ef99b4bfcaf54..a1f0f5732b2b77 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -11377,6 +11377,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/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 78f718533bd55c..b989ff2a9c95c4 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -8606,6 +8606,7 @@ void ASTReader::ReadLateParsedTemplates(
 
       auto LT = std::make_unique<LateParsedTemplate>();
       LT->D = GetLocalDecl(*FMod, LateParsed[Idx++]);
+      LT->FPO = FPOptions::getFromOpaqueInt(LateParsed[Idx++]);
 
       ModuleFile *F = getOwningModuleFile(LT->D);
       assert(F && "No module");

diff  --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index e2dec17f7cae77..f4389ecd7629a1 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4278,6 +4278,7 @@ void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
     LateParsedTemplate &LPT = *LPTMapEntry.second;
     AddDeclRef(FD, Record);
     AddDeclRef(LPT.D, Record);
+    Record.push_back(LPT.FPO.getAsOpaqueInt());
     Record.push_back(LPT.Toks.size());
 
     for (const auto &Tok : LPT.Toks) {

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


        


More information about the cfe-commits mailing list