r220496 - patch to issue warning on comparing parameters with

Richard Trieu rtrieu at google.com
Thu Oct 23 18:14:08 PDT 2014


Sorry for the duplicate email.  Once more, with the list this time.

On Thu, Oct 23, 2014 at 12:00 PM, Fariborz Jahanian <fjahanian at apple.com>
wrote:

> Author: fjahanian
> Date: Thu Oct 23 14:00:10 2014
> New Revision: 220496
>
> URL: http://llvm.org/viewvc/llvm-project?rev=220496&view=rev
> Log:
> patch to issue warning on comparing parameters with
> nonnull attribute when comparison is always
> true/false. Patch by Steven Wu with few fixes and minor
> refactoring and adding tests by me. rdar://18712242
>
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/lib/Sema/SemaChecking.cpp
>     cfe/trunk/test/Sema/nonnull.c
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=220496&r1=220495&r2=220496&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Oct 23
> 14:00:10 2014
> @@ -2500,6 +2500,10 @@ def warn_impcast_pointer_to_bool : Warni
>      "address of%select{| function| array}0 '%1' will always evaluate to "
>      "'true'">,
>      InGroup<PointerBoolConversion>;
> +def warn_cast_nonnull_to_bool : Warning<
> +    "nonnull parameter '%0' will always evaluate to "
> +    "'true'">,
> +    InGroup<PointerBoolConversion>;
>  def warn_this_bool_conversion : Warning<
>    "'this' pointer cannot be null in well-defined C++ code; pointer may be
> "
>    "assumed to always convert to true">, InGroup<UndefinedBoolConversion>;
> @@ -2512,6 +2516,10 @@ def warn_null_pointer_compare : Warning<
>      "comparison of %select{address of|function|array}0 '%1' %select{not
> |}2"
>      "equal to a null pointer is always %select{true|false}2">,
>      InGroup<TautologicalPointerCompare>;
> +def warn_nonnull_parameter_compare : Warning<
> +    "comparison of nonnull parameter '%0' %select{not |}1"
> +    "equal to a null pointer is always %select{true|false}1">,
> +    InGroup<TautologicalPointerCompare>;
>  def warn_this_null_compare : Warning<
>    "'this' pointer cannot be null in well-defined C++ code; comparison may
> be "
>    "assumed to always evaluate to %select{true|false}0">,
>
> Why are two new diagnostic messages added here?  The text is nearly
identical, so it should work by adding a new choice to the %select in the
existing warning message.

> Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=220496&r1=220495&r2=220496&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaChecking.cpp Thu Oct 23 14:00:10 2014
> @@ -6678,7 +6678,37 @@ void Sema::DiagnoseAlwaysNonNullPointer(
>    // Weak Decls can be null.
>    if (!D || D->isWeak())
>      return;
> -
>
Move the non-null parameter check to a helper function which takes a
ParmVarDecl as a parameter and use early exit to prevent extra work.

> +  // Check for parameter decl with nonnull attribute
> +  if (ParmVarDecl* PV = dyn_cast<ParmVarDecl>(D)) {
> +    if (FunctionDecl* FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
> +      unsigned NumArgs = FD->getNumParams();
> +      llvm::SmallBitVector AttrNonNull(NumArgs);
>
BitVector not needed in new function.  Access to AttrNonNull are turned in
returns.

> +      for (const auto *NonNull : FD->specific_attrs<NonNullAttr>()) {
> +        if (!NonNull->args_size()) {
> +          AttrNonNull.set(0, NumArgs);
>
Early exit here.

> +          break;
> +        }
> +        for (unsigned Val : NonNull->args()) {
> +          if (Val >= NumArgs)
> +            continue;
> +          AttrNonNull.set(Val);
>
Use Val to get the ParmVarDecl from the FunctionDecl, which can be compared
to ParmVarDecl and return on equality.

> +        }
> +      }
> +      if (!AttrNonNull.empty())
> +        for (unsigned i = 0; i < NumArgs; ++i)
> +          if (FD->getParamDecl(i) == PV && AttrNonNull[i]) {
> +            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;
> +            return;
> +          }
> +    }
> +  }
> +
>    QualType T = D->getType();
>    const bool IsArray = T->isArrayType();
>    const bool IsFunction = T->isFunctionType();
>
> Once the new warning and the old warning are folded together, use the
current Diag call instead having a new one here.

> Modified: cfe/trunk/test/Sema/nonnull.c
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/nonnull.c?rev=220496&r1=220495&r2=220496&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/Sema/nonnull.c (original)
> +++ cfe/trunk/test/Sema/nonnull.c Thu Oct 23 14:00:10 2014
> @@ -83,3 +83,28 @@ void redecl_test(void *p) {
>    redecl(p, 0); // expected-warning{{null passed}}
>    redecl(0, p); // expected-warning{{null passed}}
>  }
> +
> +// rdar://18712242
> +#define NULL (void*)0
> +__attribute__((__nonnull__))
> +int evil_nonnull_func(int* pointer, void * pv)
> +{
> +   if (pointer == NULL) {  // expected-warning {{comparison of nonnull
> parameter 'pointer' equal to a null pointer is always false}}
> +     return 0;
> +   } else {
> +     return *pointer;
> +   }
> +
> +   if (pv == NULL) {} // expected-warning {{comparison of nonnull
> parameter 'pv' equal to a null pointer is always false}}
> +}
> +
> +int another_evil_nonnull_func(int* pointer, char ch, void * pv)
> __attribute__((nonnull(1, 3)));
> +int another_evil_nonnull_func(int* pointer, char ch, void * pv) {
> +   if (pointer == NULL) { // expected-warning {{comparison of nonnull
> parameter 'pointer' equal to a null pointer is always false}}
> +     return 0;
> +   } else {
> +     return *pointer;
> +   }
> +
> +   if (pv == NULL) {} // expected-warning {{comparison of nonnull
> parameter 'pv' equal to a null pointer is always false}}
> +}
>
> Add a test which has multiple pointer parameters, only a few which are
marked non-null.  Test that the warning only fires on the non-null pointer
parameters.

>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141023/95049191/attachment.html>


More information about the cfe-commits mailing list