@@ -189,66 +189,67 @@ public boolean hasCompatibleTypesForCall(AccessPath apBase, SootClass dest) {
189189 /**
190190 * Gets the more precise one of the two given types. If there is no ordering
191191 * (i.e., the two types are not cast-compatible) null is returned.
192- *
193- * @param tp1 The first type
194- * @param tp2 The second type
192+ * IMPORTANT: this method is not commutative on array types. The second type must
193+ * always be the declared type, which is used to infer the array depth.
194+ * Consider, for example, the case
195+ * objArr[i] = str;
196+ * where we can narrow the type of objArr to String[]. Vice versa,
197+ * obj = strArr[i];
198+ * allows us to narrow the type of obj to String. Therefore,
199+ * getMorePreciseType(String, Object[]) should return String[] and
200+ * getMorePreciseType(Object[], String) should return String.
201+ *
202+ * @param possibleRefinement The first type
203+ * @param declType The second type
195204 * @return The more precise one of the two given types
196205 */
197- public Type getMorePreciseType (Type tp1 , Type tp2 ) {
206+ public Type getMorePreciseType (Type possibleRefinement , Type declType ) {
198207 final FastHierarchy fastHierarchy = scene .getOrMakeFastHierarchy ();
199208
200- if (tp1 == null )
201- return tp2 ;
202- else if (tp2 == null )
203- return tp1 ;
204- else if (tp1 == tp2 )
205- return tp1 ;
206- else if (TypeUtils .isObjectLikeType (tp1 ))
207- return tp2 ;
208- else if (TypeUtils .isObjectLikeType (tp2 ))
209- return tp1 ;
210- else if (tp1 instanceof PrimType && tp2 instanceof PrimType )
209+ if (declType == null )
210+ return possibleRefinement ;
211+ else if (possibleRefinement == null )
212+ return declType ;
213+ else if (declType == possibleRefinement )
214+ return declType ;
215+ else if (TypeUtils .isObjectLikeType (declType ))
216+ return possibleRefinement ;
217+ else if (TypeUtils .isObjectLikeType (possibleRefinement ))
218+ return declType ;
219+ else if (declType instanceof PrimType && possibleRefinement instanceof PrimType )
211220 return null ;
212- else if (fastHierarchy .canStoreType (tp2 , tp1 ))
213- return tp2 ;
214- else if (fastHierarchy .canStoreType (tp1 , tp2 ))
215- return tp1 ;
221+ else if (fastHierarchy .canStoreType (possibleRefinement , declType ))
222+ return possibleRefinement ;
223+ else if (fastHierarchy .canStoreType (declType , possibleRefinement ))
224+ return declType ;
216225 else {
217226 // If one type is an array type and the other one is the base type,
218227 // we still accept the cast
219- if (tp1 instanceof ArrayType && tp2 instanceof ArrayType ) {
220- ArrayType at1 = (ArrayType ) tp1 ;
221- ArrayType at2 = (ArrayType ) tp2 ;
228+ if (declType instanceof ArrayType && possibleRefinement instanceof ArrayType ) {
229+ ArrayType at1 = (ArrayType ) declType ;
230+ ArrayType at2 = (ArrayType ) possibleRefinement ;
222231 if (at1 .numDimensions != at2 .numDimensions )
223232 return null ;
224233 Type preciseType = getMorePreciseType (at1 .getElementType (), at2 .getElementType ());
225234 if (preciseType == null )
226235 return null ;
227236
228237 return ArrayType .v (preciseType , at1 .numDimensions );
229- } else if (tp1 instanceof ArrayType ) {
230- ArrayType at = (ArrayType ) tp1 ;
231- return getMorePreciseType (at .getElementType (), tp2 );
232- } else if (tp2 instanceof ArrayType ) {
233- ArrayType at = (ArrayType ) tp2 ;
234- return getMorePreciseType (tp1 , at .getElementType ());
238+ } else if (declType instanceof ArrayType ) {
239+ ArrayType at = (ArrayType ) declType ;
240+ Type preciseType = getMorePreciseType (at .getElementType (), possibleRefinement );
241+ if (preciseType == null )
242+ return null ;
243+
244+ return ArrayType .v (preciseType , at .numDimensions );
245+ } else if (possibleRefinement instanceof ArrayType ) {
246+ ArrayType at = (ArrayType ) possibleRefinement ;
247+ return getMorePreciseType (at .getElementType (), declType );
235248 }
236249 }
237250 return null ;
238251 }
239252
240- /**
241- * Gets the more precise one of the two given types
242- *
243- * @param tp1 The first type
244- * @param tp2 The second type
245- * @return The more precise one of the two given types
246- */
247- public String getMorePreciseType (String tp1 , String tp2 ) {
248- Type newType = getMorePreciseType (getTypeFromString (tp1 ), getTypeFromString (tp2 ));
249- return newType == null ? null : "" + newType ;
250- }
251-
252253 /**
253254 * Creates a Soot Type from the given string
254255 *
0 commit comments