diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -1017,6 +1017,21 @@ } } + // Try to get the Index as Nonloc, then cast to ArrayIndexTy. + // Otherwise return None. + const auto MaybeNonLocIndexOfElementRegion = + [this](const ElementRegion *ElemReg) -> Optional { + SVal IndexVal = ElemReg->getIndex(); + Optional Index = IndexVal.getAs(); + if (!Index) + return llvm::None; + IndexVal = evalCastFromNonLoc(*Index, ArrayIndexTy); + Index = IndexVal.getAs(); + if (!Index) + return llvm::None; + return Index.getValue(); + }; + // Handle special cases for when both regions are element regions. const ElementRegion *RightER = dyn_cast(RightMR); const ElementRegion *LeftER = dyn_cast(LeftMR); @@ -1027,31 +1042,32 @@ // give the correct answer. if (LeftER->getSuperRegion() == RightER->getSuperRegion() && LeftER->getElementType() == RightER->getElementType()) { - // Get the left index and cast it to the correct type. - // If the index is unknown or undefined, bail out here. - SVal LeftIndexVal = LeftER->getIndex(); - Optional LeftIndex = LeftIndexVal.getAs(); - if (!LeftIndex) - return UnknownVal(); - LeftIndexVal = evalCastFromNonLoc(*LeftIndex, ArrayIndexTy); - LeftIndex = LeftIndexVal.getAs(); - if (!LeftIndex) - return UnknownVal(); - // Do the same for the right index. - SVal RightIndexVal = RightER->getIndex(); - Optional RightIndex = RightIndexVal.getAs(); - if (!RightIndex) - return UnknownVal(); - RightIndexVal = evalCastFromNonLoc(*RightIndex, ArrayIndexTy); - RightIndex = RightIndexVal.getAs(); - if (!RightIndex) + Optional LeftIndex = MaybeNonLocIndexOfElementRegion(LeftER); + Optional RightIndex = MaybeNonLocIndexOfElementRegion(RightER); + + if (!LeftIndex || !RightIndex) return UnknownVal(); // Actually perform the operation. // evalBinOpNN expects the two indexes to already be the right type. return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy); } + } else if (LeftER && isa(RightMR)) { + if (LeftER->getSuperRegion() != RightMR) + return UnknownVal(); + if (Optional LeftIndex = MaybeNonLocIndexOfElementRegion(LeftER)) + return LeftIndex.getValue(); + return UnknownVal(); + } else if (RightER && isa(LeftMR)) { + if (RightER->getSuperRegion() != LeftMR) + return UnknownVal(); + if (Optional RightIndex = + MaybeNonLocIndexOfElementRegion(RightER)) + llvm_unreachable( + "TODO: return the negated value of RightIndex - figure out how :D\n" + "Maybe a unary minus operator would do the job."); + return UnknownVal(); } // Special handling of the FieldRegions, even with symbolic offsets.