diff --git a/clang/lib/StaticAnalyzer/Core/Store.cpp b/clang/lib/StaticAnalyzer/Core/Store.cpp --- a/clang/lib/StaticAnalyzer/Core/Store.cpp +++ b/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(V.getAsRegion())) - if (SR->getSymbol()->getType().getCanonicalType() != - castTy.getCanonicalType()) - return loc::MemRegionVal(castRegion(SR, castTy)); + if (const auto *SR = dyn_cast_or_null(V.getAsRegion())) { + QualType sr = SR->getSymbol()->getType(); + if (!hasSameUnqualifiedPointeeType(sr, castTy)) + return loc::MemRegionVal(castRegion(SR, castTy)); + } return svalBuilder.dispatchCast(V, castTy); } diff --git a/clang/test/Analysis/uninit-val-const-likeness.c b/clang/test/Analysis/uninit-val-const-likeness.c new file mode 100644 --- /dev/null +++ b/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; +}