diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 73 |
1 files changed, 45 insertions, 28 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 9d8a3f5240d..d5c80c9e201 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1180,8 +1180,7 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, /// Checks if a the given expression evaluates to null. /// /// \brief Returns true if the value evaluates to null. -static bool CheckNonNullExpr(Sema &S, - const Expr *Expr) { +static bool CheckNonNullExpr(Sema &S, const Expr *Expr) { // If the expression has non-null type, it doesn't evaluate to null. if (auto nullability = Expr->IgnoreImplicit()->getType()->getNullability(S.Context)) { @@ -7666,6 +7665,26 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, } } + auto ComplainAboutNonnullParamOrCall = [&](bool IsParam) { + std::string Str; + llvm::raw_string_ostream S(Str); + E->printPretty(S, nullptr, getPrintingPolicy()); + unsigned DiagID = IsCompare ? diag::warn_nonnull_expr_compare + : diag::warn_cast_nonnull_to_bool; + Diag(E->getExprLoc(), DiagID) << IsParam << S.str() + << E->getSourceRange() << Range << IsEqual; + }; + + // If we have a CallExpr that is tagged with returns_nonnull, we can complain. + if (auto *Call = dyn_cast<CallExpr>(E->IgnoreParenImpCasts())) { + if (auto *Callee = Call->getDirectCallee()) { + if (Callee->hasAttr<ReturnsNonNullAttr>()) { + ComplainAboutNonnullParamOrCall(false); + return; + } + } + } + // Expect to find a single Decl. Skip anything more complicated. ValueDecl *D = nullptr; if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) { @@ -7677,40 +7696,38 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, // Weak Decls can be null. if (!D || D->isWeak()) return; - + // Check for parameter decl with nonnull attribute - if (const ParmVarDecl* PV = dyn_cast<ParmVarDecl>(D)) { - if (getCurFunction() && !getCurFunction()->ModifiedNonNullParams.count(PV)) - if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) { - unsigned NumArgs = FD->getNumParams(); - llvm::SmallBitVector AttrNonNull(NumArgs); + if (const auto* PV = dyn_cast<ParmVarDecl>(D)) { + if (getCurFunction() && + !getCurFunction()->ModifiedNonNullParams.count(PV)) { + if (PV->hasAttr<NonNullAttr>()) { + ComplainAboutNonnullParamOrCall(true); + return; + } + + if (const auto *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) { + auto ParamIter = std::find(FD->param_begin(), FD->param_end(), PV); + assert(ParamIter != FD->param_end()); + unsigned ParamNo = std::distance(FD->param_begin(), ParamIter); + for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) { if (!NonNull->args_size()) { - AttrNonNull.set(0, NumArgs); - break; - } - for (unsigned Val : NonNull->args()) { - if (Val >= NumArgs) - continue; - AttrNonNull.set(Val); + ComplainAboutNonnullParamOrCall(true); + return; } - } - if (!AttrNonNull.empty()) - for (unsigned i = 0; i < NumArgs; ++i) - if (FD->getParamDecl(i) == PV && - (AttrNonNull[i] || PV->hasAttr<NonNullAttr>())) { - std::string Str; - llvm::raw_string_ostream S(Str); - E->printPretty(S, nullptr, getPrintingPolicy()); - unsigned DiagID = IsCompare ? diag::warn_nonnull_parameter_compare - : diag::warn_cast_nonnull_to_bool; - Diag(E->getExprLoc(), DiagID) << S.str() << E->getSourceRange() - << Range << IsEqual; + + for (unsigned ArgNo : NonNull->args()) { + if (ArgNo == ParamNo) { + ComplainAboutNonnullParamOrCall(true); return; } + } + } } } - + } + QualType T = D->getType(); const bool IsArray = T->isArrayType(); const bool IsFunction = T->isFunctionType(); |