vabridgers created this revision. vabridgers added reviewers: dcoughlin, dergachev.a. vabridgers added a project: clang. Herald added a subscriber: cfe-commits.
This change fixes part 1 described by Artem in the Bugzilla report 43364. The comparison done was on a canonical, but should have been done on an unqualified type. Without using the unqualified type, the type comparison in this specific case is for "const Type * const" against "Type * const", which for the purposes of static analysis can be done not considering the Type's const qualifier. This is best done using a nonqualified type comparison. Test cases were added to cover this change. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D70836 Files: clang/lib/StaticAnalyzer/Core/Store.cpp clang/test/Analysis/uninit-val-const-likeness.c Index: clang/test/Analysis/uninit-val-const-likeness.c =================================================================== --- /dev/null +++ clang/test/Analysis/uninit-val-const-likeness.c @@ -0,0 +1,56 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -verify +// expected-no-diagnostics + +#define SIZE 2 + +typedef struct { + int noOfSymbols; +} Params; + +static void create(const Params * const params, int fooList[]) { + int tmpList[SIZE] = {0}; + for (int i = 0; i < params->noOfSymbols; i++) + fooList[i] = tmpList[i]; +} + +int work(Params * const params) { + int fooList[SIZE]; + create(params, fooList); + int sum = 0; + for (int i = 0; i < params->noOfSymbols; i++) + sum += fooList[i]; + return sum; +} + +static void create2(const Params * const * pparams, int fooList[]) { + const Params * params = *pparams; + int tmpList[SIZE] = {0}; + for (int i = 0; i < params->noOfSymbols; i++) + fooList[i] = tmpList[i]; +} + +int work2(const Params * const params) { + int fooList[SIZE]; + create2(¶ms, fooList); + int sum = 0; + for (int i = 0; i < params->noOfSymbols; i++) + sum += fooList[i]; + return sum; +} + +static void create3(Params * const * pparams, int fooList[]) { + const Params * params = *pparams; + int tmpList[SIZE] = {0}; + for (int i = 0; i < params->noOfSymbols; i++) + fooList[i] = tmpList[i]; +} + +int work3(const Params * const params) { + int fooList[SIZE]; + Params *const *ptr = (Params *const*)¶ms; + create3(ptr, fooList); + int sum = 0; + for (int i = 0; i < params->noOfSymbols; i++) + sum += fooList[i]; + return sum; +} Index: clang/lib/StaticAnalyzer/Core/Store.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/Store.cpp +++ clang/lib/StaticAnalyzer/Core/Store.cpp @@ -393,6 +393,11 @@ return UnknownVal(); } +static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) { + return ty1->getPointeeType().getTypePtr() == + ty2->getPointeeType().getTypePtr(); +} + /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted /// as another region. @@ -421,10 +426,11 @@ // FIXME: We really need a single good function to perform casts for us // correctly every time we need it. if (castTy->isPointerType() && !castTy->isVoidPointerType()) - if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) - if (SR->getSymbol()->getType().getCanonicalType() != - castTy.getCanonicalType()) - return loc::MemRegionVal(castRegion(SR, castTy)); + if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) { + QualType sr = SR->getSymbol()->getType(); + if (!hasSameUnqualifiedPointeeType(sr, castTy)) + return loc::MemRegionVal(castRegion(SR, castTy)); + } return svalBuilder.dispatchCast(V, castTy); }
Index: clang/test/Analysis/uninit-val-const-likeness.c =================================================================== --- /dev/null +++ clang/test/Analysis/uninit-val-const-likeness.c @@ -0,0 +1,56 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core %s -verify +// expected-no-diagnostics + +#define SIZE 2 + +typedef struct { + int noOfSymbols; +} Params; + +static void create(const Params * const params, int fooList[]) { + int tmpList[SIZE] = {0}; + for (int i = 0; i < params->noOfSymbols; i++) + fooList[i] = tmpList[i]; +} + +int work(Params * const params) { + int fooList[SIZE]; + create(params, fooList); + int sum = 0; + for (int i = 0; i < params->noOfSymbols; i++) + sum += fooList[i]; + return sum; +} + +static void create2(const Params * const * pparams, int fooList[]) { + const Params * params = *pparams; + int tmpList[SIZE] = {0}; + for (int i = 0; i < params->noOfSymbols; i++) + fooList[i] = tmpList[i]; +} + +int work2(const Params * const params) { + int fooList[SIZE]; + create2(¶ms, fooList); + int sum = 0; + for (int i = 0; i < params->noOfSymbols; i++) + sum += fooList[i]; + return sum; +} + +static void create3(Params * const * pparams, int fooList[]) { + const Params * params = *pparams; + int tmpList[SIZE] = {0}; + for (int i = 0; i < params->noOfSymbols; i++) + fooList[i] = tmpList[i]; +} + +int work3(const Params * const params) { + int fooList[SIZE]; + Params *const *ptr = (Params *const*)¶ms; + create3(ptr, fooList); + int sum = 0; + for (int i = 0; i < params->noOfSymbols; i++) + sum += fooList[i]; + return sum; +} Index: clang/lib/StaticAnalyzer/Core/Store.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/Store.cpp +++ clang/lib/StaticAnalyzer/Core/Store.cpp @@ -393,6 +393,11 @@ return UnknownVal(); } +static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) { + return ty1->getPointeeType().getTypePtr() == + ty2->getPointeeType().getTypePtr(); +} + /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted /// as another region. @@ -421,10 +426,11 @@ // FIXME: We really need a single good function to perform casts for us // correctly every time we need it. if (castTy->isPointerType() && !castTy->isVoidPointerType()) - if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) - if (SR->getSymbol()->getType().getCanonicalType() != - castTy.getCanonicalType()) - return loc::MemRegionVal(castRegion(SR, castTy)); + if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion())) { + QualType sr = SR->getSymbol()->getType(); + if (!hasSameUnqualifiedPointeeType(sr, castTy)) + return loc::MemRegionVal(castRegion(SR, castTy)); + } return svalBuilder.dispatchCast(V, castTy); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits