[PATCH] D119004: [NFC][analyzer] Allow CallDescriptions to be matched with CallExprs

Kristóf Umann via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 4 08:23:58 PST 2022


Szelethus created this revision.
Szelethus added reviewers: NoQ, steakhal, xazax.hun, martong, ASDenysPetrov.
Herald added subscribers: manas, gamesh411, dkrupp, donat.nagy, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware.
Szelethus requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

As of now, we have two interfaces to for defining signatures: `StdLibraryFunctionsChecker::Signature` and `CallDescription`. An example for how `Signature`s are used can be seen here:

  addToFunctionSummaryMap(
      "isprint", Signature(ArgTypes{IntTy}, RetType{IntTy}),
      Summary(EvalCallAsPure)
          .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)),
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
          .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)),
                 ReturnValueCondition(WithinRange, SingleValue(0))}));

The name of the function is searched for in translation unit's identifier table, then the `Signature` is matched against each decl `Decl` with the same name. Ideally, this yields a `FunctionDecl`, which is mapped to its `Summary`.

This works well for C functions, but doesn't support C++ at all.

`CallDescription` emerged with a strong emphasis on recognizing C++ functions. The common example brough up is `std::string`, which in some standard library implementations is actually called something like `std::__cxx11::basic_string`, but not in others. Matching this can be a nightmare for checker developers. For this reason, `CallDescription`s can be defined like this:

  
  InnerPointerChecker()
      : AppendFn({"std", "basic_string", "append"}),
        AssignFn({"std", "basic_string", "assign"}),
        AddressofFn({"std", "addressof"}),
        ClearFn({"std", "basic_string", "clear"}),
        CStrFn({"std", "basic_string", "c_str"}), DataFn({"std", "data"}, 1),
        DataMemberFn({"std", "basic_string", "data"}),
        EraseFn({"std", "basic_string", "erase"}),
        InsertFn({"std", "basic_string", "insert"}),
        PopBackFn({"std", "basic_string", "pop_back"}),
        PushBackFn({"std", "basic_string", "push_back"}),
        ReplaceFn({"std", "basic_string", "replace"}),
        ReserveFn({"std", "basic_string", "reserve"}),
        ResizeFn({"std", "basic_string", "resize"}),
        ShrinkToFitFn({"std", "basic_string", "shrink_to_fit"}),
        SwapFn({"std", "basic_string", "swap"}) {}

Any identifier which matches //at least// these identifiers are considered a match (which sometimes leads to incorrect matching, e.g. D81745 <https://reviews.llvm.org/D81745>).

`CallDescription`s are (usually) not used for digging up `FunctionDecl`s from the translation unit, but rather during symbolic execution to check in a pre/post call event whether the called function matches the `CallDescription`:

  bool InnerPointerChecker::isInnerPointerAccessFunction(
      const CallEvent &Call) const {
    return matchesAny(Call, CStrFn, DataFn, DataMemberFn);
  }

Most of the new checkers implementing pre/post condition checks on functions now use `CallDescriptionMap` or `CallDescriptionSet`. Its up to debate whether the newer `Signature` approach is better, but its not obvious, and converting from one to the other may be non-trivial as well.

---

Now, onto this patch. Since `CallDescription`s can only be matched against `CallEvent`s that are created during symbolic execution, it was not possible to use it in syntactic-only contexts. For example, even though `InnerPointerChecker` can check with its set of `CallDescription`s whether a function call is interested during analysis, its unable to check without hassle whether a non-analyzer piece of code also calls such a function.

The patch adds the ability to use `CallDescription`s in syntactic contexts as well. While we already have that in `Signature`, we still want to leverage the ability to use dynamic information when we have it (function pointers, for example). This could be done with `Signature` as well (`StdLibraryFunctionsChecker` does it), but it makes it even less of a drop-in replacement.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119004

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
  clang/lib/StaticAnalyzer/Core/CallDescription.cpp
  clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D119004.405962.patch
Type: text/x-patch
Size: 9332 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220204/5cb551f7/attachment-0001.bin>


More information about the cfe-commits mailing list