diff --git a/clang/include/clang/Basic/PartialDiagnostic.h b/clang/include/clang/Basic/PartialDiagnostic.h index e8cc564c8a20..9960d5beb5c1 100644 --- a/clang/include/clang/Basic/PartialDiagnostic.h +++ b/clang/include/clang/Basic/PartialDiagnostic.h @@ -109,7 +109,7 @@ public: // Add all arguments. for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) { DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i], - (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]); + (Diagnostic::ArgumentKind)DiagStorage->DiagArgumentsKind[i]); } // Add all ranges. @@ -129,13 +129,25 @@ public: PD.AddTaggedVal(I, Diagnostic::ak_uint); return PD; } - + + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + int I) { + PD.AddTaggedVal(I, Diagnostic::ak_sint); + return PD; + } + + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const char *S) { + PD.AddTaggedVal(reinterpret_cast(S), Diagnostic::ak_c_string); + return PD; + } + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, const SourceRange &R) { PD.AddSourceRange(R); return PD; } - + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, DeclarationName N); }; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 84a430ab5235..6f7ad609a034 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5419,6 +5419,23 @@ static inline bool IsEqOrRel(int Opc) { return Opc >= BinaryOperator::LT && Opc <= BinaryOperator::NE; } +static void SuggestParentheses(Sema &Self, SourceLocation Loc, + const PartialDiagnostic &PD, + SourceRange ParenRange) +{ + SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd()); + if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { + // We can't display the parentheses, so just dig the + // warning/error and return. + Self.Diag(Loc, PD); + return; + } + + Self.Diag(Loc, PD) + << CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(") + << CodeModificationHint::CreateInsertion(EndLoc, ")"); +} + static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc, SourceLocation OpLoc,Expr *lhs,Expr *rhs){ typedef BinaryOperator::Opcode Opcode; @@ -5439,15 +5456,21 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc, return; if (IsEqOrRel(lhsopc)) - Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel) - << SourceRange(lhs->getLocStart(), OpLoc) - << BinaryOperator::getOpcodeStr(Opc) - << BinaryOperator::getOpcodeStr(static_cast(lhsopc)); + SuggestParentheses(Self, OpLoc, + PDiag(diag::warn_precedence_bitwise_rel) + << SourceRange(lhs->getLocStart(), OpLoc) + << BinaryOperator::getOpcodeStr(Opc) + << BinaryOperator::getOpcodeStr(static_cast(lhsopc)), + SourceRange(cast(lhs)->getRHS()->getLocStart(), + rhs->getLocEnd())); else if (IsEqOrRel(rhsopc)) - Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel) - << SourceRange(OpLoc, rhs->getLocEnd()) - << BinaryOperator::getOpcodeStr(Opc) - << BinaryOperator::getOpcodeStr(static_cast(rhsopc)); + SuggestParentheses(Self, OpLoc, + PDiag(diag::warn_precedence_bitwise_rel) + << SourceRange(OpLoc, rhs->getLocEnd()) + << BinaryOperator::getOpcodeStr(Opc) + << BinaryOperator::getOpcodeStr(static_cast(rhsopc)), + SourceRange(lhs->getLocEnd(), + cast(rhs)->getLHS()->getLocStart())); } /// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky