r331556 - [analyzer] Treat more const variables and fields as known contants.

Alexander Kornienko via cfe-commits cfe-commits at lists.llvm.org
Mon May 7 11:57:20 PDT 2018


It looks like this commit has introduced an assertion failure. See
https://bugs.llvm.org/show_bug.cgi?id=37357.

On Fri, May 4, 2018 at 10:56 PM Artem Dergachev via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: dergachev
> Date: Fri May  4 13:52:39 2018
> New Revision: 331556
>
> URL: http://llvm.org/viewvc/llvm-project?rev=331556&view=rev
> Log:
> [analyzer] Treat more const variables and fields as known contants.
>
> When loading from a variable or a field that is declared as constant,
> the analyzer will try to inspect its initializer and constant-fold it.
> Upon success, the analyzer would skip normal load and return the respective
> constant.
>
> The new behavior also applies to fields/elements of brace-initialized
> structures
> and arrays.
>
> Patch by Rafael Stahl!
>
> Differential Revision: https://reviews.llvm.org/D45774
>
> Added:
>     cfe/trunk/test/Analysis/globals.cpp
> Modified:
>     cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
>     cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=331556&r1=331555&r2=331556&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Fri May  4 13:52:39
> 2018
> @@ -1606,7 +1606,7 @@ SVal RegionStoreManager::getBindingForEl
>    const MemRegion* superR = R->getSuperRegion();
>
>    // Check if the region is an element region of a string literal.
> -  if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
> +  if (const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
>      // FIXME: Handle loads from strings where the literal is treated as
>      // an integer, e.g., *((unsigned int*)"hello")
>      QualType T =
> Ctx.getAsArrayType(StrR->getValueType())->getElementType();
> @@ -1629,6 +1629,27 @@ SVal RegionStoreManager::getBindingForEl
>        char c = (i >= length) ? '\0' : Str->getCodeUnit(i);
>        return svalBuilder.makeIntVal(c, T);
>      }
> +  } else if (const VarRegion *VR = dyn_cast<VarRegion>(superR)) {
> +    // Check if the containing array is const and has an initialized
> value.
> +    const VarDecl *VD = VR->getDecl();
> +    // Either the array or the array element has to be const.
> +    if (VD->getType().isConstQualified() ||
> R->getElementType().isConstQualified()) {
> +      if (const Expr *Init = VD->getInit()) {
> +        if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
> +          // The array index has to be known.
> +          if (auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
> +            int64_t i = CI->getValue().getSExtValue();
> +            // Return unknown value if index is out of bounds.
> +            if (i < 0 || i >= InitList->getNumInits())
> +              return UnknownVal();
> +
> +            if (const Expr *ElemInit = InitList->getInit(i))
> +              if (Optional<SVal> V = svalBuilder.getConstantVal(ElemInit))
> +                return *V;
> +          }
> +        }
> +      }
> +    }
>    }
>
>    // Check for loads from a code text region.  For such loads, just give
> up.
> @@ -1678,7 +1699,28 @@ SVal RegionStoreManager::getBindingForFi
>    if (const Optional<SVal> &V = B.getDirectBinding(R))
>      return *V;
>
> -  QualType Ty = R->getValueType();
> +  // Is the field declared constant and has an in-class initializer?
> +  const FieldDecl *FD = R->getDecl();
> +  QualType Ty = FD->getType();
> +  if (Ty.isConstQualified())
> +    if (const Expr *Init = FD->getInClassInitializer())
> +      if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
> +        return *V;
> +
> +  // If the containing record was initialized, try to get its constant
> value.
> +  const MemRegion* superR = R->getSuperRegion();
> +  if (const auto *VR = dyn_cast<VarRegion>(superR)) {
> +    const VarDecl *VD = VR->getDecl();
> +    QualType RecordVarTy = VD->getType();
> +    // Either the record variable or the field has to be const qualified.
> +    if (RecordVarTy.isConstQualified() || Ty.isConstQualified())
> +      if (const Expr *Init = VD->getInit())
> +        if (const auto *InitList = dyn_cast<InitListExpr>(Init))
> +          if (const Expr *FieldInit =
> InitList->getInit(FD->getFieldIndex()))
> +            if (Optional<SVal> V = svalBuilder.getConstantVal(FieldInit))
> +              return *V;
> +  }
> +
>    return getBindingForFieldOrElementCommon(B, R, Ty);
>  }
>
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp?rev=331556&r1=331555&r2=331556&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp Fri May  4 13:52:39
> 2018
> @@ -119,7 +119,7 @@ SValBuilder::getRegionValueSymbolVal(con
>
>    if (T->isNullPtrType())
>      return makeZeroVal(T);
> -
> +
>    if (!SymbolManager::canSymbolicate(T))
>      return UnknownVal();
>
> @@ -328,12 +328,19 @@ Optional<SVal> SValBuilder::getConstantV
>    case Stmt::CXXNullPtrLiteralExprClass:
>      return makeNull();
>
> +  case Stmt::CStyleCastExprClass:
> +  case Stmt::CXXFunctionalCastExprClass:
> +  case Stmt::CXXConstCastExprClass:
> +  case Stmt::CXXReinterpretCastExprClass:
> +  case Stmt::CXXStaticCastExprClass:
>    case Stmt::ImplicitCastExprClass: {
>      const auto *CE = cast<CastExpr>(E);
>      switch (CE->getCastKind()) {
>      default:
>        break;
>      case CK_ArrayToPointerDecay:
> +    case CK_IntegralToPointer:
> +    case CK_NoOp:
>      case CK_BitCast: {
>        const Expr *SE = CE->getSubExpr();
>        Optional<SVal> Val = getConstantVal(SE);
>
> Added: cfe/trunk/test/Analysis/globals.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/globals.cpp?rev=331556&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/Analysis/globals.cpp (added)
> +++ cfe/trunk/test/Analysis/globals.cpp Fri May  4 13:52:39 2018
> @@ -0,0 +1,111 @@
> +// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
> +
> +
> +static const unsigned long long scull = 0;
> +void static_int()
> +{
> +    *(int*)scull = 0; // expected-warning{{Dereference of null pointer}}
> +}
> +
> +const unsigned long long cull = 0;
> +void const_int()
> +{
> +    *(int*)cull = 0; // expected-warning{{Dereference of null pointer}}
> +}
> +
> +static int * const spc = 0;
> +void static_ptr()
> +{
> +    *spc = 0; // expected-warning{{Dereference of null pointer}}
> +}
> +
> +int * const pc = 0;
> +void const_ptr()
> +{
> +    *pc = 0; // expected-warning{{Dereference of null pointer}}
> +}
> +
> +const unsigned long long cull_nonnull = 4;
> +void nonnull_int()
> +{
> +    *(int*)(cull_nonnull - 4) = 0; // expected-warning{{Dereference of
> null pointer}}
> +}
> +
> +int * const pc_nonnull = (int*)sizeof(int);
> +void nonnull_ptr()
> +{
> +    *(pc_nonnull - 1) = 0; // expected-warning{{Dereference of null
> pointer}}
> +}
> +
> +int * const constcast = const_cast<int * const>((int*)sizeof(int));
> +void cast1()
> +{
> +    *(constcast - 1) = 0; // expected-warning{{Dereference of null
> pointer}}
> +}
> +
> +int * const recast = reinterpret_cast<int*>(sizeof(int));
> +void cast2()
> +{
> +    *(recast - 1) = 0; // expected-warning{{Dereference of null pointer}}
> +}
> +
> +int * const staticcast = static_cast<int * const>((int*)sizeof(int));
> +void cast3()
> +{
> +    *(staticcast - 1) = 0; // expected-warning{{Dereference of null
> pointer}}
> +}
> +
> +struct Foo { int a; };
> +Foo * const dyncast = dynamic_cast<Foo * const>((Foo*)sizeof(Foo));
> +void cast4()
> +{
> +    // Do not handle dynamic_cast for now, because it may change the
> pointer value.
> +    (dyncast - 1)->a = 0; // no-warning
> +}
> +
> +typedef int * const intptrconst;
> +int * const funccast = intptrconst(sizeof(int));
> +void cast5()
> +{
> +    *(funccast - 1) = 0; // expected-warning{{Dereference of null
> pointer}}
> +}
> +
> +struct S1
> +{
> +    int * p;
> +};
> +const S1 s1 = {
> +    .p = (int*)sizeof(int)
> +};
> +void conststruct()
> +{
> +    *(s1.p - 1) = 0; // expected-warning{{Dereference of null pointer}}
> +}
> +
> +struct S2
> +{
> +    int * const p;
> +};
> +S2 s2 = {
> +    .p = (int*)sizeof(int)
> +};
> +void constfield()
> +{
> +    *(s2.p - 1) = 0; // expected-warning{{Dereference of null pointer}}
> +}
> +
> +int * const parr[1] = { (int*)sizeof(int) };
> +void constarr()
> +{
> +    *(parr[0] - 1) = 0; // expected-warning{{Dereference of null pointer}}
> +}
> +
> +struct S3
> +{
> +    int * p = (int*)sizeof(int);
> +};
> +void recordinit()
> +{
> +    S3 s3;
> +    *(s3.p - 1) = 0; // expected-warning{{Dereference of null pointer}}
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180507/64ee030e/attachment-0001.html>


More information about the cfe-commits mailing list