xref: /freebsd/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- DynamicTypePropagation.cpp ------------------------------*- C++ -*--===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains two checkers. One helps the static analyzer core to track
10 // types, the other does type inference on Obj-C generics and report type
11 // errors.
12 //
13 // Dynamic Type Propagation:
14 // This checker defines the rules for dynamic type gathering and propagation.
15 //
16 // Generics Checker for Objective-C:
17 // This checker tries to find type errors that the compiler is not able to catch
18 // due to the implicit conversions that were introduced for backward
19 // compatibility.
20 //
21 //===----------------------------------------------------------------------===//
22 
23 #include "clang/AST/DynamicRecursiveASTVisitor.h"
24 #include "clang/AST/ParentMap.h"
25 #include "clang/Basic/Builtins.h"
26 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
27 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
28 #include "clang/StaticAnalyzer/Core/Checker.h"
29 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
30 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
31 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
32 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
33 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
34 #include "llvm/ADT/STLExtras.h"
35 #include <optional>
36 
37 using namespace clang;
38 using namespace ento;
39 
40 // ProgramState trait - The type inflation is tracked by DynamicTypeMap. This is
41 // an auxiliary map that tracks more information about generic types, because in
42 // some cases the most derived type is not the most informative one about the
43 // type parameters. This types that are stored for each symbol in this map must
44 // be specialized.
45 // TODO: In some case the type stored in this map is exactly the same that is
46 // stored in DynamicTypeMap. We should no store duplicated information in those
47 // cases.
48 REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef,
49                                const ObjCObjectPointerType *)
50 
51 namespace {
52 class DynamicTypePropagation
53     : public CheckerFamily<check::PreCall, check::PostCall, check::DeadSymbols,
54                            check::PostStmt<CastExpr>,
55                            check::PostStmt<CXXNewExpr>, check::PreObjCMessage,
56                            check::PostObjCMessage> {
57 public:
58   // This checker family implements only one frontend, but -- unlike a simple
59   // Checker -- its backend can be enabled (by the checker DynamicTypeChecker
60   // which depends on it) without enabling the frontend.
61   CheckerFrontendWithBugType ObjCGenericsChecker{
62       "Generics", categories::CoreFoundationObjectiveC};
63 
64 private:
65   /// Return a better dynamic type if one can be derived from the cast.
66   const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE,
67                                                  CheckerContext &C) const;
68 
69   ExplodedNode *dynamicTypePropagationOnCasts(const CastExpr *CE,
70                                               ProgramStateRef &State,
71                                               CheckerContext &C) const;
72 
73   class GenericsBugVisitor : public BugReporterVisitor {
74   public:
GenericsBugVisitor(SymbolRef S)75     GenericsBugVisitor(SymbolRef S) : Sym(S) {}
76 
Profile(llvm::FoldingSetNodeID & ID) const77     void Profile(llvm::FoldingSetNodeID &ID) const override {
78       static int X = 0;
79       ID.AddPointer(&X);
80       ID.AddPointer(Sym);
81     }
82 
83     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
84                                      BugReporterContext &BRC,
85                                      PathSensitiveBugReport &BR) override;
86 
87   private:
88     // The tracked symbol.
89     SymbolRef Sym;
90   };
91 
92   void reportGenericsBug(const ObjCObjectPointerType *From,
93                          const ObjCObjectPointerType *To, ExplodedNode *N,
94                          SymbolRef Sym, CheckerContext &C,
95                          const Stmt *ReportedNode = nullptr) const;
96 
97 public:
98   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
99   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
100   void checkPostStmt(const CastExpr *CastE, CheckerContext &C) const;
101   void checkPostStmt(const CXXNewExpr *NewE, CheckerContext &C) const;
102   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
103   void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
104   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
105 
106   /// Identifies this checker family for debugging purposes.
getDebugTag() const107   StringRef getDebugTag() const override { return "DynamicTypePropagation"; }
108 };
109 
isObjCClassType(QualType Type)110 bool isObjCClassType(QualType Type) {
111   if (const auto *PointerType = dyn_cast<ObjCObjectPointerType>(Type)) {
112     return PointerType->getObjectType()->isObjCClass();
113   }
114   return false;
115 }
116 
117 struct RuntimeType {
118   const ObjCObjectType *Type = nullptr;
119   bool Precise = false;
120 
operator bool__anonf3f583590111::RuntimeType121   operator bool() const { return Type != nullptr; }
122 };
123 
inferReceiverType(const ObjCMethodCall & Message,CheckerContext & C)124 RuntimeType inferReceiverType(const ObjCMethodCall &Message,
125                               CheckerContext &C) {
126   const ObjCMessageExpr *MessageExpr = Message.getOriginExpr();
127 
128   // Check if we can statically infer the actual type precisely.
129   //
130   // 1. Class is written directly in the message:
131   // \code
132   //   [ActualClass classMethod];
133   // \endcode
134   if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Class) {
135     return {MessageExpr->getClassReceiver()->getAs<ObjCObjectType>(),
136             /*Precise=*/true};
137   }
138 
139   // 2. Receiver is 'super' from a class method (a.k.a 'super' is a
140   //    class object).
141   // \code
142   //   [super classMethod];
143   // \endcode
144   if (MessageExpr->getReceiverKind() == ObjCMessageExpr::SuperClass) {
145     return {MessageExpr->getSuperType()->getAs<ObjCObjectType>(),
146             /*Precise=*/true};
147   }
148 
149   // 3. Receiver is 'super' from an instance method (a.k.a 'super' is an
150   //    instance of a super class).
151   // \code
152   //   [super instanceMethod];
153   // \encode
154   if (MessageExpr->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
155     if (const auto *ObjTy =
156             MessageExpr->getSuperType()->getAs<ObjCObjectPointerType>())
157       return {ObjTy->getObjectType(), /*Precise=*/true};
158   }
159 
160   const Expr *RecE = MessageExpr->getInstanceReceiver();
161 
162   if (!RecE)
163     return {};
164 
165   // Otherwise, let's try to get type information from our estimations of
166   // runtime types.
167   QualType InferredType;
168   SVal ReceiverSVal = C.getSVal(RecE);
169   ProgramStateRef State = C.getState();
170 
171   if (const MemRegion *ReceiverRegion = ReceiverSVal.getAsRegion()) {
172     if (DynamicTypeInfo DTI = getDynamicTypeInfo(State, ReceiverRegion)) {
173       InferredType = DTI.getType().getCanonicalType();
174     }
175   }
176 
177   if (SymbolRef ReceiverSymbol = ReceiverSVal.getAsSymbol()) {
178     if (InferredType.isNull()) {
179       InferredType = ReceiverSymbol->getType();
180     }
181 
182     // If receiver is a Class object, we want to figure out the type it
183     // represents.
184     if (isObjCClassType(InferredType)) {
185       // We actually might have some info on what type is contained in there.
186       if (DynamicTypeInfo DTI =
187               getClassObjectDynamicTypeInfo(State, ReceiverSymbol)) {
188 
189         // Types in Class objects can be ONLY Objective-C types
190         return {cast<ObjCObjectType>(DTI.getType()), !DTI.canBeASubClass()};
191       }
192 
193       SVal SelfSVal = State->getSelfSVal(C.getLocationContext());
194 
195       // Another way we can guess what is in Class object, is when it is a
196       // 'self' variable of the current class method.
197       if (ReceiverSVal == SelfSVal) {
198         // In this case, we should return the type of the enclosing class
199         // declaration.
200         if (const ObjCMethodDecl *MD =
201                 dyn_cast<ObjCMethodDecl>(C.getStackFrame()->getDecl()))
202           if (const ObjCObjectType *ObjTy = dyn_cast<ObjCObjectType>(
203                   MD->getClassInterface()->getTypeForDecl()))
204             return {ObjTy};
205       }
206     }
207   }
208 
209   // Unfortunately, it seems like we have no idea what that type is.
210   if (InferredType.isNull()) {
211     return {};
212   }
213 
214   // We can end up here if we got some dynamic type info and the
215   // receiver is not one of the known Class objects.
216   if (const auto *ReceiverInferredType =
217           dyn_cast<ObjCObjectPointerType>(InferredType)) {
218     return {ReceiverInferredType->getObjectType()};
219   }
220 
221   // Any other type (like 'Class') is not really useful at this point.
222   return {};
223 }
224 } // end anonymous namespace
225 
checkDeadSymbols(SymbolReaper & SR,CheckerContext & C) const226 void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR,
227                                               CheckerContext &C) const {
228   ProgramStateRef State = removeDeadTypes(C.getState(), SR);
229   State = removeDeadClassObjectTypes(State, SR);
230 
231   MostSpecializedTypeArgsMapTy TyArgMap =
232       State->get<MostSpecializedTypeArgsMap>();
233   for (SymbolRef Sym : llvm::make_first_range(TyArgMap)) {
234     if (SR.isDead(Sym)) {
235       State = State->remove<MostSpecializedTypeArgsMap>(Sym);
236     }
237   }
238 
239   C.addTransition(State);
240 }
241 
recordFixedType(const MemRegion * Region,const CXXMethodDecl * MD,CheckerContext & C)242 static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
243                             CheckerContext &C) {
244   assert(Region);
245   assert(MD);
246 
247   ASTContext &Ctx = C.getASTContext();
248   QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent()));
249 
250   ProgramStateRef State = C.getState();
251   State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubClassed=*/false);
252   C.addTransition(State);
253 }
254 
checkPreCall(const CallEvent & Call,CheckerContext & C) const255 void DynamicTypePropagation::checkPreCall(const CallEvent &Call,
256                                           CheckerContext &C) const {
257   if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
258     // C++11 [class.cdtor]p4: When a virtual function is called directly or
259     //   indirectly from a constructor or from a destructor, including during
260     //   the construction or destruction of the class's non-static data members,
261     //   and the object to which the call applies is the object under
262     //   construction or destruction, the function called is the final overrider
263     //   in the constructor's or destructor's class and not one overriding it in
264     //   a more-derived class.
265 
266     switch (Ctor->getOriginExpr()->getConstructionKind()) {
267     case CXXConstructionKind::Complete:
268     case CXXConstructionKind::Delegating:
269       // No additional type info necessary.
270       return;
271     case CXXConstructionKind::NonVirtualBase:
272     case CXXConstructionKind::VirtualBase:
273       if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion())
274         recordFixedType(Target, Ctor->getDecl(), C);
275       return;
276     }
277 
278     return;
279   }
280 
281   if (const CXXDestructorCall *Dtor = dyn_cast<CXXDestructorCall>(&Call)) {
282     // C++11 [class.cdtor]p4 (see above)
283     if (!Dtor->isBaseDestructor())
284       return;
285 
286     const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion();
287     if (!Target)
288       return;
289 
290     const Decl *D = Dtor->getDecl();
291     if (!D)
292       return;
293 
294     recordFixedType(Target, cast<CXXDestructorDecl>(D), C);
295     return;
296   }
297 }
298 
checkPostCall(const CallEvent & Call,CheckerContext & C) const299 void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
300                                            CheckerContext &C) const {
301   // We can obtain perfect type info for return values from some calls.
302   if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
303 
304     // Get the returned value if it's a region.
305     const MemRegion *RetReg = Call.getReturnValue().getAsRegion();
306     if (!RetReg)
307       return;
308 
309     ProgramStateRef State = C.getState();
310     const ObjCMethodDecl *D = Msg->getDecl();
311 
312     if (D && D->hasRelatedResultType()) {
313       switch (Msg->getMethodFamily()) {
314       default:
315         break;
316 
317       // We assume that the type of the object returned by alloc and new are the
318       // pointer to the object of the class specified in the receiver of the
319       // message.
320       case OMF_alloc:
321       case OMF_new: {
322         // Get the type of object that will get created.
323         RuntimeType ObjTy = inferReceiverType(*Msg, C);
324 
325         if (!ObjTy)
326           return;
327 
328         QualType DynResTy =
329             C.getASTContext().getObjCObjectPointerType(QualType(ObjTy.Type, 0));
330         // We used to assume that whatever type we got from inferring the
331         // type is actually precise (and it is not exactly correct).
332         // A big portion of the existing behavior depends on that assumption
333         // (e.g. certain inlining won't take place). For this reason, we don't
334         // use ObjTy.Precise flag here.
335         //
336         // TODO: We should mitigate this problem some time in the future
337         // and replace hardcoded 'false' with '!ObjTy.Precise'.
338         C.addTransition(setDynamicTypeInfo(State, RetReg, DynResTy, false));
339         break;
340       }
341       case OMF_init: {
342         // Assume, the result of the init method has the same dynamic type as
343         // the receiver and propagate the dynamic type info.
344         const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion();
345         if (!RecReg)
346           return;
347         DynamicTypeInfo RecDynType = getDynamicTypeInfo(State, RecReg);
348         C.addTransition(setDynamicTypeInfo(State, RetReg, RecDynType));
349         break;
350       }
351       }
352     }
353     return;
354   }
355 
356   if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
357     // We may need to undo the effects of our pre-call check.
358     switch (Ctor->getOriginExpr()->getConstructionKind()) {
359     case CXXConstructionKind::Complete:
360     case CXXConstructionKind::Delegating:
361       // No additional work necessary.
362       // Note: This will leave behind the actual type of the object for
363       // complete constructors, but arguably that's a good thing, since it
364       // means the dynamic type info will be correct even for objects
365       // constructed with operator new.
366       return;
367     case CXXConstructionKind::NonVirtualBase:
368     case CXXConstructionKind::VirtualBase:
369       if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
370         // We just finished a base constructor. Now we can use the subclass's
371         // type when resolving virtual calls.
372         const LocationContext *LCtx = C.getLocationContext();
373 
374         // FIXME: In C++17 classes with non-virtual bases may be treated as
375         // aggregates, and in such case no top-frame constructor will be called.
376         // Figure out if we need to do anything in this case.
377         // FIXME: Instead of relying on the ParentMap, we should have the
378         // trigger-statement (InitListExpr or CXXParenListInitExpr in this case)
379         // available in this callback, ideally as part of CallEvent.
380         if (isa_and_nonnull<InitListExpr, CXXParenListInitExpr>(
381                 LCtx->getParentMap().getParent(Ctor->getOriginExpr())))
382           return;
383 
384         recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C);
385       }
386       return;
387     }
388   }
389 }
390 
391 /// TODO: Handle explicit casts.
392 ///       Handle C++ casts.
393 ///
394 /// Precondition: the cast is between ObjCObjectPointers.
dynamicTypePropagationOnCasts(const CastExpr * CE,ProgramStateRef & State,CheckerContext & C) const395 ExplodedNode *DynamicTypePropagation::dynamicTypePropagationOnCasts(
396     const CastExpr *CE, ProgramStateRef &State, CheckerContext &C) const {
397   // We only track type info for regions.
398   const MemRegion *ToR = C.getSVal(CE).getAsRegion();
399   if (!ToR)
400     return C.getPredecessor();
401 
402   if (isa<ExplicitCastExpr>(CE))
403     return C.getPredecessor();
404 
405   if (const Type *NewTy = getBetterObjCType(CE, C)) {
406     State = setDynamicTypeInfo(State, ToR, QualType(NewTy, 0));
407     return C.addTransition(State);
408   }
409   return C.getPredecessor();
410 }
411 
checkPostStmt(const CXXNewExpr * NewE,CheckerContext & C) const412 void DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE,
413                                            CheckerContext &C) const {
414   if (NewE->isArray())
415     return;
416 
417   // We only track dynamic type info for regions.
418   const MemRegion *MR = C.getSVal(NewE).getAsRegion();
419   if (!MR)
420     return;
421 
422   C.addTransition(setDynamicTypeInfo(C.getState(), MR, NewE->getType(),
423                                      /*CanBeSubClassed=*/false));
424 }
425 
426 // Return a better dynamic type if one can be derived from the cast.
427 // Compare the current dynamic type of the region and the new type to which we
428 // are casting. If the new type is lower in the inheritance hierarchy, pick it.
429 const ObjCObjectPointerType *
getBetterObjCType(const Expr * CastE,CheckerContext & C) const430 DynamicTypePropagation::getBetterObjCType(const Expr *CastE,
431                                           CheckerContext &C) const {
432   const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
433   assert(ToR);
434 
435   // Get the old and new types.
436   const ObjCObjectPointerType *NewTy =
437       CastE->getType()->getAs<ObjCObjectPointerType>();
438   if (!NewTy)
439     return nullptr;
440   QualType OldDTy = getDynamicTypeInfo(C.getState(), ToR).getType();
441   if (OldDTy.isNull()) {
442     return NewTy;
443   }
444   const ObjCObjectPointerType *OldTy =
445     OldDTy->getAs<ObjCObjectPointerType>();
446   if (!OldTy)
447     return nullptr;
448 
449   // Id the old type is 'id', the new one is more precise.
450   if (OldTy->isObjCIdType() && !NewTy->isObjCIdType())
451     return NewTy;
452 
453   // Return new if it's a subclass of old.
454   const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl();
455   const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl();
456   if (ToI && FromI && FromI->isSuperClassOf(ToI))
457     return NewTy;
458 
459   return nullptr;
460 }
461 
getMostInformativeDerivedClassImpl(const ObjCObjectPointerType * From,const ObjCObjectPointerType * To,const ObjCObjectPointerType * MostInformativeCandidate,ASTContext & C)462 static const ObjCObjectPointerType *getMostInformativeDerivedClassImpl(
463     const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
464     const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C) {
465   // Checking if from and to are the same classes modulo specialization.
466   if (From->getInterfaceDecl()->getCanonicalDecl() ==
467       To->getInterfaceDecl()->getCanonicalDecl()) {
468     if (To->isSpecialized()) {
469       assert(MostInformativeCandidate->isSpecialized());
470       return MostInformativeCandidate;
471     }
472     return From;
473   }
474 
475   if (To->getObjectType()->getSuperClassType().isNull()) {
476     // If To has no super class and From and To aren't the same then
477     // To was not actually a descendent of From. In this case the best we can
478     // do is 'From'.
479     return From;
480   }
481 
482   const auto *SuperOfTo =
483       To->getObjectType()->getSuperClassType()->castAs<ObjCObjectType>();
484   assert(SuperOfTo);
485   QualType SuperPtrOfToQual =
486       C.getObjCObjectPointerType(QualType(SuperOfTo, 0));
487   const auto *SuperPtrOfTo = SuperPtrOfToQual->castAs<ObjCObjectPointerType>();
488   if (To->isUnspecialized())
489     return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo, SuperPtrOfTo,
490                                               C);
491   else
492     return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo,
493                                               MostInformativeCandidate, C);
494 }
495 
496 /// A downcast may loose specialization information. E. g.:
497 ///   MutableMap<T, U> : Map
498 /// The downcast to MutableMap looses the information about the types of the
499 /// Map (due to the type parameters are not being forwarded to Map), and in
500 /// general there is no way to recover that information from the
501 /// declaration. In order to have to most information, lets find the most
502 /// derived type that has all the type parameters forwarded.
503 ///
504 /// Get the a subclass of \p From (which has a lower bound \p To) that do not
505 /// loose information about type parameters. \p To has to be a subclass of
506 /// \p From. From has to be specialized.
507 static const ObjCObjectPointerType *
getMostInformativeDerivedClass(const ObjCObjectPointerType * From,const ObjCObjectPointerType * To,ASTContext & C)508 getMostInformativeDerivedClass(const ObjCObjectPointerType *From,
509                                const ObjCObjectPointerType *To, ASTContext &C) {
510   return getMostInformativeDerivedClassImpl(From, To, To, C);
511 }
512 
513 /// Inputs:
514 ///   \param StaticLowerBound Static lower bound for a symbol. The dynamic lower
515 ///   bound might be the subclass of this type.
516 ///   \param StaticUpperBound A static upper bound for a symbol.
517 ///   \p StaticLowerBound expected to be the subclass of \p StaticUpperBound.
518 ///   \param Current The type that was inferred for a symbol in a previous
519 ///   context. Might be null when this is the first time that inference happens.
520 /// Precondition:
521 ///   \p StaticLowerBound or \p StaticUpperBound is specialized. If \p Current
522 ///   is not null, it is specialized.
523 /// Possible cases:
524 ///   (1) The \p Current is null and \p StaticLowerBound <: \p StaticUpperBound
525 ///   (2) \p StaticLowerBound <: \p Current <: \p StaticUpperBound
526 ///   (3) \p Current <: \p StaticLowerBound <: \p StaticUpperBound
527 ///   (4) \p StaticLowerBound <: \p StaticUpperBound <: \p Current
528 /// Effect:
529 ///   Use getMostInformativeDerivedClass with the upper and lower bound of the
530 ///   set {\p StaticLowerBound, \p Current, \p StaticUpperBound}. The computed
531 ///   lower bound must be specialized. If the result differs from \p Current or
532 ///   \p Current is null, store the result.
533 static bool
storeWhenMoreInformative(ProgramStateRef & State,SymbolRef Sym,const ObjCObjectPointerType * const * Current,const ObjCObjectPointerType * StaticLowerBound,const ObjCObjectPointerType * StaticUpperBound,ASTContext & C)534 storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym,
535                          const ObjCObjectPointerType *const *Current,
536                          const ObjCObjectPointerType *StaticLowerBound,
537                          const ObjCObjectPointerType *StaticUpperBound,
538                          ASTContext &C) {
539   // TODO: The above 4 cases are not exhaustive. In particular, it is possible
540   // for Current to be incomparable with StaticLowerBound, StaticUpperBound,
541   // or both.
542   //
543   // For example, suppose Foo<T> and Bar<T> are unrelated types.
544   //
545   //  Foo<T> *f = ...
546   //  Bar<T> *b = ...
547   //
548   //  id t1 = b;
549   //  f = t1;
550   //  id t2 = f; // StaticLowerBound is Foo<T>, Current is Bar<T>
551   //
552   // We should either constrain the callers of this function so that the stated
553   // preconditions hold (and assert it) or rewrite the function to expicitly
554   // handle the additional cases.
555 
556   // Precondition
557   assert(StaticUpperBound->isSpecialized() ||
558          StaticLowerBound->isSpecialized());
559   assert(!Current || (*Current)->isSpecialized());
560 
561   // Case (1)
562   if (!Current) {
563     if (StaticUpperBound->isUnspecialized()) {
564       State = State->set<MostSpecializedTypeArgsMap>(Sym, StaticLowerBound);
565       return true;
566     }
567     // Upper bound is specialized.
568     const ObjCObjectPointerType *WithMostInfo =
569         getMostInformativeDerivedClass(StaticUpperBound, StaticLowerBound, C);
570     State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
571     return true;
572   }
573 
574   // Case (3)
575   if (C.canAssignObjCInterfaces(StaticLowerBound, *Current)) {
576     return false;
577   }
578 
579   // Case (4)
580   if (C.canAssignObjCInterfaces(*Current, StaticUpperBound)) {
581     // The type arguments might not be forwarded at any point of inheritance.
582     const ObjCObjectPointerType *WithMostInfo =
583         getMostInformativeDerivedClass(*Current, StaticUpperBound, C);
584     WithMostInfo =
585         getMostInformativeDerivedClass(WithMostInfo, StaticLowerBound, C);
586     if (WithMostInfo == *Current)
587       return false;
588     State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
589     return true;
590   }
591 
592   // Case (2)
593   const ObjCObjectPointerType *WithMostInfo =
594       getMostInformativeDerivedClass(*Current, StaticLowerBound, C);
595   if (WithMostInfo != *Current) {
596     State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
597     return true;
598   }
599 
600   return false;
601 }
602 
603 /// Type inference based on static type information that is available for the
604 /// cast and the tracked type information for the given symbol. When the tracked
605 /// symbol and the destination type of the cast are unrelated, report an error.
checkPostStmt(const CastExpr * CE,CheckerContext & C) const606 void DynamicTypePropagation::checkPostStmt(const CastExpr *CE,
607                                            CheckerContext &C) const {
608   if (CE->getCastKind() != CK_BitCast)
609     return;
610 
611   QualType OriginType = CE->getSubExpr()->getType();
612   QualType DestType = CE->getType();
613 
614   const auto *OrigObjectPtrType = OriginType->getAs<ObjCObjectPointerType>();
615   const auto *DestObjectPtrType = DestType->getAs<ObjCObjectPointerType>();
616 
617   if (!OrigObjectPtrType || !DestObjectPtrType)
618     return;
619 
620   ProgramStateRef State = C.getState();
621   ExplodedNode *AfterTypeProp = dynamicTypePropagationOnCasts(CE, State, C);
622 
623   ASTContext &ASTCtxt = C.getASTContext();
624 
625   // This checker detects the subtyping relationships using the assignment
626   // rules. In order to be able to do this the kindofness must be stripped
627   // first. The checker treats every type as kindof type anyways: when the
628   // tracked type is the subtype of the static type it tries to look up the
629   // methods in the tracked type first.
630   OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
631   DestObjectPtrType = DestObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
632 
633   if (OrigObjectPtrType->isUnspecialized() &&
634       DestObjectPtrType->isUnspecialized())
635     return;
636 
637   SymbolRef Sym = C.getSVal(CE).getAsSymbol();
638   if (!Sym)
639     return;
640 
641   const ObjCObjectPointerType *const *TrackedType =
642       State->get<MostSpecializedTypeArgsMap>(Sym);
643 
644   if (isa<ExplicitCastExpr>(CE)) {
645     // Treat explicit casts as an indication from the programmer that the
646     // Objective-C type system is not rich enough to express the needed
647     // invariant. In such cases, forget any existing information inferred
648     // about the type arguments. We don't assume the casted-to specialized
649     // type here because the invariant the programmer specifies in the cast
650     // may only hold at this particular program point and not later ones.
651     // We don't want a suppressing cast to require a cascade of casts down the
652     // line.
653     if (TrackedType) {
654       State = State->remove<MostSpecializedTypeArgsMap>(Sym);
655       C.addTransition(State, AfterTypeProp);
656     }
657     return;
658   }
659 
660   // Check which assignments are legal.
661   bool OrigToDest =
662       ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, OrigObjectPtrType);
663   bool DestToOrig =
664       ASTCtxt.canAssignObjCInterfaces(OrigObjectPtrType, DestObjectPtrType);
665 
666   // The tracked type should be the sub or super class of the static destination
667   // type. When an (implicit) upcast or a downcast happens according to static
668   // types, and there is no subtyping relationship between the tracked and the
669   // static destination types, it indicates an error.
670   if (TrackedType &&
671       !ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, *TrackedType) &&
672       !ASTCtxt.canAssignObjCInterfaces(*TrackedType, DestObjectPtrType)) {
673     // This distinct program point tag is needed because `State` can be
674     // identical to the state of the node `AfterTypeProp`, and in that case
675     // `generateNonFatalErrorNode` would "cache out" and return nullptr
676     // (instead of re-creating an already existing node).
677     static SimpleProgramPointTag IllegalConv("DynamicTypePropagation",
678                                              "IllegalConversion");
679     ExplodedNode *N =
680         C.generateNonFatalErrorNode(State, AfterTypeProp, &IllegalConv);
681     if (N)
682       reportGenericsBug(*TrackedType, DestObjectPtrType, N, Sym, C);
683     return;
684   }
685 
686   // Handle downcasts and upcasts.
687 
688   const ObjCObjectPointerType *LowerBound = DestObjectPtrType;
689   const ObjCObjectPointerType *UpperBound = OrigObjectPtrType;
690   if (OrigToDest && !DestToOrig)
691     std::swap(LowerBound, UpperBound);
692 
693   // The id type is not a real bound. Eliminate it.
694   LowerBound = LowerBound->isObjCIdType() ? UpperBound : LowerBound;
695   UpperBound = UpperBound->isObjCIdType() ? LowerBound : UpperBound;
696 
697   if (storeWhenMoreInformative(State, Sym, TrackedType, LowerBound, UpperBound,
698                                ASTCtxt)) {
699     C.addTransition(State, AfterTypeProp);
700   }
701 }
702 
stripCastsAndSugar(const Expr * E)703 static const Expr *stripCastsAndSugar(const Expr *E) {
704   E = E->IgnoreParenImpCasts();
705   if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
706     E = POE->getSyntacticForm()->IgnoreParenImpCasts();
707   if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
708     E = OVE->getSourceExpr()->IgnoreParenImpCasts();
709   return E;
710 }
711 
isObjCTypeParamDependent(QualType Type)712 static bool isObjCTypeParamDependent(QualType Type) {
713   // It is illegal to typedef parameterized types inside an interface. Therefore
714   // an Objective-C type can only be dependent on a type parameter when the type
715   // parameter structurally present in the type itself.
716   class IsObjCTypeParamDependentTypeVisitor
717       : public DynamicRecursiveASTVisitor {
718   public:
719     IsObjCTypeParamDependentTypeVisitor() = default;
720     bool VisitObjCTypeParamType(ObjCTypeParamType *Type) override {
721       if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
722         Result = true;
723         return false;
724       }
725       return true;
726     }
727 
728     bool Result = false;
729   };
730 
731   IsObjCTypeParamDependentTypeVisitor Visitor;
732   Visitor.TraverseType(Type);
733   return Visitor.Result;
734 }
735 
736 /// A method might not be available in the interface indicated by the static
737 /// type. However it might be available in the tracked type. In order to
738 /// properly substitute the type parameters we need the declaration context of
739 /// the method. The more specialized the enclosing class of the method is, the
740 /// more likely that the parameter substitution will be successful.
741 static const ObjCMethodDecl *
findMethodDecl(const ObjCMessageExpr * MessageExpr,const ObjCObjectPointerType * TrackedType,ASTContext & ASTCtxt)742 findMethodDecl(const ObjCMessageExpr *MessageExpr,
743                const ObjCObjectPointerType *TrackedType, ASTContext &ASTCtxt) {
744   const ObjCMethodDecl *Method = nullptr;
745 
746   QualType ReceiverType = MessageExpr->getReceiverType();
747 
748   // Do this "devirtualization" on instance and class methods only. Trust the
749   // static type on super and super class calls.
750   if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Instance ||
751       MessageExpr->getReceiverKind() == ObjCMessageExpr::Class) {
752     // When the receiver type is id, Class, or some super class of the tracked
753     // type, look up the method in the tracked type, not in the receiver type.
754     // This way we preserve more information.
755     if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType() ||
756         ASTCtxt.canAssignObjCInterfaces(
757             ReceiverType->castAs<ObjCObjectPointerType>(), TrackedType)) {
758       const ObjCInterfaceDecl *InterfaceDecl = TrackedType->getInterfaceDecl();
759       // The method might not be found.
760       Selector Sel = MessageExpr->getSelector();
761       Method = InterfaceDecl->lookupInstanceMethod(Sel);
762       if (!Method)
763         Method = InterfaceDecl->lookupClassMethod(Sel);
764     }
765   }
766 
767   // Fallback to statick method lookup when the one based on the tracked type
768   // failed.
769   return Method ? Method : MessageExpr->getMethodDecl();
770 }
771 
772 /// Get the returned ObjCObjectPointerType by a method based on the tracked type
773 /// information, or null pointer when the returned type is not an
774 /// ObjCObjectPointerType.
getReturnTypeForMethod(const ObjCMethodDecl * Method,ArrayRef<QualType> TypeArgs,const ObjCObjectPointerType * SelfType,ASTContext & C)775 static QualType getReturnTypeForMethod(
776     const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs,
777     const ObjCObjectPointerType *SelfType, ASTContext &C) {
778   QualType StaticResultType = Method->getReturnType();
779 
780   // Is the return type declared as instance type?
781   if (StaticResultType == C.getObjCInstanceType())
782     return QualType(SelfType, 0);
783 
784   // Check whether the result type depends on a type parameter.
785   if (!isObjCTypeParamDependent(StaticResultType))
786     return QualType();
787 
788   QualType ResultType = StaticResultType.substObjCTypeArgs(
789       C, TypeArgs, ObjCSubstitutionContext::Result);
790 
791   return ResultType;
792 }
793 
794 /// When the receiver has a tracked type, use that type to validate the
795 /// argumments of the message expression and the return value.
checkPreObjCMessage(const ObjCMethodCall & M,CheckerContext & C) const796 void DynamicTypePropagation::checkPreObjCMessage(const ObjCMethodCall &M,
797                                                  CheckerContext &C) const {
798   ProgramStateRef State = C.getState();
799   SymbolRef Sym = M.getReceiverSVal().getAsSymbol();
800   if (!Sym)
801     return;
802 
803   const ObjCObjectPointerType *const *TrackedType =
804       State->get<MostSpecializedTypeArgsMap>(Sym);
805   if (!TrackedType)
806     return;
807 
808   // Get the type arguments from tracked type and substitute type arguments
809   // before do the semantic check.
810 
811   ASTContext &ASTCtxt = C.getASTContext();
812   const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
813   const ObjCMethodDecl *Method =
814       findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
815 
816   // It is possible to call non-existent methods in Obj-C.
817   if (!Method)
818     return;
819 
820   // If the method is declared on a class that has a non-invariant
821   // type parameter, don't warn about parameter mismatches after performing
822   // substitution. This prevents warning when the programmer has purposely
823   // casted the receiver to a super type or unspecialized type but the analyzer
824   // has a more precise tracked type than the programmer intends at the call
825   // site.
826   //
827   // For example, consider NSArray (which has a covariant type parameter)
828   // and NSMutableArray (a subclass of NSArray where the type parameter is
829   // invariant):
830   // NSMutableArray *a = [[NSMutableArray<NSString *> alloc] init;
831   //
832   // [a containsObject:number]; // Safe: -containsObject is defined on NSArray.
833   // NSArray<NSObject *> *other = [a arrayByAddingObject:number]  // Safe
834   //
835   // [a addObject:number] // Unsafe: -addObject: is defined on NSMutableArray
836   //
837 
838   const ObjCInterfaceDecl *Interface = Method->getClassInterface();
839   if (!Interface)
840     return;
841 
842   ObjCTypeParamList *TypeParams = Interface->getTypeParamList();
843   if (!TypeParams)
844     return;
845 
846   for (ObjCTypeParamDecl *TypeParam : *TypeParams) {
847     if (TypeParam->getVariance() != ObjCTypeParamVariance::Invariant)
848       return;
849   }
850 
851   std::optional<ArrayRef<QualType>> TypeArgs =
852       (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
853   // This case might happen when there is an unspecialized override of a
854   // specialized method.
855   if (!TypeArgs)
856     return;
857 
858   for (unsigned i = 0; i < Method->param_size(); i++) {
859     const Expr *Arg = MessageExpr->getArg(i);
860     const ParmVarDecl *Param = Method->parameters()[i];
861 
862     QualType OrigParamType = Param->getType();
863     if (!isObjCTypeParamDependent(OrigParamType))
864       continue;
865 
866     QualType ParamType = OrigParamType.substObjCTypeArgs(
867         ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Parameter);
868     // Check if it can be assigned
869     const auto *ParamObjectPtrType = ParamType->getAs<ObjCObjectPointerType>();
870     const auto *ArgObjectPtrType =
871         stripCastsAndSugar(Arg)->getType()->getAs<ObjCObjectPointerType>();
872     if (!ParamObjectPtrType || !ArgObjectPtrType)
873       continue;
874 
875     // Check if we have more concrete tracked type that is not a super type of
876     // the static argument type.
877     SVal ArgSVal = M.getArgSVal(i);
878     SymbolRef ArgSym = ArgSVal.getAsSymbol();
879     if (ArgSym) {
880       const ObjCObjectPointerType *const *TrackedArgType =
881           State->get<MostSpecializedTypeArgsMap>(ArgSym);
882       if (TrackedArgType &&
883           ASTCtxt.canAssignObjCInterfaces(ArgObjectPtrType, *TrackedArgType)) {
884         ArgObjectPtrType = *TrackedArgType;
885       }
886     }
887 
888     // Warn when argument is incompatible with the parameter.
889     if (!ASTCtxt.canAssignObjCInterfaces(ParamObjectPtrType,
890                                          ArgObjectPtrType)) {
891       ExplodedNode *N = C.generateNonFatalErrorNode(State);
892       reportGenericsBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C, Arg);
893       return;
894     }
895   }
896 }
897 
898 /// This callback is used to infer the types for Class variables. This info is
899 /// used later to validate messages that sent to classes. Class variables are
900 /// initialized with by invoking the 'class' method on a class.
901 /// This method is also used to infer the type information for the return
902 /// types.
903 // TODO: right now it only tracks generic types. Extend this to track every
904 // type in the DynamicTypeMap and diagnose type errors!
checkPostObjCMessage(const ObjCMethodCall & M,CheckerContext & C) const905 void DynamicTypePropagation::checkPostObjCMessage(const ObjCMethodCall &M,
906                                                   CheckerContext &C) const {
907   const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
908 
909   SymbolRef RetSym = M.getReturnValue().getAsSymbol();
910   if (!RetSym)
911     return;
912 
913   Selector Sel = MessageExpr->getSelector();
914   ProgramStateRef State = C.getState();
915 
916   // Here we try to propagate information on Class objects.
917   if (Sel.getAsString() == "class") {
918     // We try to figure out the type from the receiver of the 'class' message.
919     if (RuntimeType ReceiverRuntimeType = inferReceiverType(M, C)) {
920 
921       ReceiverRuntimeType.Type->getSuperClassType();
922       QualType ReceiverClassType(ReceiverRuntimeType.Type, 0);
923 
924       // We want to consider only precise information on generics.
925       if (ReceiverRuntimeType.Type->isSpecialized() &&
926           ReceiverRuntimeType.Precise) {
927         QualType ReceiverClassPointerType =
928             C.getASTContext().getObjCObjectPointerType(ReceiverClassType);
929         const auto *InferredType =
930             ReceiverClassPointerType->castAs<ObjCObjectPointerType>();
931         State = State->set<MostSpecializedTypeArgsMap>(RetSym, InferredType);
932       }
933 
934       // Constrain the resulting class object to the inferred type.
935       State = setClassObjectDynamicTypeInfo(State, RetSym, ReceiverClassType,
936                                             !ReceiverRuntimeType.Precise);
937 
938       C.addTransition(State);
939       return;
940     }
941   }
942 
943   if (Sel.getAsString() == "superclass") {
944     // We try to figure out the type from the receiver of the 'superclass'
945     // message.
946     if (RuntimeType ReceiverRuntimeType = inferReceiverType(M, C)) {
947 
948       // Result type would be a super class of the receiver's type.
949       QualType ReceiversSuperClass =
950           ReceiverRuntimeType.Type->getSuperClassType();
951 
952       // Check if it really had super class.
953       //
954       // TODO: we can probably pay closer attention to cases when the class
955       // object can be 'nil' as the result of such message.
956       if (!ReceiversSuperClass.isNull()) {
957         // Constrain the resulting class object to the inferred type.
958         State = setClassObjectDynamicTypeInfo(
959             State, RetSym, ReceiversSuperClass, !ReceiverRuntimeType.Precise);
960 
961         C.addTransition(State);
962       }
963       return;
964     }
965   }
966 
967   // Tracking for return types.
968   SymbolRef RecSym = M.getReceiverSVal().getAsSymbol();
969   if (!RecSym)
970     return;
971 
972   const ObjCObjectPointerType *const *TrackedType =
973       State->get<MostSpecializedTypeArgsMap>(RecSym);
974   if (!TrackedType)
975     return;
976 
977   ASTContext &ASTCtxt = C.getASTContext();
978   const ObjCMethodDecl *Method =
979       findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
980   if (!Method)
981     return;
982 
983   std::optional<ArrayRef<QualType>> TypeArgs =
984       (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
985   if (!TypeArgs)
986     return;
987 
988   QualType ResultType =
989       getReturnTypeForMethod(Method, *TypeArgs, *TrackedType, ASTCtxt);
990   // The static type is the same as the deduced type.
991   if (ResultType.isNull())
992     return;
993 
994   const MemRegion *RetRegion = M.getReturnValue().getAsRegion();
995   ExplodedNode *Pred = C.getPredecessor();
996   // When there is an entry available for the return symbol in DynamicTypeMap,
997   // the call was inlined, and the information in the DynamicTypeMap is should
998   // be precise.
999   if (RetRegion && !getRawDynamicTypeInfo(State, RetRegion)) {
1000     // TODO: we have duplicated information in DynamicTypeMap and
1001     // MostSpecializedTypeArgsMap. We should only store anything in the later if
1002     // the stored data differs from the one stored in the former.
1003     State = setDynamicTypeInfo(State, RetRegion, ResultType,
1004                                /*CanBeSubClassed=*/true);
1005     Pred = C.addTransition(State);
1006   }
1007 
1008   const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>();
1009 
1010   if (!ResultPtrType || ResultPtrType->isUnspecialized())
1011     return;
1012 
1013   // When the result is a specialized type and it is not tracked yet, track it
1014   // for the result symbol.
1015   if (!State->get<MostSpecializedTypeArgsMap>(RetSym)) {
1016     State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType);
1017     C.addTransition(State, Pred);
1018   }
1019 }
1020 
reportGenericsBug(const ObjCObjectPointerType * From,const ObjCObjectPointerType * To,ExplodedNode * N,SymbolRef Sym,CheckerContext & C,const Stmt * ReportedNode) const1021 void DynamicTypePropagation::reportGenericsBug(
1022     const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
1023     ExplodedNode *N, SymbolRef Sym, CheckerContext &C,
1024     const Stmt *ReportedNode) const {
1025   if (!ObjCGenericsChecker.isEnabled())
1026     return;
1027 
1028   SmallString<192> Buf;
1029   llvm::raw_svector_ostream OS(Buf);
1030   OS << "Conversion from value of type '";
1031   QualType::print(From, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
1032   OS << "' to incompatible type '";
1033   QualType::print(To, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
1034   OS << "'";
1035   auto R = std::make_unique<PathSensitiveBugReport>(ObjCGenericsChecker,
1036                                                     OS.str(), N);
1037   R->markInteresting(Sym);
1038   R->addVisitor(std::make_unique<GenericsBugVisitor>(Sym));
1039   if (ReportedNode)
1040     R->addRange(ReportedNode->getSourceRange());
1041   C.emitReport(std::move(R));
1042 }
1043 
VisitNode(const ExplodedNode * N,BugReporterContext & BRC,PathSensitiveBugReport & BR)1044 PathDiagnosticPieceRef DynamicTypePropagation::GenericsBugVisitor::VisitNode(
1045     const ExplodedNode *N, BugReporterContext &BRC,
1046     PathSensitiveBugReport &BR) {
1047   ProgramStateRef state = N->getState();
1048   ProgramStateRef statePrev = N->getFirstPred()->getState();
1049 
1050   const ObjCObjectPointerType *const *TrackedType =
1051       state->get<MostSpecializedTypeArgsMap>(Sym);
1052   const ObjCObjectPointerType *const *TrackedTypePrev =
1053       statePrev->get<MostSpecializedTypeArgsMap>(Sym);
1054   if (!TrackedType)
1055     return nullptr;
1056 
1057   if (TrackedTypePrev && *TrackedTypePrev == *TrackedType)
1058     return nullptr;
1059 
1060   // Retrieve the associated statement.
1061   const Stmt *S = N->getStmtForDiagnostics();
1062   if (!S)
1063     return nullptr;
1064 
1065   const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
1066 
1067   SmallString<256> Buf;
1068   llvm::raw_svector_ostream OS(Buf);
1069   OS << "Type '";
1070   QualType::print(*TrackedType, Qualifiers(), OS, LangOpts, llvm::Twine());
1071   OS << "' is inferred from ";
1072 
1073   if (const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
1074     OS << "explicit cast (from '";
1075     QualType::print(ExplicitCast->getSubExpr()->getType().getTypePtr(),
1076                     Qualifiers(), OS, LangOpts, llvm::Twine());
1077     OS << "' to '";
1078     QualType::print(ExplicitCast->getType().getTypePtr(), Qualifiers(), OS,
1079                     LangOpts, llvm::Twine());
1080     OS << "')";
1081   } else if (const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
1082     OS << "implicit cast (from '";
1083     QualType::print(ImplicitCast->getSubExpr()->getType().getTypePtr(),
1084                     Qualifiers(), OS, LangOpts, llvm::Twine());
1085     OS << "' to '";
1086     QualType::print(ImplicitCast->getType().getTypePtr(), Qualifiers(), OS,
1087                     LangOpts, llvm::Twine());
1088     OS << "')";
1089   } else {
1090     OS << "this context";
1091   }
1092 
1093   // Generate the extra diagnostic.
1094   PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
1095                              N->getLocationContext());
1096   return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true);
1097 }
1098 
1099 /// Register checkers.
registerObjCGenericsChecker(CheckerManager & Mgr)1100 void ento::registerObjCGenericsChecker(CheckerManager &Mgr) {
1101   Mgr.getChecker<DynamicTypePropagation>()->ObjCGenericsChecker.enable(Mgr);
1102 }
1103 
shouldRegisterObjCGenericsChecker(const CheckerManager &)1104 bool ento::shouldRegisterObjCGenericsChecker(const CheckerManager &) {
1105   return true;
1106 }
1107 
registerDynamicTypePropagation(CheckerManager & Mgr)1108 void ento::registerDynamicTypePropagation(CheckerManager &Mgr) {
1109   // The checker 'core.DynamicTypeChecker' relies on the modeling implemented
1110   // in the class 'DynamicTypePropagation', so this "modeling checker" can
1111   // register the 'DynamicTypePropagation' backend for its callbacks without
1112   // enabling its frontend.
1113   Mgr.getChecker<DynamicTypePropagation>();
1114 }
1115 
shouldRegisterDynamicTypePropagation(const CheckerManager &)1116 bool ento::shouldRegisterDynamicTypePropagation(const CheckerManager &) {
1117   return true;
1118 }
1119