@@ -10602,6 +10602,45 @@ static void checkArithmeticNull(Sema &S, ExprResult &LHS, ExprResult &RHS,
1060210602 << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
1060310603}
1060410604
10605+ static void DetectPrecisionLossInComplexDivision(Sema &S, QualType DivisorTy,
10606+ SourceLocation OpLoc) {
10607+ // If the divisor is real, then this is real/real or complex/real division.
10608+ // Either way there can be no precision loss.
10609+ auto *CT = DivisorTy->getAs<ComplexType>();
10610+ if (!CT)
10611+ return;
10612+
10613+ QualType ElementType = CT->getElementType();
10614+ bool IsComplexRangePromoted = S.getLangOpts().getComplexRange() ==
10615+ LangOptions::ComplexRangeKind::CX_Promoted;
10616+ if (!ElementType->isFloatingType() || !IsComplexRangePromoted)
10617+ return;
10618+
10619+ ASTContext &Ctx = S.getASTContext();
10620+ QualType HigherElementType = Ctx.GetHigherPrecisionFPType(ElementType);
10621+ const llvm::fltSemantics &ElementTypeSemantics =
10622+ Ctx.getFloatTypeSemantics(ElementType);
10623+ const llvm::fltSemantics &HigherElementTypeSemantics =
10624+ Ctx.getFloatTypeSemantics(HigherElementType);
10625+
10626+ if ((llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 >
10627+ llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) ||
10628+ (HigherElementType == Ctx.LongDoubleTy &&
10629+ !Ctx.getTargetInfo().hasLongDoubleType())) {
10630+ // Retain the location of the first use of higher precision type.
10631+ if (!S.LocationOfExcessPrecisionNotSatisfied.isValid())
10632+ S.LocationOfExcessPrecisionNotSatisfied = OpLoc;
10633+ for (auto &[Type, Num] : S.ExcessPrecisionNotSatisfied) {
10634+ if (Type == HigherElementType) {
10635+ Num++;
10636+ return;
10637+ }
10638+ }
10639+ S.ExcessPrecisionNotSatisfied.push_back(std::make_pair(
10640+ HigherElementType, S.ExcessPrecisionNotSatisfied.size()));
10641+ }
10642+ }
10643+
1060510644static void DiagnoseDivisionSizeofPointerOrArray(Sema &S, Expr *LHS, Expr *RHS,
1060610645 SourceLocation Loc) {
1060710646 const auto *LUE = dyn_cast<UnaryExprOrTypeTraitExpr>(LHS);
@@ -10696,6 +10735,7 @@ QualType Sema::CheckMultiplyDivideOperands(ExprResult &LHS, ExprResult &RHS,
1069610735 if (compType.isNull() || !compType->isArithmeticType())
1069710736 return InvalidOperands(Loc, LHS, RHS);
1069810737 if (IsDiv) {
10738+ DetectPrecisionLossInComplexDivision(*this, RHS.get()->getType(), Loc);
1069910739 DiagnoseBadDivideOrRemainderValues(*this, LHS, RHS, Loc, IsDiv);
1070010740 DiagnoseDivisionSizeofPointerOrArray(*this, LHS.get(), RHS.get(), Loc);
1070110741 }
@@ -15347,39 +15387,6 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
1534715387 DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr);
1534815388}
1534915389
15350- static void DetectPrecisionLossInComplexDivision(Sema &S, SourceLocation OpLoc,
15351- Expr *Operand) {
15352- if (auto *CT = Operand->getType()->getAs<ComplexType>()) {
15353- QualType ElementType = CT->getElementType();
15354- bool IsComplexRangePromoted = S.getLangOpts().getComplexRange() ==
15355- LangOptions::ComplexRangeKind::CX_Promoted;
15356- if (ElementType->isFloatingType() && IsComplexRangePromoted) {
15357- ASTContext &Ctx = S.getASTContext();
15358- QualType HigherElementType = Ctx.GetHigherPrecisionFPType(ElementType);
15359- const llvm::fltSemantics &ElementTypeSemantics =
15360- Ctx.getFloatTypeSemantics(ElementType);
15361- const llvm::fltSemantics &HigherElementTypeSemantics =
15362- Ctx.getFloatTypeSemantics(HigherElementType);
15363- if ((llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 >
15364- llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) ||
15365- (HigherElementType == Ctx.LongDoubleTy &&
15366- !Ctx.getTargetInfo().hasLongDoubleType())) {
15367- // Retain the location of the first use of higher precision type.
15368- if (!S.LocationOfExcessPrecisionNotSatisfied.isValid())
15369- S.LocationOfExcessPrecisionNotSatisfied = OpLoc;
15370- for (auto &[Type, Num] : S.ExcessPrecisionNotSatisfied) {
15371- if (Type == HigherElementType) {
15372- Num++;
15373- return;
15374- }
15375- }
15376- S.ExcessPrecisionNotSatisfied.push_back(std::make_pair(
15377- HigherElementType, S.ExcessPrecisionNotSatisfied.size()));
15378- }
15379- }
15380- }
15381- }
15382-
1538315390ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
1538415391 tok::TokenKind Kind,
1538515392 Expr *LHSExpr, Expr *RHSExpr) {
@@ -15390,11 +15397,6 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
1539015397 // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0"
1539115398 DiagnoseBinOpPrecedence(*this, Opc, TokLoc, LHSExpr, RHSExpr);
1539215399
15393- // Emit warnings if the requested higher precision type equal to the current
15394- // type precision.
15395- if (Kind == tok::TokenKind::slash)
15396- DetectPrecisionLossInComplexDivision(*this, TokLoc, LHSExpr);
15397-
1539815400 BuiltinCountedByRefKind K =
1539915401 BinaryOperator::isAssignmentOp(Opc) ? AssignmentKind : BinaryExprKind;
1540015402
@@ -21111,11 +21113,15 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
2111121113 const bool IsTypeAliasTemplateDecl = isa<TypeAliasTemplateDecl>(Temp);
2111221114
2111321115 NestedNameSpecifier *NNS = ULE->getQualifierLoc().getNestedNameSpecifier();
21114- TemplateName TN(dyn_cast<TemplateDecl>(Temp));
21115- if (TN.isNull())
21116+ // FIXME: AssumedTemplate is not very appropriate for error recovery here,
21117+ // as it models only the unqualified-id case, where this case can clearly be
21118+ // qualified. Thus we can't just qualify an assumed template.
21119+ TemplateName TN;
21120+ if (auto *TD = dyn_cast<TemplateDecl>(Temp))
21121+ TN = Context.getQualifiedTemplateName(NNS, ULE->hasTemplateKeyword(),
21122+ TemplateName(TD));
21123+ else
2111621124 TN = Context.getAssumedTemplateName(NameInfo.getName());
21117- TN = Context.getQualifiedTemplateName(NNS,
21118- /*TemplateKeyword=*/true, TN);
2111921125
2112021126 Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_type_template)
2112121127 << TN << ULE->getSourceRange() << IsTypeAliasTemplateDecl;
0 commit comments