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@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@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits