kpn created this revision.
kpn added reviewers: rsmith, craig.topper, hfinkel.
Herald added a subscriber: cfe-commits.

We have in place support for parsing #pragma FENV_ACCESS, but that information 
is then discarded with a warning to the user that we don't support it.

This patch gets us one step closer by getting the info down into the AST.


Repository:
  rC Clang

https://reviews.llvm.org/D49865

Files:
  include/clang/AST/Expr.h
  include/clang/Basic/LangOptions.h
  include/clang/Basic/TokenKinds.def
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/Parse/ParsePragma.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaAttr.cpp

Index: lib/Sema/SemaAttr.cpp
===================================================================
--- lib/Sema/SemaAttr.cpp
+++ lib/Sema/SemaAttr.cpp
@@ -773,6 +773,18 @@
   }
 }
 
+void Sema::ActOnPragmaFENVAccess(LangOptions::FENVAccessModeKind FPC) {
+  switch (FPC) {
+  case LangOptions::FEA_On:
+    FPFeatures.setAllowFENVAccess();
+    break;
+  case LangOptions::FEA_Off:
+    FPFeatures.setDisallowFENVAccess();
+    break;
+  }
+}
+
+
 void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
                                        SourceLocation Loc) {
   // Visibility calculations will consider the namespace's visibility.
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -674,6 +674,9 @@
   case tok::annot_pragma_fp_contract:
     HandlePragmaFPContract();
     return nullptr;
+  case tok::annot_pragma_fenv_access:
+    HandlePragmaFENVAccess();
+    return nullptr;
   case tok::annot_pragma_fp:
     HandlePragmaFP();
     break;
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -348,6 +348,12 @@
     ConsumeAnnotationToken();
     return StmtError();
 
+  case tok::annot_pragma_fenv_access:
+    ProhibitAttributes(Attrs);
+    //Diag(Tok, diag::err_pragma_fp_scope);
+    HandlePragmaFENVAccess();
+    return StmtEmpty();
+
   case tok::annot_pragma_opencl_extension:
     ProhibitAttributes(Attrs);
     HandlePragmaOpenCLExtension();
@@ -914,6 +920,9 @@
     case tok::annot_pragma_fp:
       HandlePragmaFP();
       break;
+    case tok::annot_pragma_fenv_access:
+      HandlePragmaFENVAccess();
+      break;
     case tok::annot_pragma_ms_pointers_to_members:
       HandlePragmaMSPointersToMembers();
       break;
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp
+++ lib/Parse/ParsePragma.cpp
@@ -106,8 +106,19 @@
     tok::OnOffSwitch OOS;
     if (PP.LexOnOffSwitch(OOS))
      return;
-    if (OOS == tok::OOS_ON)
+    if (OOS == tok::OOS_ON) {
       PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
+
+      MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
+                                1);
+      Toks[0].startToken();
+      Toks[0].setKind(tok::annot_pragma_fenv_access);
+      Toks[0].setLocation(Tok.getLocation());
+      Toks[0].setAnnotationEndLoc(Tok.getLocation());
+      Toks[0].setAnnotationValue(reinterpret_cast<void*>(
+                               static_cast<uintptr_t>(OOS)));
+      PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
+    }
   }
 };
 
@@ -591,6 +602,32 @@
   ConsumeAnnotationToken();
 }
 
+void Parser::HandlePragmaFENVAccess() {
+  assert(Tok.is(tok::annot_pragma_fenv_access));
+  tok::OnOffSwitch OOS =
+    static_cast<tok::OnOffSwitch>(
+    reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
+
+  LangOptions::FENVAccessModeKind FPC;
+  switch (OOS) {
+  case tok::OOS_ON:
+    FPC = LangOptions::FEA_On;
+    break;
+  case tok::OOS_OFF:
+    FPC = LangOptions::FEA_Off;
+    break;
+#if NOTYET // FIXME: Add this cli option when it makes sense.
+  case tok::OOS_DEFAULT:
+    FPC = getLangOpts().getDefaultFENVAccessMode();
+    break;
+#endif
+  }
+
+  Actions.ActOnPragmaFENVAccess(FPC);
+  ConsumeAnnotationToken();
+}
+
+
 StmtResult Parser::HandlePragmaCaptured()
 {
   assert(Tok.is(tok::annot_pragma_captured));
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -8433,6 +8433,10 @@
   /// \#pragma clang fp contract
   void ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC);
 
+  /// ActOnPragmaFENVAccess - Called on well formed
+  /// \#pragma STDC FENV_ACCESS
+  void ActOnPragmaFENVAccess(LangOptions::FENVAccessModeKind FPC);
+
   /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
   /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
   void AddAlignmentAttributesForRecord(RecordDecl *RD);
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -668,6 +668,10 @@
   void HandlePragmaFPContract();
 
   /// Handle the annotation token produced for
+  /// #pragma STDC FENV_ACCESS...
+  void HandlePragmaFENVAccess();
+
+  /// \brief Handle the annotation token produced for
   /// #pragma clang fp ...
   void HandlePragmaFP();
 
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def
+++ include/clang/Basic/TokenKinds.def
@@ -779,6 +779,11 @@
 // handles them.
 ANNOTATION(pragma_fp_contract)
 
+// Annotation for #pragma STDC FENV_ACCESS
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_fenv_access)
+
 // Annotation for #pragma pointers_to_members...
 // The lexer produces these so that they only take effect when the parser
 // handles them.
Index: include/clang/Basic/LangOptions.h
===================================================================
--- include/clang/Basic/LangOptions.h
+++ include/clang/Basic/LangOptions.h
@@ -137,6 +137,14 @@
     FPC_Fast
   };
 
+  // TODO: merge FENVAccessModeKind and FPContractModeKind
+  enum FENVAccessModeKind {
+    FEA_Off,
+
+    FEA_On
+  };
+
+
 public:
   /// Set of enabled sanitizers.
   SanitizerSet Sanitize;
@@ -289,12 +297,24 @@
 
   void setDisallowFPContract() { fp_contract = LangOptions::FPC_Off; }
 
+  bool allowFENVAccess() const {
+    return fenv_access == LangOptions::FEA_On;
+  }
+
+  void setAllowFENVAccess() {
+    fenv_access = LangOptions::FEA_On;
+  }
+
+  void setDisallowFENVAccess() { fenv_access = LangOptions::FEA_Off; }
+
   /// Used to serialize this.
-  unsigned getInt() const { return fp_contract; }
+  unsigned getInt() const { return fp_contract | (fenv_access << 2); }
 
 private:
-  /// Adjust BinaryOperator::FPFeatures to match the bit-field size of this.
+  /// Adjust BinaryOperator::FPFeatures to match the total bit-field size 
+  /// of these two.
   unsigned fp_contract : 2;
+  unsigned fenv_access : 1;
 };
 
 /// Describes the kind of translation unit being processed.
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -3083,7 +3083,7 @@
 
   // This is only meaningful for operations on floating point types and 0
   // otherwise.
-  unsigned FPFeatures : 2;
+  unsigned FPFeatures : 3;
   SourceLocation OpLoc;
 
   enum { LHS, RHS, END_EXPR };
@@ -3254,6 +3254,12 @@
     return FPOptions(FPFeatures).allowFPContractWithinStatement();
   }
 
+  // Get the FENV_ACCESS status of this operator. Only meaningful for
+  // operations on floating point types.
+  bool isFENVAccessOn() const {
+    return FPOptions(FPFeatures).allowFENVAccess();
+  }
+
 protected:
   BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
                  ExprValueKind VK, ExprObjectKind OK,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to