Skip to content

Commit 412f6f7

Browse files
zahiraamhamphet
authored andcommitted
[NFC] Move warning from CodeGen to Sema. (llvm#107397)
This is a warning that wasn't associated with the source location. Moved it to Sema and changed the warning message to a more verbose one.
1 parent b30eaa8 commit 412f6f7

File tree

9 files changed

+89
-28
lines changed

9 files changed

+89
-28
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,23 @@ class ASTContext : public RefCountedBase<ASTContext> {
782782
const TargetInfo &getTargetInfo() const { return *Target; }
783783
const TargetInfo *getAuxTargetInfo() const { return AuxTarget; }
784784

785+
const QualType GetHigherPrecisionFPType(QualType ElementType) const {
786+
const auto *CurrentBT = cast<BuiltinType>(ElementType);
787+
switch (CurrentBT->getKind()) {
788+
case BuiltinType::Kind::Half:
789+
case BuiltinType::Kind::Float16:
790+
return FloatTy;
791+
case BuiltinType::Kind::Float:
792+
case BuiltinType::Kind::BFloat16:
793+
return DoubleTy;
794+
case BuiltinType::Kind::Double:
795+
return LongDoubleTy;
796+
default:
797+
return ElementType;
798+
}
799+
return ElementType;
800+
}
801+
785802
/// getIntTypeForBitwidth -
786803
/// sets integer QualTy according to specified details:
787804
/// bitwidth, signed/unsigned.

clang/include/clang/Basic/DiagnosticCommonKinds.td

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ def note_using : Note<"using">;
4545
def note_possibility : Note<"one possibility">;
4646
def note_also_found : Note<"also found">;
4747

48-
def warn_next_larger_fp_type_same_size_than_fp : Warning<
49-
"higher precision floating-point type size has the same size than "
50-
"floating-point type size">,
51-
InGroup<DiagGroup<"higher-precision-fp">>;
52-
5348
// Parse && Lex
5449

5550
let CategoryName = "Lexical or Preprocessor Issue" in {

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6800,6 +6800,12 @@ def warn_arc_lifetime_result_type : Warning<
68006800
"ARC %select{unused|__unsafe_unretained|__strong|__weak|__autoreleasing}0 "
68016801
"lifetime qualifier on return type is ignored">,
68026802
InGroup<IgnoredQualifiers>;
6803+
def warn_excess_precision_not_supported : Warning<
6804+
"excess precision is requested but the target does not support excess "
6805+
"precision which may result in observable differences in complex division "
6806+
"behavior%select{|, additional uses where the requested higher precision "
6807+
"cannot be honored were found but not diagnosed}0">,
6808+
InGroup<DiagGroup<"higher-precision-for-complex-division">>;
68036809

68046810
let CategoryName = "ARC Retain Cycle" in {
68056811

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7957,6 +7957,10 @@ class Sema final : public SemaBase {
79577957
/// Do an explicit extend of the given block pointer if we're in ARC.
79587958
void maybeExtendBlockObject(ExprResult &E);
79597959

7960+
std::vector<std::pair<QualType, unsigned>> ExcessPrecisionNotSatisfied;
7961+
SourceLocation LocationOfExcessPrecisionNotSatisfied;
7962+
void DiagnosePrecisionLossInComplexDivision();
7963+
79607964
private:
79617965
static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
79627966

clang/lib/CodeGen/CGExprComplex.cpp

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -288,28 +288,15 @@ class ComplexExprEmitter
288288
ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName,
289289
const BinOpInfo &Op);
290290

291-
QualType GetHigherPrecisionFPType(QualType ElementType) {
292-
const auto *CurrentBT = cast<BuiltinType>(ElementType);
293-
switch (CurrentBT->getKind()) {
294-
case BuiltinType::Kind::Float16:
295-
return CGF.getContext().FloatTy;
296-
case BuiltinType::Kind::Float:
297-
case BuiltinType::Kind::BFloat16:
298-
return CGF.getContext().DoubleTy;
299-
case BuiltinType::Kind::Double:
300-
return CGF.getContext().LongDoubleTy;
301-
default:
302-
return ElementType;
303-
}
304-
}
305-
306291
QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType,
307292
bool IsDivOpCode) {
308-
QualType HigherElementType = GetHigherPrecisionFPType(ElementType);
293+
ASTContext &Ctx = CGF.getContext();
294+
const QualType HigherElementType =
295+
Ctx.GetHigherPrecisionFPType(ElementType);
309296
const llvm::fltSemantics &ElementTypeSemantics =
310-
CGF.getContext().getFloatTypeSemantics(ElementType);
297+
Ctx.getFloatTypeSemantics(ElementType);
311298
const llvm::fltSemantics &HigherElementTypeSemantics =
312-
CGF.getContext().getFloatTypeSemantics(HigherElementType);
299+
Ctx.getFloatTypeSemantics(HigherElementType);
313300
// Check that the promoted type can handle the intermediate values without
314301
// overflowing. This can be interpreted as:
315302
// (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal) * 2 <=
@@ -320,10 +307,10 @@ class ComplexExprEmitter
320307
if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
321308
llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
322309
FPHasBeenPromoted = true;
323-
return CGF.getContext().getComplexType(HigherElementType);
310+
return Ctx.getComplexType(HigherElementType);
324311
} else {
325-
DiagnosticsEngine &Diags = CGF.CGM.getDiags();
326-
Diags.Report(diag::warn_next_larger_fp_type_same_size_than_fp);
312+
// The intermediate values can't be represented in the promoted type
313+
// without overflowing.
327314
return QualType();
328315
}
329316
}

clang/lib/Sema/Sema.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,7 @@ void Sema::ActOnEndOfTranslationUnit() {
12131213
DiagnoseUnterminatedPragmaAlignPack();
12141214
DiagnoseUnterminatedPragmaAttribute();
12151215
OpenMP().DiagnoseUnterminatedOpenMPDeclareTarget();
1216+
DiagnosePrecisionLossInComplexDivision();
12161217

12171218
// All delayed member exception specs should be checked or we end up accepting
12181219
// incompatible declarations.

clang/lib/Sema/SemaAttr.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,16 @@ void Sema::PrintPragmaAttributeInstantiationPoint() {
11801180
diag::note_pragma_attribute_applied_decl_here);
11811181
}
11821182

1183+
void Sema::DiagnosePrecisionLossInComplexDivision() {
1184+
for (auto &[Type, Num] : ExcessPrecisionNotSatisfied) {
1185+
assert(LocationOfExcessPrecisionNotSatisfied.isValid() &&
1186+
"expected a valid source location");
1187+
Diag(LocationOfExcessPrecisionNotSatisfied,
1188+
diag::warn_excess_precision_not_supported)
1189+
<< static_cast<bool>(Num);
1190+
}
1191+
}
1192+
11831193
void Sema::DiagnoseUnterminatedPragmaAttribute() {
11841194
if (PragmaAttributeStack.empty())
11851195
return;

clang/lib/Sema/SemaExpr.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15115,6 +15115,37 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
1511515115
DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr);
1511615116
}
1511715117

15118+
static void DetectPrecisionLossInComplexDivision(Sema &S, SourceLocation OpLoc,
15119+
Expr *Operand) {
15120+
if (auto *CT = Operand->getType()->getAs<ComplexType>()) {
15121+
QualType ElementType = CT->getElementType();
15122+
bool IsComplexRangePromoted = S.getLangOpts().getComplexRange() ==
15123+
LangOptions::ComplexRangeKind::CX_Promoted;
15124+
if (ElementType->isFloatingType() && IsComplexRangePromoted) {
15125+
ASTContext &Ctx = S.getASTContext();
15126+
QualType HigherElementType = Ctx.GetHigherPrecisionFPType(ElementType);
15127+
const llvm::fltSemantics &ElementTypeSemantics =
15128+
Ctx.getFloatTypeSemantics(ElementType);
15129+
const llvm::fltSemantics &HigherElementTypeSemantics =
15130+
Ctx.getFloatTypeSemantics(HigherElementType);
15131+
if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 >
15132+
llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
15133+
// Retain the location of the first use of higher precision type.
15134+
if (!S.LocationOfExcessPrecisionNotSatisfied.isValid())
15135+
S.LocationOfExcessPrecisionNotSatisfied = OpLoc;
15136+
for (auto &[Type, Num] : S.ExcessPrecisionNotSatisfied) {
15137+
if (Type == HigherElementType) {
15138+
Num++;
15139+
return;
15140+
}
15141+
}
15142+
S.ExcessPrecisionNotSatisfied.push_back(std::make_pair(
15143+
HigherElementType, S.ExcessPrecisionNotSatisfied.size()));
15144+
}
15145+
}
15146+
}
15147+
}
15148+
1511815149
ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
1511915150
tok::TokenKind Kind,
1512015151
Expr *LHSExpr, Expr *RHSExpr) {
@@ -15125,6 +15156,11 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
1512515156
// Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
1512615157
DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr);
1512715158

