Home | History | Annotate | Download | only in Checkers
      1 //== DynamicTypePropagation.cpp -------------------------------- -*- C++ -*--=//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains two checkers. One helps the static analyzer core to track
     11 // types, the other does type inference on Obj-C generics and report type
     12 // errors.
     13 //
     14 // Dynamic Type Propagation:
     15 // This checker defines the rules for dynamic type gathering and propagation.
     16 //
     17 // Generics Checker for Objective-C:
     18 // This checker tries to find type errors that the compiler is not able to catch
     19 // due to the implicit conversions that were introduced for backward
     20 // compatibility.
     21 //
     22 //===----------------------------------------------------------------------===//
     23 
     24 #include "ClangSACheckers.h"
     25 #include "clang/AST/RecursiveASTVisitor.h"
     26 #include "clang/Basic/Builtins.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/DynamicTypeMap.h"
     32 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
     33 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
     34 
     35 using namespace clang;
     36 using namespace ento;
     37 
     38 // ProgramState trait - The type inflation is tracked by DynamicTypeMap. This is
     39 // an auxiliary map that tracks more information about generic types, because in
     40 // some cases the most derived type is not the most informative one about the
     41 // type parameters. This types that are stored for each symbol in this map must
     42 // be specialized.
     43 // TODO: In some case the type stored in this map is exactly the same that is
     44 // stored in DynamicTypeMap. We should no store duplicated information in those
     45 // cases.
     46 REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef,
     47                                const ObjCObjectPointerType *)
     48 
     49 namespace {
     50 class DynamicTypePropagation:
     51     public Checker< check::PreCall,
     52                     check::PostCall,
     53                     check::DeadSymbols,
     54                     check::PostStmt<CastExpr>,
     55                     check::PostStmt<CXXNewExpr>,
     56                     check::PreObjCMessage,
     57                     check::PostObjCMessage > {
     58   const ObjCObjectType *getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
     59                                                     CheckerContext &C) const;
     60 
     61   /// \brief Return a better dynamic type if one can be derived from the cast.
     62   const ObjCObjectPointerType *getBetterObjCType(const Expr *CastE,
     63                                                  CheckerContext &C) const;
     64 
     65   ExplodedNode *dynamicTypePropagationOnCasts(const CastExpr *CE,
     66                                               ProgramStateRef &State,
     67                                               CheckerContext &C) const;
     68 
     69   mutable std::unique_ptr<BugType> ObjCGenericsBugType;
     70   void initBugType() const {
     71     if (!ObjCGenericsBugType)
     72       ObjCGenericsBugType.reset(
     73           new BugType(this, "Generics", categories::CoreFoundationObjectiveC));
     74   }
     75 
     76   class GenericsBugVisitor : public BugReporterVisitorImpl<GenericsBugVisitor> {
     77   public:
     78     GenericsBugVisitor(SymbolRef S) : Sym(S) {}
     79 
     80     void Profile(llvm::FoldingSetNodeID &ID) const override {
     81       static int X = 0;
     82       ID.AddPointer(&X);
     83       ID.AddPointer(Sym);
     84     }
     85 
     86     PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
     87                                    const ExplodedNode *PrevN,
     88                                    BugReporterContext &BRC,
     89                                    BugReport &BR) override;
     90 
     91   private:
     92     // The tracked symbol.
     93     SymbolRef Sym;
     94   };
     95 
     96   void reportGenericsBug(const ObjCObjectPointerType *From,
     97                          const ObjCObjectPointerType *To, ExplodedNode *N,
     98                          SymbolRef Sym, CheckerContext &C,
     99                          const Stmt *ReportedNode = nullptr) const;
    100 public:
    101   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
    102   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
    103   void checkPostStmt(const CastExpr *CastE, CheckerContext &C) const;
    104   void checkPostStmt(const CXXNewExpr *NewE, CheckerContext &C) const;
    105   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
    106   void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
    107   void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
    108 
    109   /// This value is set to true, when the Generics checker is turned on.
    110   DefaultBool CheckGenerics;
    111 };
    112 }
    113 
    114 void DynamicTypePropagation::checkDeadSymbols(SymbolReaper &SR,
    115                                               CheckerContext &C) const {
    116   ProgramStateRef State = C.getState();
    117   DynamicTypeMapImpl TypeMap = State->get<DynamicTypeMap>();
    118   for (DynamicTypeMapImpl::iterator I = TypeMap.begin(), E = TypeMap.end();
    119        I != E; ++I) {
    120     if (!SR.isLiveRegion(I->first)) {
    121       State = State->remove<DynamicTypeMap>(I->first);
    122     }
    123   }
    124 
    125   if (!SR.hasDeadSymbols()) {
    126     C.addTransition(State);
    127     return;
    128   }
    129 
    130   MostSpecializedTypeArgsMapTy TyArgMap =
    131       State->get<MostSpecializedTypeArgsMap>();
    132   for (MostSpecializedTypeArgsMapTy::iterator I = TyArgMap.begin(),
    133                                               E = TyArgMap.end();
    134        I != E; ++I) {
    135     if (SR.isDead(I->first)) {
    136       State = State->remove<MostSpecializedTypeArgsMap>(I->first);
    137     }
    138   }
    139 
    140   C.addTransition(State);
    141 }
    142 
    143 static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD,
    144                             CheckerContext &C) {
    145   assert(Region);
    146   assert(MD);
    147 
    148   ASTContext &Ctx = C.getASTContext();
    149   QualType Ty = Ctx.getPointerType(Ctx.getRecordType(MD->getParent()));
    150 
    151   ProgramStateRef State = C.getState();
    152   State = setDynamicTypeInfo(State, Region, Ty, /*CanBeSubclass=*/false);
    153   C.addTransition(State);
    154   return;
    155 }
    156 
    157 void DynamicTypePropagation::checkPreCall(const CallEvent &Call,
    158                                           CheckerContext &C) const {
    159   if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
    160     // C++11 [class.cdtor]p4: When a virtual function is called directly or
    161     //   indirectly from a constructor or from a destructor, including during
    162     //   the construction or destruction of the class's non-static data members,
    163     //   and the object to which the call applies is the object under
    164     //   construction or destruction, the function called is the final overrider
    165     //   in the constructor's or destructor's class and not one overriding it in
    166     //   a more-derived class.
    167 
    168     switch (Ctor->getOriginExpr()->getConstructionKind()) {
    169     case CXXConstructExpr::CK_Complete:
    170     case CXXConstructExpr::CK_Delegating:
    171       // No additional type info necessary.
    172       return;
    173     case CXXConstructExpr::CK_NonVirtualBase:
    174     case CXXConstructExpr::CK_VirtualBase:
    175       if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion())
    176         recordFixedType(Target, Ctor->getDecl(), C);
    177       return;
    178     }
    179 
    180     return;
    181   }
    182 
    183   if (const CXXDestructorCall *Dtor = dyn_cast<CXXDestructorCall>(&Call)) {
    184     // C++11 [class.cdtor]p4 (see above)
    185     if (!Dtor->isBaseDestructor())
    186       return;
    187 
    188     const MemRegion *Target = Dtor->getCXXThisVal().getAsRegion();
    189     if (!Target)
    190       return;
    191 
    192     const Decl *D = Dtor->getDecl();
    193     if (!D)
    194       return;
    195 
    196     recordFixedType(Target, cast<CXXDestructorDecl>(D), C);
    197     return;
    198   }
    199 }
    200 
    201 void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
    202                                            CheckerContext &C) const {
    203   // We can obtain perfect type info for return values from some calls.
    204   if (const ObjCMethodCall *Msg = dyn_cast<ObjCMethodCall>(&Call)) {
    205 
    206     // Get the returned value if it's a region.
    207     const MemRegion *RetReg = Call.getReturnValue().getAsRegion();
    208     if (!RetReg)
    209       return;
    210 
    211     ProgramStateRef State = C.getState();
    212     const ObjCMethodDecl *D = Msg->getDecl();
    213 
    214     if (D && D->hasRelatedResultType()) {
    215       switch (Msg->getMethodFamily()) {
    216       default:
    217         break;
    218 
    219       // We assume that the type of the object returned by alloc and new are the
    220       // pointer to the object of the class specified in the receiver of the
    221       // message.
    222       case OMF_alloc:
    223       case OMF_new: {
    224         // Get the type of object that will get created.
    225         const ObjCMessageExpr *MsgE = Msg->getOriginExpr();
    226         const ObjCObjectType *ObjTy = getObjectTypeForAllocAndNew(MsgE, C);
    227         if (!ObjTy)
    228           return;
    229         QualType DynResTy =
    230                  C.getASTContext().getObjCObjectPointerType(QualType(ObjTy, 0));
    231         C.addTransition(setDynamicTypeInfo(State, RetReg, DynResTy, false));
    232         break;
    233       }
    234       case OMF_init: {
    235         // Assume, the result of the init method has the same dynamic type as
    236         // the receiver and propagate the dynamic type info.
    237         const MemRegion *RecReg = Msg->getReceiverSVal().getAsRegion();
    238         if (!RecReg)
    239           return;
    240         DynamicTypeInfo RecDynType = getDynamicTypeInfo(State, RecReg);
    241         C.addTransition(setDynamicTypeInfo(State, RetReg, RecDynType));
    242         break;
    243       }
    244       }
    245     }
    246     return;
    247   }
    248 
    249   if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
    250     // We may need to undo the effects of our pre-call check.
    251     switch (Ctor->getOriginExpr()->getConstructionKind()) {
    252     case CXXConstructExpr::CK_Complete:
    253     case CXXConstructExpr::CK_Delegating:
    254       // No additional work necessary.
    255       // Note: This will leave behind the actual type of the object for
    256       // complete constructors, but arguably that's a good thing, since it
    257       // means the dynamic type info will be correct even for objects
    258       // constructed with operator new.
    259       return;
    260     case CXXConstructExpr::CK_NonVirtualBase:
    261     case CXXConstructExpr::CK_VirtualBase:
    262       if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
    263         // We just finished a base constructor. Now we can use the subclass's
    264         // type when resolving virtual calls.
    265         const Decl *D = C.getLocationContext()->getDecl();
    266         recordFixedType(Target, cast<CXXConstructorDecl>(D), C);
    267       }
    268       return;
    269     }
    270   }
    271 }
    272 
    273 /// TODO: Handle explicit casts.
    274 ///       Handle C++ casts.
    275 ///
    276 /// Precondition: the cast is between ObjCObjectPointers.
    277 ExplodedNode *DynamicTypePropagation::dynamicTypePropagationOnCasts(
    278     const CastExpr *CE, ProgramStateRef &State, CheckerContext &C) const {
    279   // We only track type info for regions.
    280   const MemRegion *ToR = C.getSVal(CE).getAsRegion();
    281   if (!ToR)
    282     return C.getPredecessor();
    283 
    284   if (isa<ExplicitCastExpr>(CE))
    285     return C.getPredecessor();
    286 
    287   if (const Type *NewTy = getBetterObjCType(CE, C)) {
    288     State = setDynamicTypeInfo(State, ToR, QualType(NewTy, 0));
    289     return C.addTransition(State);
    290   }
    291   return C.getPredecessor();
    292 }
    293 
    294 void DynamicTypePropagation::checkPostStmt(const CXXNewExpr *NewE,
    295                                            CheckerContext &C) const {
    296   if (NewE->isArray())
    297     return;
    298 
    299   // We only track dynamic type info for regions.
    300   const MemRegion *MR = C.getSVal(NewE).getAsRegion();
    301   if (!MR)
    302     return;
    303 
    304   C.addTransition(setDynamicTypeInfo(C.getState(), MR, NewE->getType(),
    305                                      /*CanBeSubclass=*/false));
    306 }
    307 
    308 const ObjCObjectType *
    309 DynamicTypePropagation::getObjectTypeForAllocAndNew(const ObjCMessageExpr *MsgE,
    310                                                     CheckerContext &C) const {
    311   if (MsgE->getReceiverKind() == ObjCMessageExpr::Class) {
    312     if (const ObjCObjectType *ObjTy
    313           = MsgE->getClassReceiver()->getAs<ObjCObjectType>())
    314     return ObjTy;
    315   }
    316 
    317   if (MsgE->getReceiverKind() == ObjCMessageExpr::SuperClass) {
    318     if (const ObjCObjectType *ObjTy
    319           = MsgE->getSuperType()->getAs<ObjCObjectType>())
    320       return ObjTy;
    321   }
    322 
    323   const Expr *RecE = MsgE->getInstanceReceiver();
    324   if (!RecE)
    325     return nullptr;
    326 
    327   RecE= RecE->IgnoreParenImpCasts();
    328   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RecE)) {
    329     const StackFrameContext *SFCtx = C.getStackFrame();
    330     // Are we calling [self alloc]? If this is self, get the type of the
    331     // enclosing ObjC class.
    332     if (DRE->getDecl() == SFCtx->getSelfDecl()) {
    333       if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(SFCtx->getDecl()))
    334         if (const ObjCObjectType *ObjTy =
    335             dyn_cast<ObjCObjectType>(MD->getClassInterface()->getTypeForDecl()))
    336           return ObjTy;
    337     }
    338   }
    339   return nullptr;
    340 }
    341 
    342 // Return a better dynamic type if one can be derived from the cast.
    343 // Compare the current dynamic type of the region and the new type to which we
    344 // are casting. If the new type is lower in the inheritance hierarchy, pick it.
    345 const ObjCObjectPointerType *
    346 DynamicTypePropagation::getBetterObjCType(const Expr *CastE,
    347                                           CheckerContext &C) const {
    348   const MemRegion *ToR = C.getSVal(CastE).getAsRegion();
    349   assert(ToR);
    350 
    351   // Get the old and new types.
    352   const ObjCObjectPointerType *NewTy =
    353       CastE->getType()->getAs<ObjCObjectPointerType>();
    354   if (!NewTy)
    355     return nullptr;
    356   QualType OldDTy = getDynamicTypeInfo(C.getState(), ToR).getType();
    357   if (OldDTy.isNull()) {
    358     return NewTy;
    359   }
    360   const ObjCObjectPointerType *OldTy =
    361     OldDTy->getAs<ObjCObjectPointerType>();
    362   if (!OldTy)
    363     return nullptr;
    364 
    365   // Id the old type is 'id', the new one is more precise.
    366   if (OldTy->isObjCIdType() && !NewTy->isObjCIdType())
    367     return NewTy;
    368 
    369   // Return new if it's a subclass of old.
    370   const ObjCInterfaceDecl *ToI = NewTy->getInterfaceDecl();
    371   const ObjCInterfaceDecl *FromI = OldTy->getInterfaceDecl();
    372   if (ToI && FromI && FromI->isSuperClassOf(ToI))
    373     return NewTy;
    374 
    375   return nullptr;
    376 }
    377 
    378 static const ObjCObjectPointerType *getMostInformativeDerivedClassImpl(
    379     const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
    380     const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C) {
    381   // Checking if from and to are the same classes modulo specialization.
    382   if (From->getInterfaceDecl()->getCanonicalDecl() ==
    383       To->getInterfaceDecl()->getCanonicalDecl()) {
    384     if (To->isSpecialized()) {
    385       assert(MostInformativeCandidate->isSpecialized());
    386       return MostInformativeCandidate;
    387     }
    388     return From;
    389   }
    390   const auto *SuperOfTo =
    391       To->getObjectType()->getSuperClassType()->getAs<ObjCObjectType>();
    392   assert(SuperOfTo);
    393   QualType SuperPtrOfToQual =
    394       C.getObjCObjectPointerType(QualType(SuperOfTo, 0));
    395   const auto *SuperPtrOfTo = SuperPtrOfToQual->getAs<ObjCObjectPointerType>();
    396   if (To->isUnspecialized())
    397     return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo, SuperPtrOfTo,
    398                                               C);
    399   else
    400     return getMostInformativeDerivedClassImpl(From, SuperPtrOfTo,
    401                                               MostInformativeCandidate, C);
    402 }
    403 
    404 /// A downcast may loose specialization information. E. g.:
    405 ///   MutableMap<T, U> : Map
    406 /// The downcast to MutableMap looses the information about the types of the
    407 /// Map (due to the type parameters are not being forwarded to Map), and in
    408 /// general there is no way to recover that information from the
    409 /// declaration. In order to have to most information, lets find the most
    410 /// derived type that has all the type parameters forwarded.
    411 ///
    412 /// Get the a subclass of \p From (which has a lower bound \p To) that do not
    413 /// loose information about type parameters. \p To has to be a subclass of
    414 /// \p From. From has to be specialized.
    415 static const ObjCObjectPointerType *
    416 getMostInformativeDerivedClass(const ObjCObjectPointerType *From,
    417                                const ObjCObjectPointerType *To, ASTContext &C) {
    418   return getMostInformativeDerivedClassImpl(From, To, To, C);
    419 }
    420 
    421 /// Inputs:
    422 ///   \param StaticLowerBound Static lower bound for a symbol. The dynamic lower
    423 ///   bound might be the subclass of this type.
    424 ///   \param StaticUpperBound A static upper bound for a symbol.
    425 ///   \p StaticLowerBound expected to be the subclass of \p StaticUpperBound.
    426 ///   \param Current The type that was inferred for a symbol in a previous
    427 ///   context. Might be null when this is the first time that inference happens.
    428 /// Precondition:
    429 ///   \p StaticLowerBound or \p StaticUpperBound is specialized. If \p Current
    430 ///   is not null, it is specialized.
    431 /// Possible cases:
    432 ///   (1) The \p Current is null and \p StaticLowerBound <: \p StaticUpperBound
    433 ///   (2) \p StaticLowerBound <: \p Current <: \p StaticUpperBound
    434 ///   (3) \p Current <: \p StaticLowerBound <: \p StaticUpperBound
    435 ///   (4) \p StaticLowerBound <: \p StaticUpperBound <: \p Current
    436 /// Effect:
    437 ///   Use getMostInformativeDerivedClass with the upper and lower bound of the
    438 ///   set {\p StaticLowerBound, \p Current, \p StaticUpperBound}. The computed
    439 ///   lower bound must be specialized. If the result differs from \p Current or
    440 ///   \p Current is null, store the result.
    441 static bool
    442 storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym,
    443                          const ObjCObjectPointerType *const *Current,
    444                          const ObjCObjectPointerType *StaticLowerBound,
    445                          const ObjCObjectPointerType *StaticUpperBound,
    446                          ASTContext &C) {
    447   // Precondition
    448   assert(StaticUpperBound->isSpecialized() ||
    449          StaticLowerBound->isSpecialized());
    450   assert(!Current || (*Current)->isSpecialized());
    451 
    452   // Case (1)
    453   if (!Current) {
    454     if (StaticUpperBound->isUnspecialized()) {
    455       State = State->set<MostSpecializedTypeArgsMap>(Sym, StaticLowerBound);
    456       return true;
    457     }
    458     // Upper bound is specialized.
    459     const ObjCObjectPointerType *WithMostInfo =
    460         getMostInformativeDerivedClass(StaticUpperBound, StaticLowerBound, C);
    461     State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
    462     return true;
    463   }
    464 
    465   // Case (3)
    466   if (C.canAssignObjCInterfaces(StaticLowerBound, *Current)) {
    467     return false;
    468   }
    469 
    470   // Case (4)
    471   if (C.canAssignObjCInterfaces(*Current, StaticUpperBound)) {
    472     // The type arguments might not be forwarded at any point of inheritance.
    473     const ObjCObjectPointerType *WithMostInfo =
    474         getMostInformativeDerivedClass(*Current, StaticUpperBound, C);
    475     WithMostInfo =
    476         getMostInformativeDerivedClass(WithMostInfo, StaticLowerBound, C);
    477     if (WithMostInfo == *Current)
    478       return false;
    479     State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
    480     return true;
    481   }
    482 
    483   // Case (2)
    484   const ObjCObjectPointerType *WithMostInfo =
    485       getMostInformativeDerivedClass(*Current, StaticLowerBound, C);
    486   if (WithMostInfo != *Current) {
    487     State = State->set<MostSpecializedTypeArgsMap>(Sym, WithMostInfo);
    488     return true;
    489   }
    490 
    491   return false;
    492 }
    493 
    494 /// Type inference based on static type information that is available for the
    495 /// cast and the tracked type information for the given symbol. When the tracked
    496 /// symbol and the destination type of the cast are unrelated, report an error.
    497 void DynamicTypePropagation::checkPostStmt(const CastExpr *CE,
    498                                            CheckerContext &C) const {
    499   if (CE->getCastKind() != CK_BitCast)
    500     return;
    501 
    502   QualType OriginType = CE->getSubExpr()->getType();
    503   QualType DestType = CE->getType();
    504 
    505   const auto *OrigObjectPtrType = OriginType->getAs<ObjCObjectPointerType>();
    506   const auto *DestObjectPtrType = DestType->getAs<ObjCObjectPointerType>();
    507 
    508   if (!OrigObjectPtrType || !DestObjectPtrType)
    509     return;
    510 
    511   ProgramStateRef State = C.getState();
    512   ExplodedNode *AfterTypeProp = dynamicTypePropagationOnCasts(CE, State, C);
    513 
    514   ASTContext &ASTCtxt = C.getASTContext();
    515 
    516   // This checker detects the subtyping relationships using the assignment
    517   // rules. In order to be able to do this the kindofness must be stripped
    518   // first. The checker treats every type as kindof type anyways: when the
    519   // tracked type is the subtype of the static type it tries to look up the
    520   // methods in the tracked type first.
    521   OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
    522   DestObjectPtrType = DestObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
    523 
    524   // TODO: erase tracked information when there is a cast to unrelated type
    525   //       and everything is unspecialized statically.
    526   if (OrigObjectPtrType->isUnspecialized() &&
    527       DestObjectPtrType->isUnspecialized())
    528     return;
    529 
    530   SymbolRef Sym = State->getSVal(CE, C.getLocationContext()).getAsSymbol();
    531   if (!Sym)
    532     return;
    533 
    534   // Check which assignments are legal.
    535   bool OrigToDest =
    536       ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, OrigObjectPtrType);
    537   bool DestToOrig =
    538       ASTCtxt.canAssignObjCInterfaces(OrigObjectPtrType, DestObjectPtrType);
    539   const ObjCObjectPointerType *const *TrackedType =
    540       State->get<MostSpecializedTypeArgsMap>(Sym);
    541 
    542   // Downcasts and upcasts handled in an uniform way regardless of being
    543   // explicit. Explicit casts however can happen between mismatched types.
    544   if (isa<ExplicitCastExpr>(CE) && !OrigToDest && !DestToOrig) {
    545     // Mismatched types. If the DestType specialized, store it. Forget the
    546     // tracked type otherwise.
    547     if (DestObjectPtrType->isSpecialized()) {
    548       State = State->set<MostSpecializedTypeArgsMap>(Sym, DestObjectPtrType);
    549       C.addTransition(State, AfterTypeProp);
    550     } else if (TrackedType) {
    551       State = State->remove<MostSpecializedTypeArgsMap>(Sym);
    552       C.addTransition(State, AfterTypeProp);
    553     }
    554     return;
    555   }
    556 
    557   // The tracked type should be the sub or super class of the static destination
    558   // type. When an (implicit) upcast or a downcast happens according to static
    559   // types, and there is no subtyping relationship between the tracked and the
    560   // static destination types, it indicates an error.
    561   if (TrackedType &&
    562       !ASTCtxt.canAssignObjCInterfaces(DestObjectPtrType, *TrackedType) &&
    563       !ASTCtxt.canAssignObjCInterfaces(*TrackedType, DestObjectPtrType)) {
    564     static CheckerProgramPointTag IllegalConv(this, "IllegalConversion");
    565     ExplodedNode *N = C.addTransition(State, AfterTypeProp, &IllegalConv);
    566     reportGenericsBug(*TrackedType, DestObjectPtrType, N, Sym, C);
    567     return;
    568   }
    569 
    570   // Handle downcasts and upcasts.
    571 
    572   const ObjCObjectPointerType *LowerBound = DestObjectPtrType;
    573   const ObjCObjectPointerType *UpperBound = OrigObjectPtrType;
    574   if (OrigToDest && !DestToOrig)
    575     std::swap(LowerBound, UpperBound);
    576 
    577   // The id type is not a real bound. Eliminate it.
    578   LowerBound = LowerBound->isObjCIdType() ? UpperBound : LowerBound;
    579   UpperBound = UpperBound->isObjCIdType() ? LowerBound : UpperBound;
    580 
    581   if (storeWhenMoreInformative(State, Sym, TrackedType, LowerBound, UpperBound,
    582                                ASTCtxt)) {
    583     C.addTransition(State, AfterTypeProp);
    584   }
    585 }
    586 
    587 static const Expr *stripCastsAndSugar(const Expr *E) {
    588   E = E->IgnoreParenImpCasts();
    589   if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
    590     E = POE->getSyntacticForm()->IgnoreParenImpCasts();
    591   if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
    592     E = OVE->getSourceExpr()->IgnoreParenImpCasts();
    593   return E;
    594 }
    595 
    596 static bool isObjCTypeParamDependent(QualType Type) {
    597   // It is illegal to typedef parameterized types inside an interface. Therfore
    598   // an Objective-C type can only be dependent on a type parameter when the type
    599   // parameter structurally present in the type itself.
    600   class IsObjCTypeParamDependentTypeVisitor
    601       : public RecursiveASTVisitor<IsObjCTypeParamDependentTypeVisitor> {
    602   public:
    603     IsObjCTypeParamDependentTypeVisitor() : Result(false) {}
    604     bool VisitTypedefType(const TypedefType *Type) {
    605       if (isa<ObjCTypeParamDecl>(Type->getDecl())) {
    606         Result = true;
    607         return false;
    608       }
    609       return true;
    610     }
    611 
    612     bool Result;
    613   };
    614 
    615   IsObjCTypeParamDependentTypeVisitor Visitor;
    616   Visitor.TraverseType(Type);
    617   return Visitor.Result;
    618 }
    619 
    620 /// A method might not be available in the interface indicated by the static
    621 /// type. However it might be available in the tracked type. In order to
    622 /// properly substitute the type parameters we need the declaration context of
    623 /// the method. The more specialized the enclosing class of the method is, the
    624 /// more likely that the parameter substitution will be successful.
    625 static const ObjCMethodDecl *
    626 findMethodDecl(const ObjCMessageExpr *MessageExpr,
    627                const ObjCObjectPointerType *TrackedType, ASTContext &ASTCtxt) {
    628   const ObjCMethodDecl *Method = nullptr;
    629 
    630   QualType ReceiverType = MessageExpr->getReceiverType();
    631   const auto *ReceiverObjectPtrType =
    632       ReceiverType->getAs<ObjCObjectPointerType>();
    633 
    634   // Do this "devirtualization" on instance and class methods only. Trust the
    635   // static type on super and super class calls.
    636   if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Instance ||
    637       MessageExpr->getReceiverKind() == ObjCMessageExpr::Class) {
    638     // When the receiver type is id, Class, or some super class of the tracked
    639     // type, look up the method in the tracked type, not in the receiver type.
    640     // This way we preserve more information.
    641     if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType() ||
    642         ASTCtxt.canAssignObjCInterfaces(ReceiverObjectPtrType, TrackedType)) {
    643       const ObjCInterfaceDecl *InterfaceDecl = TrackedType->getInterfaceDecl();
    644       // The method might not be found.
    645       Selector Sel = MessageExpr->getSelector();
    646       Method = InterfaceDecl->lookupInstanceMethod(Sel);
    647       if (!Method)
    648         Method = InterfaceDecl->lookupClassMethod(Sel);
    649     }
    650   }
    651 
    652   // Fallback to statick method lookup when the one based on the tracked type
    653   // failed.
    654   return Method ? Method : MessageExpr->getMethodDecl();
    655 }
    656 
    657 /// Get the returned ObjCObjectPointerType by a method based on the tracked type
    658 /// information, or null pointer when the returned type is not an
    659 /// ObjCObjectPointerType.
    660 static QualType getReturnTypeForMethod(
    661     const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs,
    662     const ObjCObjectPointerType *SelfType, ASTContext &C) {
    663   QualType StaticResultType = Method->getReturnType();
    664 
    665   // Is the return type declared as instance type?
    666   if (StaticResultType == C.getObjCInstanceType())
    667     return QualType(SelfType, 0);
    668 
    669   // Check whether the result type depends on a type parameter.
    670   if (!isObjCTypeParamDependent(StaticResultType))
    671     return QualType();
    672 
    673   QualType ResultType = StaticResultType.substObjCTypeArgs(
    674       C, TypeArgs, ObjCSubstitutionContext::Result);
    675 
    676   return ResultType;
    677 }
    678 
    679 /// When the receiver has a tracked type, use that type to validate the
    680 /// argumments of the message expression and the return value.
    681 void DynamicTypePropagation::checkPreObjCMessage(const ObjCMethodCall &M,
    682                                                  CheckerContext &C) const {
    683   ProgramStateRef State = C.getState();
    684   SymbolRef Sym = M.getReceiverSVal().getAsSymbol();
    685   if (!Sym)
    686     return;
    687 
    688   const ObjCObjectPointerType *const *TrackedType =
    689       State->get<MostSpecializedTypeArgsMap>(Sym);
    690   if (!TrackedType)
    691     return;
    692 
    693   // Get the type arguments from tracked type and substitute type arguments
    694   // before do the semantic check.
    695 
    696   ASTContext &ASTCtxt = C.getASTContext();
    697   const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
    698   const ObjCMethodDecl *Method =
    699       findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
    700 
    701   // It is possible to call non-existent methods in Obj-C.
    702   if (!Method)
    703     return;
    704 
    705   Optional<ArrayRef<QualType>> TypeArgs =
    706       (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
    707   // This case might happen when there is an unspecialized override of a
    708   // specialized method.
    709   if (!TypeArgs)
    710     return;
    711 
    712   for (unsigned i = 0; i < Method->param_size(); i++) {
    713     const Expr *Arg = MessageExpr->getArg(i);
    714     const ParmVarDecl *Param = Method->parameters()[i];
    715 
    716     QualType OrigParamType = Param->getType();
    717     if (!isObjCTypeParamDependent(OrigParamType))
    718       continue;
    719 
    720     QualType ParamType = OrigParamType.substObjCTypeArgs(
    721         ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Parameter);
    722     // Check if it can be assigned
    723     const auto *ParamObjectPtrType = ParamType->getAs<ObjCObjectPointerType>();
    724     const auto *ArgObjectPtrType =
    725         stripCastsAndSugar(Arg)->getType()->getAs<ObjCObjectPointerType>();
    726     if (!ParamObjectPtrType || !ArgObjectPtrType)
    727       continue;
    728 
    729     // Check if we have more concrete tracked type that is not a super type of
    730     // the static argument type.
    731     SVal ArgSVal = M.getArgSVal(i);
    732     SymbolRef ArgSym = ArgSVal.getAsSymbol();
    733     if (ArgSym) {
    734       const ObjCObjectPointerType *const *TrackedArgType =
    735           State->get<MostSpecializedTypeArgsMap>(ArgSym);
    736       if (TrackedArgType &&
    737           ASTCtxt.canAssignObjCInterfaces(ArgObjectPtrType, *TrackedArgType)) {
    738         ArgObjectPtrType = *TrackedArgType;
    739       }
    740     }
    741 
    742     // Warn when argument is incompatible with the parameter.
    743     if (!ASTCtxt.canAssignObjCInterfaces(ParamObjectPtrType,
    744                                          ArgObjectPtrType)) {
    745       static CheckerProgramPointTag Tag(this, "ArgTypeMismatch");
    746       ExplodedNode *N = C.addTransition(State, &Tag);
    747       reportGenericsBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C, Arg);
    748       return;
    749     }
    750   }
    751 }
    752 
    753 /// This callback is used to infer the types for Class variables. This info is
    754 /// used later to validate messages that sent to classes. Class variables are
    755 /// initialized with by invoking the 'class' method on a class.
    756 /// This method is also used to infer the type information for the return
    757 /// types.
    758 // TODO: right now it only tracks generic types. Extend this to track every
    759 // type in the DynamicTypeMap and diagnose type errors!
    760 void DynamicTypePropagation::checkPostObjCMessage(const ObjCMethodCall &M,
    761                                                   CheckerContext &C) const {
    762   const ObjCMessageExpr *MessageExpr = M.getOriginExpr();
    763 
    764   SymbolRef RetSym = M.getReturnValue().getAsSymbol();
    765   if (!RetSym)
    766     return;
    767 
    768   Selector Sel = MessageExpr->getSelector();
    769   ProgramStateRef State = C.getState();
    770   // Inference for class variables.
    771   // We are only interested in cases where the class method is invoked on a
    772   // class. This method is provided by the runtime and available on all classes.
    773   if (MessageExpr->getReceiverKind() == ObjCMessageExpr::Class &&
    774       Sel.getAsString() == "class") {
    775 
    776     QualType ReceiverType = MessageExpr->getClassReceiver();
    777     const auto *ReceiverClassType = ReceiverType->getAs<ObjCObjectType>();
    778     QualType ReceiverClassPointerType =
    779         C.getASTContext().getObjCObjectPointerType(
    780             QualType(ReceiverClassType, 0));
    781 
    782     if (!ReceiverClassType->isSpecialized())
    783       return;
    784     const auto *InferredType =
    785         ReceiverClassPointerType->getAs<ObjCObjectPointerType>();
    786     assert(InferredType);
    787 
    788     State = State->set<MostSpecializedTypeArgsMap>(RetSym, InferredType);
    789     C.addTransition(State);
    790     return;
    791   }
    792 
    793   // Tracking for return types.
    794   SymbolRef RecSym = M.getReceiverSVal().getAsSymbol();
    795   if (!RecSym)
    796     return;
    797 
    798   const ObjCObjectPointerType *const *TrackedType =
    799       State->get<MostSpecializedTypeArgsMap>(RecSym);
    800   if (!TrackedType)
    801     return;
    802 
    803   ASTContext &ASTCtxt = C.getASTContext();
    804   const ObjCMethodDecl *Method =
    805       findMethodDecl(MessageExpr, *TrackedType, ASTCtxt);
    806   if (!Method)
    807     return;
    808 
    809   Optional<ArrayRef<QualType>> TypeArgs =
    810       (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
    811   if (!TypeArgs)
    812     return;
    813 
    814   QualType ResultType =
    815       getReturnTypeForMethod(Method, *TypeArgs, *TrackedType, ASTCtxt);
    816   // The static type is the same as the deduced type.
    817   if (ResultType.isNull())
    818     return;
    819 
    820   const MemRegion *RetRegion = M.getReturnValue().getAsRegion();
    821   ExplodedNode *Pred = C.getPredecessor();
    822   // When there is an entry available for the return symbol in DynamicTypeMap,
    823   // the call was inlined, and the information in the DynamicTypeMap is should
    824   // be precise.
    825   if (RetRegion && !State->get<DynamicTypeMap>(RetRegion)) {
    826     // TODO: we have duplicated information in DynamicTypeMap and
    827     // MostSpecializedTypeArgsMap. We should only store anything in the later if
    828     // the stored data differs from the one stored in the former.
    829     State = setDynamicTypeInfo(State, RetRegion, ResultType,
    830                                /*CanBeSubclass=*/true);
    831     Pred = C.addTransition(State);
    832   }
    833 
    834   const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>();
    835 
    836   if (!ResultPtrType || ResultPtrType->isUnspecialized())
    837     return;
    838 
    839   // When the result is a specialized type and it is not tracked yet, track it
    840   // for the result symbol.
    841   if (!State->get<MostSpecializedTypeArgsMap>(RetSym)) {
    842     State = State->set<MostSpecializedTypeArgsMap>(RetSym, ResultPtrType);
    843     C.addTransition(State, Pred);
    844   }
    845 }
    846 
    847 void DynamicTypePropagation::reportGenericsBug(
    848     const ObjCObjectPointerType *From, const ObjCObjectPointerType *To,
    849     ExplodedNode *N, SymbolRef Sym, CheckerContext &C,
    850     const Stmt *ReportedNode) const {
    851   if (!CheckGenerics)
    852     return;
    853 
    854   initBugType();
    855   SmallString<192> Buf;
    856   llvm::raw_svector_ostream OS(Buf);
    857   OS << "Conversion from value of type '";
    858   QualType::print(From, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
    859   OS << "' to incompatible type '";
    860   QualType::print(To, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
    861   OS << "'";
    862   std::unique_ptr<BugReport> R(
    863       new BugReport(*ObjCGenericsBugType, OS.str(), N));
    864   R->markInteresting(Sym);
    865   R->addVisitor(llvm::make_unique<GenericsBugVisitor>(Sym));
    866   if (ReportedNode)
    867     R->addRange(ReportedNode->getSourceRange());
    868   C.emitReport(std::move(R));
    869 }
    870 
    871 PathDiagnosticPiece *DynamicTypePropagation::GenericsBugVisitor::VisitNode(
    872     const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
    873     BugReport &BR) {
    874   ProgramStateRef state = N->getState();
    875   ProgramStateRef statePrev = PrevN->getState();
    876 
    877   const ObjCObjectPointerType *const *TrackedType =
    878       state->get<MostSpecializedTypeArgsMap>(Sym);
    879   const ObjCObjectPointerType *const *TrackedTypePrev =
    880       statePrev->get<MostSpecializedTypeArgsMap>(Sym);
    881   if (!TrackedType)
    882     return nullptr;
    883 
    884   if (TrackedTypePrev && *TrackedTypePrev == *TrackedType)
    885     return nullptr;
    886 
    887   // Retrieve the associated statement.
    888   const Stmt *S = nullptr;
    889   ProgramPoint ProgLoc = N->getLocation();
    890   if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
    891     S = SP->getStmt();
    892   }
    893 
    894   if (!S)
    895     return nullptr;
    896 
    897   const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
    898 
    899   SmallString<256> Buf;
    900   llvm::raw_svector_ostream OS(Buf);
    901   OS << "Type '";
    902   QualType::print(*TrackedType, Qualifiers(), OS, LangOpts, llvm::Twine());
    903   OS << "' is inferred from ";
    904 
    905   if (const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
    906     OS << "explicit cast (from '";
    907     QualType::print(ExplicitCast->getSubExpr()->getType().getTypePtr(),
    908                     Qualifiers(), OS, LangOpts, llvm::Twine());
    909     OS << "' to '";
    910     QualType::print(ExplicitCast->getType().getTypePtr(), Qualifiers(), OS,
    911                     LangOpts, llvm::Twine());
    912     OS << "')";
    913   } else if (const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
    914     OS << "implicit cast (from '";
    915     QualType::print(ImplicitCast->getSubExpr()->getType().getTypePtr(),
    916                     Qualifiers(), OS, LangOpts, llvm::Twine());
    917     OS << "' to '";
    918     QualType::print(ImplicitCast->getType().getTypePtr(), Qualifiers(), OS,
    919                     LangOpts, llvm::Twine());
    920     OS << "')";
    921   } else {
    922     OS << "this context";
    923   }
    924 
    925   // Generate the extra diagnostic.
    926   PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
    927                              N->getLocationContext());
    928   return new PathDiagnosticEventPiece(Pos, OS.str(), true, nullptr);
    929 }
    930 
    931 /// Register checkers.
    932 void ento::registerObjCGenericsChecker(CheckerManager &mgr) {
    933   DynamicTypePropagation *checker =
    934       mgr.registerChecker<DynamicTypePropagation>();
    935   checker->CheckGenerics = true;
    936 }
    937 
    938 void ento::registerDynamicTypePropagation(CheckerManager &mgr) {
    939   mgr.registerChecker<DynamicTypePropagation>();
    940 }
    941