|
15 | 15 | #include "UsedDeclVisitor.h"
|
16 | 16 | #include "clang/AST/ASTConsumer.h"
|
17 | 17 | #include "clang/AST/ASTContext.h"
|
| 18 | +#include "clang/AST/ASTDiagnostic.h" |
18 | 19 | #include "clang/AST/ASTLambda.h"
|
19 | 20 | #include "clang/AST/ASTMutationListener.h"
|
20 | 21 | #include "clang/AST/CXXInheritance.h"
|
@@ -1568,15 +1569,91 @@ void Sema::checkEnumArithmeticConversions(Expr *LHS, Expr *RHS,
|
1568 | 1569 | }
|
1569 | 1570 | }
|
1570 | 1571 |
|
| 1572 | +static void CheckUnicodeArithmeticConversions(Sema &SemaRef, Expr *LHS, |
| 1573 | + Expr *RHS, SourceLocation Loc, |
| 1574 | + ArithConvKind ACK) { |
| 1575 | + QualType LHSType = LHS->getType().getUnqualifiedType(); |
| 1576 | + QualType RHSType = RHS->getType().getUnqualifiedType(); |
| 1577 | + |
| 1578 | + if (!SemaRef.getLangOpts().CPlusPlus || !LHSType->isUnicodeCharacterType() || |
| 1579 | + !RHSType->isUnicodeCharacterType()) |
| 1580 | + return; |
| 1581 | + |
| 1582 | + if (ACK == ArithConvKind::Comparison) { |
| 1583 | + if (SemaRef.getASTContext().hasSameType(LHSType, RHSType)) |
| 1584 | + return; |
| 1585 | + |
| 1586 | + auto IsSingleCodeUnitCP = [](const QualType &T, const llvm::APSInt &Value) { |
| 1587 | + if (T->isChar8Type()) |
| 1588 | + return llvm::IsSingleCodeUnitUTF8Codepoint(Value.getExtValue()); |
| 1589 | + if (T->isChar16Type()) |
| 1590 | + return llvm::IsSingleCodeUnitUTF16Codepoint(Value.getExtValue()); |
| 1591 | + assert(T->isChar32Type()); |
| 1592 | + return llvm::IsSingleCodeUnitUTF32Codepoint(Value.getExtValue()); |
| 1593 | + }; |
| 1594 | + |
| 1595 | + Expr::EvalResult LHSRes, RHSRes; |
| 1596 | + bool LHSSuccess = LHS->EvaluateAsInt(LHSRes, SemaRef.getASTContext(), |
| 1597 | + Expr::SE_AllowSideEffects, |
| 1598 | + SemaRef.isConstantEvaluatedContext()); |
| 1599 | + bool RHSuccess = RHS->EvaluateAsInt(RHSRes, SemaRef.getASTContext(), |
| 1600 | + Expr::SE_AllowSideEffects, |
| 1601 | + SemaRef.isConstantEvaluatedContext()); |
| 1602 | + |
| 1603 | + // Don't warn if the one known value is a representable |
| 1604 | + // in the type of both expressions. |
| 1605 | + if (LHSSuccess != RHSuccess) { |
| 1606 | + Expr::EvalResult &Res = LHSSuccess ? LHSRes : RHSRes; |
| 1607 | + if (IsSingleCodeUnitCP(LHSType, Res.Val.getInt()) && |
| 1608 | + IsSingleCodeUnitCP(RHSType, Res.Val.getInt())) |
| 1609 | + return; |
| 1610 | + } |
| 1611 | + |
| 1612 | + if (!LHSSuccess || !RHSuccess) { |
| 1613 | + SemaRef.Diag(Loc, diag::warn_comparison_unicode_mixed_types) |
| 1614 | + << LHS->getSourceRange() << RHS->getSourceRange() << LHSType |
| 1615 | + << RHSType; |
| 1616 | + return; |
| 1617 | + } |
| 1618 | + |
| 1619 | + llvm::APSInt LHSValue(32); |
| 1620 | + LHSValue = LHSRes.Val.getInt(); |
| 1621 | + llvm::APSInt RHSValue(32); |
| 1622 | + RHSValue = RHSRes.Val.getInt(); |
| 1623 | + |
| 1624 | + bool LHSSafe = IsSingleCodeUnitCP(LHSType, LHSValue); |
| 1625 | + bool RHSSafe = IsSingleCodeUnitCP(RHSType, RHSValue); |
| 1626 | + if (LHSSafe && RHSSafe) |
| 1627 | + return; |
| 1628 | + |
| 1629 | + SemaRef.Diag(Loc, diag::warn_comparison_unicode_mixed_types_constant) |
| 1630 | + << LHS->getSourceRange() << RHS->getSourceRange() << LHSType << RHSType |
| 1631 | + << FormatUTFCodeUnitAsCodepoint(LHSValue.getExtValue(), LHSType) |
| 1632 | + << FormatUTFCodeUnitAsCodepoint(RHSValue.getExtValue(), RHSType); |
| 1633 | + return; |
| 1634 | + } |
| 1635 | + |
| 1636 | + if (SemaRef.getASTContext().hasSameType(LHSType, RHSType)) |
| 1637 | + return; |
| 1638 | + |
| 1639 | + SemaRef.Diag(Loc, diag::warn_arith_conv_mixed_unicode_types) |
| 1640 | + << LHS->getSourceRange() << RHS->getSourceRange() << ACK << LHSType |
| 1641 | + << RHSType; |
| 1642 | + return; |
| 1643 | +} |
| 1644 | + |
1571 | 1645 | /// UsualArithmeticConversions - Performs various conversions that are common to
|
1572 | 1646 | /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
|
1573 | 1647 | /// routine returns the first non-arithmetic type found. The client is
|
1574 | 1648 | /// responsible for emitting appropriate error diagnostics.
|
1575 | 1649 | QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS,
|
1576 | 1650 | SourceLocation Loc,
|
1577 | 1651 | ArithConvKind ACK) {
|
| 1652 | + |
1578 | 1653 | checkEnumArithmeticConversions(LHS.get(), RHS.get(), Loc, ACK);
|
1579 | 1654 |
|
| 1655 | + CheckUnicodeArithmeticConversions(*this, LHS.get(), RHS.get(), Loc, ACK); |
| 1656 | + |
1580 | 1657 | if (ACK != ArithConvKind::CompAssign) {
|
1581 | 1658 | LHS = UsualUnaryConversions(LHS.get());
|
1582 | 1659 | if (LHS.isInvalid())
|
|
0 commit comments