15159+
// Emit warnings if the requested higher precision type equal to the current
15160+
// type precision.
15161+
if (Kind == tok::TokenKind::slash)
15162+
DetectPrecisionLossInComplexDivision(*this, TokLoc, LHSExpr);
15163+
1512815164
return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr);
1512915165
}
1513015166

clang/test/Sema/complex-arithmetic.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
// RUN: %clang_cc1 -verify %s
2-
// expected-no-diagnostics
1+
// RUN: %clang_cc1 -verify=no-diag %s
2+
// RUN: %clang_cc1 -complex-range=promoted -triple x86_64-unknown-linux \
3+
// RUN: -verify=no-diag %s
4+
// RUN: %clang_cc1 -complex-range=promoted -triple x86_64-unknown-windows \
5+
// RUN: -verify=div-precision %s
6+
// no-diag-no-diagnostics
37

48
// This tests evaluation of _Complex arithmetic at compile time.
59

@@ -21,6 +25,7 @@ void a() {
2125
EVALF((2. + 3i) + (4. + 5i), 6. + 8i);
2226
EVALF((2. + 3i) - (4. + 5i), -2. - 2i);
2327
EVALF((2. + 3i) * (4. + 5i), -7. + 22i);
28+
// div-precision-warning@+1 {{excess precision is requested but the target does not support excess precision which may result in observable differences in complex division behavior, additional uses where the requested higher precision cannot be honored were found but not diagnosed}}
2429
EVALF((2. + 3i) / (4. + 5i), .5609 + .0487i);
2530
}
2631

0 commit comments

Comments
 (0)