// 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 };
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,
FPC_Fast
};
+ // TODO: merge FEnvAccessModeKind and FPContractModeKind
+ enum FEnvAccessModeKind {
+ FEA_Off,
+
+ FEA_On
+ };
+
+
public:
/// Set of enabled sanitizers.
SanitizerSet Sanitize;
/// Floating point control options
class FPOptions {
public:
- FPOptions() : fp_contract(LangOptions::FPC_Off) {}
+ FPOptions() : fp_contract(LangOptions::FPC_Off),
+ fenv_access(LangOptions::FEA_Off) {}
// Used for serializing.
explicit FPOptions(unsigned I)
- : fp_contract(static_cast<LangOptions::FPContractModeKind>(I)) {}
+ : fp_contract(static_cast<LangOptions::FPContractModeKind>(I & 3)),
+ fenv_access(static_cast<LangOptions::FEnvAccessModeKind>((I >> 2) & 1))
+ {}
explicit FPOptions(const LangOptions &LangOpts)
- : fp_contract(LangOpts.getDefaultFPContractMode()) {}
+ : fp_contract(LangOpts.getDefaultFPContractMode()),
+ fenv_access(LangOptions::FEA_Off) {}
+ // FIXME: Use getDefaultFEnvAccessMode() when available.
bool allowFPContractWithinStatement() const {
return fp_contract == LangOptions::FPC_On;
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.
// 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.
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();
/// \#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);
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);
}
};
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;
+ case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
+ FPC = LangOptions::FEA_Off;
+ break;
+ }
+
+ Actions.ActOnPragmaFEnvAccess(FPC);
+ ConsumeAnnotationToken();
+}
+
+
StmtResult Parser::HandlePragmaCaptured()
{
assert(Tok.is(tok::annot_pragma_captured));
ConsumeAnnotationToken();
return StmtError();
+ case tok::annot_pragma_fenv_access:
+ ProhibitAttributes(Attrs);
+ HandlePragmaFEnvAccess();
+ return StmtEmpty();
+
case tok::annot_pragma_opencl_extension:
ProhibitAttributes(Attrs);
HandlePragmaOpenCLExtension();
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;
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;
}
}
+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.