Skip to content

Commit f6b7a85

Browse files
author
git apple-llvm automerger
committed
Merge commit 'a633da5391b0' from llvm.org/master into apple/master
2 parents 6d0d2d1 + a633da5 commit f6b7a85

File tree

10 files changed

+188
-7
lines changed

10 files changed

+188
-7
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,12 @@ def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">,
11361136
def warn_stdc_fenv_access_not_supported :
11371137
Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
11381138
InGroup<UnknownPragmas>;
1139+
def warn_stdc_fenv_round_not_supported :
1140+
Warning<"pragma STDC FENV_ROUND is not supported">,
1141+
InGroup<UnknownPragmas>;
1142+
def warn_stdc_unknown_rounding_mode : Warning<
1143+
"invalid or unsupported rounding mode in '#pragma STDC FENV_ROUND' - ignored">,
1144+
InGroup<IgnoredPragmas>;
11391145
// - #pragma comment
11401146
def err_pragma_comment_malformed : Error<
11411147
"pragma comment requires parenthesized identifier and optional string">;

clang/include/clang/Basic/TokenKinds.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,11 @@ PRAGMA_ANNOTATION(pragma_fp_contract)
831831
// handles them.
832832
PRAGMA_ANNOTATION(pragma_fenv_access)
833833

834+
// Annotation for #pragma STDC FENV_ROUND
835+
// The lexer produces these so that they only take effect when the parser
836+
// handles them.
837+
PRAGMA_ANNOTATION(pragma_fenv_round)
838+
834839
// Annotation for #pragma float_control
835840
// The lexer produces these so that they only take effect when the parser
836841
// handles them.

