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 in most cases.

Reviewed by:	rsmith
Differential Revision:	https://reviews.llvm.org/D49865

llvm-svn: 339693
This commit is contained in:
Kevin P. Neal 2018-08-14 17:06:56 +00:00
parent ba74d1c4ea
commit 2c0bc8b7a3
9 changed files with 109 additions and 7 deletions

View File

@ -3269,7 +3269,7 @@ private:
// 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 };
@ -3448,6 +3448,12 @@ public:
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,

View File

@ -137,6 +137,14 @@ public:
FPC_Fast
};
// TODO: merge FEnvAccessModeKind and FPContractModeKind
enum FEnvAccessModeKind {
FEA_Off,
FEA_On
};
public:
/// Set of enabled sanitizers.
SanitizerSet Sanitize;
@ -262,14 +270,19 @@ public:
/// 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;
@ -289,12 +302,24 @@ public:
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.

View File

@ -780,6 +780,11 @@ ANNOTATION(pragma_redefine_extname)
// 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.

View File

@ -670,6 +670,10 @@ private:
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();

View File

@ -8434,6 +8434,10 @@ public:
/// \#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);

View File

@ -106,8 +106,19 @@ struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
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);
}
};
@ -604,6 +615,30 @@ void Parser::HandlePragmaFPContract() {
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));

View File

@ -348,6 +348,11 @@ Retry:
ConsumeAnnotationToken();
return StmtError();
case tok::annot_pragma_fenv_access:
ProhibitAttributes(Attrs);
HandlePragmaFEnvAccess();
return StmtEmpty();
case tok::annot_pragma_opencl_extension:
ProhibitAttributes(Attrs);
HandlePragmaOpenCLExtension();
@ -902,6 +907,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
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;

View File

@ -674,6 +674,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
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;

View File

@ -773,6 +773,18 @@ void Sema::ActOnPragmaFPContract(LangOptions::FPContractModeKind FPC) {
}
}
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.