diff options
| author | Chandler Carruth <chandlerc@gmail.com> | 2011-02-18 23:54:50 +0000 |
|---|---|---|
| committer | Chandler Carruth <chandlerc@gmail.com> | 2011-02-18 23:54:50 +0000 |
| commit | a8bea4b90ec7448231306920b7a55ab4a13841cc (patch) | |
| tree | 38d943d1ad2cd6ca939aae044d4dc01ad74544a5 /clang/lib/Sema/SemaExpr.cpp | |
| parent | 55532be31fbc60797efe9a181b01f0a4f8058fa0 (diff) | |
| download | bcm5719-llvm-a8bea4b90ec7448231306920b7a55ab4a13841cc.tar.gz bcm5719-llvm-a8bea4b90ec7448231306920b7a55ab4a13841cc.zip | |
Initial steps to improve diagnostics when there is a NULL and
a non-pointer on the two sides of a conditional expression.
Patch by Stephen Hines and Mihai Rusu.
llvm-svn: 125995
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 7e6eee7fb7b..792eb8af98b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5229,6 +5229,46 @@ ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L, return Owned(expr); } +/// \brief Emit a specialized diagnostic when one expression is a null pointer +/// constant and the other is not a pointer. +bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS, + SourceLocation QuestionLoc) { + Expr *NullExpr = LHS; + Expr *NonPointerExpr = RHS; + Expr::NullPointerConstantKind NullKind = + NullExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull); + + if (NullKind == Expr::NPCK_NotNull) { + NullExpr = RHS; + NonPointerExpr = LHS; + NullKind = + NullExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull); + } + + if (NullKind == Expr::NPCK_NotNull) + return false; + + if (NullKind == Expr::NPCK_ZeroInteger) { + // In this case, check to make sure that we got here from a "NULL" + // string in the source code. + NullExpr = NullExpr->IgnoreParenImpCasts(); + SourceManager& SM = Context.getSourceManager(); + SourceLocation Loc = SM.getInstantiationLoc(NullExpr->getExprLoc()); + unsigned Len = + Lexer::MeasureTokenLength(Loc, SM, Context.getLangOptions()); + if (Len != 4 || memcmp(SM.getCharacterData(Loc), "NULL", 4)) + return false; + } + + int DiagType = (NullKind == Expr::NPCK_CXX0X_nullptr); + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands_null) + << NonPointerExpr->getType() << DiagType + << NonPointerExpr->getSourceRange(); + return true; +} + /// Note that lhs is not null here, even if this is the gnu "x ?: y" extension. /// In that case, lhs = cond. /// C99 6.5.15 @@ -5471,6 +5511,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return LHSTy; } + // Emit a better diagnostic if one of the expressions is a null pointer + // constant and the other is not a pointer type. In this case, the user most + // likely forgot to take the address of the other expression. + if (DiagnoseConditionalForNull(LHS, RHS, QuestionLoc)) + return QualType(); + // Otherwise, the operands are not compatible. Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); |