clang/include/clang/Parse/Parser.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ class Parser : public CodeCompletionHandler {
202202
std::unique_ptr<PragmaHandler> UnrollAndJamHintHandler;
203203
std::unique_ptr<PragmaHandler> NoUnrollAndJamHintHandler;
204204
std::unique_ptr<PragmaHandler> FPHandler;
205-
std::unique_ptr<PragmaHandler> STDCFENVHandler;
205+
std::unique_ptr<PragmaHandler> STDCFenvAccessHandler;
206+
std::unique_ptr<PragmaHandler> STDCFenvRoundHandler;
206207
std::unique_ptr<PragmaHandler> STDCCXLIMITHandler;
207208
std::unique_ptr<PragmaHandler> STDCUnknownHandler;
208209
std::unique_ptr<PragmaHandler> AttributePragmaHandler;
@@ -745,6 +746,10 @@ class Parser : public CodeCompletionHandler {
745746
/// #pragma STDC FENV_ACCESS...
746747
void HandlePragmaFEnvAccess();
747748

749+
/// Handle the annotation token produced for
750+
/// #pragma STDC FENV_ROUND...
751+
void HandlePragmaFEnvRound();
752+
748753
/// Handle the annotation token produced for
749754
/// #pragma float_control
750755
void HandlePragmaFloatControl();

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9817,7 +9817,7 @@ class Sema final {
98179817
/// \#pragma STDC FENV_ACCESS
98189818
void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
98199819

9820-
/// Called to set rounding mode for floating point operations.
9820+
/// Called to set constant rounding mode for floating point operations.
98219821
void setRoundingMode(SourceLocation Loc, llvm::RoundingMode);
98229822

98239823
/// Called to set exception behavior for floating point operations.

clang/lib/Parse/ParsePragma.cpp

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,14 @@ struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
135135
}
136136
};
137137

138+
/// Handler for "\#pragma STDC FENV_ROUND ...".
139+
struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
140+
PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
141+
142+
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
143+
Token &Tok) override;
144+
};
145+
138146
/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
139147
struct PragmaSTDC_UnknownHandler : public PragmaHandler {
140148
PragmaSTDC_UnknownHandler() = default;
@@ -312,8 +320,11 @@ void Parser::initializePragmaHandlers() {
312320
FPContractHandler = std::make_unique<PragmaFPContractHandler>();
313321
PP.AddPragmaHandler("STDC", FPContractHandler.get());
314322

315-
STDCFENVHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
316-
PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
323+
STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
324+
PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
325+
326+
STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
327+
PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
317328

318329
STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
319330
PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
@@ -485,8 +496,11 @@ void Parser::resetPragmaHandlers() {
485496
PP.RemovePragmaHandler("STDC", FPContractHandler.get());
486497
FPContractHandler.reset();
487498

488-
PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
489-
STDCFENVHandler.reset();
499+
PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
500+
STDCFenvAccessHandler.reset();
501+
502+
PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
503+
STDCFenvRoundHandler.reset();
490504

491505
PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
492506
STDCCXLIMITHandler.reset();
@@ -697,6 +711,14 @@ void Parser::HandlePragmaFEnvAccess() {
697711
Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
698712
}
699713

714+
void Parser::HandlePragmaFEnvRound() {
715+
assert(Tok.is(tok::annot_pragma_fenv_round));
716+
auto RM = static_cast<llvm::RoundingMode>(
717+
reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
718+
719+
SourceLocation PragmaLoc = ConsumeAnnotationToken();
720+
Actions.setRoundingMode(PragmaLoc, RM);
721+
}
700722

701723
StmtResult Parser::HandlePragmaCaptured()
702724
{
@@ -2929,6 +2951,56 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP,
29292951
/*DisableMacroExpansion=*/false, /*IsReinject=*/false);
29302952
}
29312953

2954+
void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
2955+
PragmaIntroducer Introducer,
2956+
Token &Tok) {
2957+
Token PragmaName = Tok;
2958+
SmallVector<Token, 1> TokenList;
2959+
2960+
PP.Lex(Tok);
2961+
if (Tok.isNot(tok::identifier)) {
2962+
PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2963+
<< PragmaName.getIdentifierInfo()->getName();
2964+
return;
2965+
}
2966+
IdentifierInfo *II = Tok.getIdentifierInfo();
2967+
2968+
auto RM =
2969+
llvm::StringSwitch<llvm::RoundingMode>(II->getName())
2970+
.Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
2971+
.Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
2972+
.Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
2973+
.Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
2974+
.Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
2975+
.Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
2976+
.Default(llvm::RoundingMode::Invalid);
2977+
if (RM == llvm::RoundingMode::Invalid) {
2978+
PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
2979+
return;
2980+
}
2981+
PP.Lex(Tok);
2982+
2983+
if (Tok.isNot(tok::eod)) {
2984+
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2985+
<< "STDC FENV_ROUND";
2986+
return;
2987+
}
2988+
2989+
// Until the pragma is fully implemented, issue a warning.
2990+
PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
2991+
2992+
MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2993+
1);
2994+
Toks[0].startToken();
2995+
Toks[0].setKind(tok::annot_pragma_fenv_round);
2996+
Toks[0].setLocation(Tok.getLocation());
2997+
Toks[0].setAnnotationEndLoc(Tok.getLocation());
2998+
Toks[0].setAnnotationValue(
2999+
reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3000+
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3001+
/*IsReinject=*/false);
3002+
}
3003+
29323004
void Parser::HandlePragmaFP() {
29333005
assert(Tok.is(tok::annot_pragma_fp));
29343006
auto *AnnotValue =

clang/lib/Parse/ParseStmt.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,12 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
369369
HandlePragmaFEnvAccess();
370370
return StmtEmpty();
371371

372+
case tok::annot_pragma_fenv_round:
373+
ProhibitAttributes(Attrs);
374+
Diag(Tok, diag::err_pragma_file_or_compound_scope) << "STDC FENV_ROUND";
375+
ConsumeAnnotationToken();
376+
return StmtError();
377+
372378
case tok::annot_pragma_float_control:
373379
ProhibitAttributes(Attrs);
374380
Diag(Tok, diag::err_pragma_file_or_compound_scope) << "float_control";
@@ -943,6 +949,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() {
943949
case tok::annot_pragma_fenv_access:
944950
HandlePragmaFEnvAccess();
945951
break;
952+
case tok::annot_pragma_fenv_round:
953+
HandlePragmaFEnvRound();
954+
break;
946955
case tok::annot_pragma_float_control:
947956
HandlePragmaFloatControl();
948957
break;

clang/lib/Parse/Parser.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
791791
case tok::annot_pragma_fenv_access:
792792
HandlePragmaFEnvAccess();
793793
return nullptr;
794+
case tok::annot_pragma_fenv_round:
795+
HandlePragmaFEnvRound();
796+
return nullptr;
794797
case tok::annot_pragma_float_control:
795798
HandlePragmaFloatControl();
796799
return nullptr;

clang/lib/Sema/SemaAttr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,11 @@ void Sema::ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled) {
979979
}
980980

981981
void Sema::setRoundingMode(SourceLocation Loc, llvm::RoundingMode FPR) {
982+
// C2x: 7.6.2p3 If the FE_DYNAMIC mode is specified and FENV_ACCESS is "off",
983+
// the translator may assume that the default rounding mode is in effect.
984+
if (FPR == llvm::RoundingMode::Dynamic && !CurFPFeatures.getAllowFEnvAccess())
985+
FPR = llvm::RoundingMode::NearestTiesToEven;
986+
982987
FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides();
983988
NewFPFeatures.setRoundingModeOverride(FPR);
984989
FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures);

clang/test/AST/ast-dump-fpfeatures.cpp

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,69 @@ float func_03(float x) {
3434
// CHECK-NEXT: ParmVarDecl {{.*}} x 'float'
3535
// CHECK-NEXT: CompoundStmt
3636
// CHECK-NEXT: ReturnStmt
37-
// CHECK-NEXT: CallExpr {{.*}} FPContractMode=0
37+
// CHECK-NEXT: CallExpr {{.*}} FPContractMode=0
38+
39+
40+
41+
42+
#pragma STDC FENV_ROUND FE_DOWNWARD
43+
44+
float func_10(float x, float y) {
45+
return x + y;
46+
}
47+
48+
// CHECK-LABEL: FunctionDecl {{.*}} func_10 'float (float, float)'
49+
// CHECK: BinaryOperator {{.*}} 'float' '+' RoundingMode=3
50+
51+
float func_11(float x, float y) {
52+
if (x < 0) {
53+
#pragma STDC FENV_ROUND FE_UPWARD
54+
return x + y;
55+
}
56+
return x - y;
57+
}
58+
59+
// CHECK-LABEL: FunctionDecl {{.*}} func_11 'float (float, float)'
60+
// CHECK: BinaryOperator {{.*}} 'float' '+' RoundingMode=2
61+
// CHECK: BinaryOperator {{.*}} 'float' '-' RoundingMode=3
62+
63+
64+
#pragma STDC FENV_ROUND FE_DYNAMIC
65+
66+
float func_12(float x, float y) {
67+
return x + y;
68+
}
69+
70+
// CHECK-LABEL: FunctionDecl {{.*}} func_12 'float (float, float)'
71+
// CHECK: BinaryOperator {{.*}} 'float' '+' RoundingMode=1
72+
73+
#pragma STDC FENV_ROUND FE_TONEAREST
74+
75+
float func_13(float x, float y) {
76+
return x + y;
77+
}
78+
79+
// CHECK-LABEL: FunctionDecl {{.*}} func_13 'float (float, float)'
80+
// CHECK: BinaryOperator {{.*}} 'float' '+' RoundingMode=1
81+
82+
83+
template <typename T>
84+
T func_14(T x, T y) {
85+
#pragma STDC FENV_ROUND FE_TOWARDZERO
86+
return x + y;
87+
}
88+
89+
float func_15(float x, float y) {
90+
#pragma STDC FPENV_ROUND FE_DOWNWARD
91+
return func_14(x, y);
92+
}
93+
94+
// CHECK-LABEL: FunctionTemplateDecl {{.*}} func_14
95+
// CHECK: FunctionDecl {{.*}} func_14 'T (T, T)'
96+
// CHECK: CompoundStmt
97+
// CHECK-NEXT: ReturnStmt
98+
// CHECK-NEXT: BinaryOperator {{.*}} '+' RoundingMode=0
99+
// CHECK: FunctionDecl {{.*}} func_14 'float (float, float)'
100+
// CHECK: CompoundStmt
101+
// CHECK-NEXT: ReturnStmt
102+
// CHECK-NEXT: BinaryOperator {{.*}} 'float' '+' RoundingMode=0

clang/test/Parser/pragma-fenv_round.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -fsyntax-only -Wignored-pragmas -verify %s
2+
3+
#pragma STDC FENV_ROUND ON // expected-warning {{invalid or unsupported rounding mode}}
4+
5+
float func_01(int x, float y) {
6+
if (x)
7+
return y + 2;
8+
#pragma STDC FENV_ROUND FE_DOWNWARD // expected-error{{'#pragma STDC FENV_ROUND' can only appear at file scope or at the start of a compound statement}}
9+
// expected-warning@-1{{pragma STDC FENV_ROUND is not supported}}
10+
return x + y;
11+
}

0 commit comments

Comments
 (0)