clang  3.8.0
DynamicTypePropagation.cpp
Go to the documentation of this file.
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"
26 #include "clang/Basic/Builtins.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,
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 {
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()) {
171  // No additional type info necessary.
172  return;
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 =
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()) {
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;
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 
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 
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 
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() ==
384  if (To->isSpecialized()) {
385  assert(MostInformativeCandidate->isSpecialized());
386  return MostInformativeCandidate;
387  }
388  return From;
389  }
390  const auto *SuperOfTo =
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 *
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
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 
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.
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();
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 =
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 =
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,
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.
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 }
CastKind getCastKind() const
Definition: Expr.h:2658
const char *const CoreFoundationObjectiveC
The receiver is an object instance.
Definition: ExprObjC.h:1005
Smart pointer class that efficiently represents Objective-C method names.
A (possibly-)qualified type.
Definition: Type.h:575
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:78
bool hasDeadSymbols() const
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
Definition: ExprObjC.h:1174
A helper class which wraps a boolean value set to false by default.
Definition: Checker.h:542
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:77
QualType substObjCTypeArgs(ASTContext &ctx, ArrayRef< QualType > typeArgs, ObjCSubstitutionContext context) const
Substitute type arguments for the Objective-C type parameters used in the subject type...
Definition: Type.cpp:1065
The base class of the type hierarchy.
Definition: Type.h:1249
QualType getRecordType(const RecordDecl *Decl) const
const ObjCObjectType * getObjectType() const
Gets the type pointed to by this ObjC pointer.
Definition: Type.h:4861
bool isUnspecialized() const
Whether this type is unspecialized, meaning that is has no type arguments.
Definition: Type.h:4921
static void recordFixedType(const MemRegion *Region, const CXXMethodDecl *MD, CheckerContext &C)
bool isSpecialized() const
Whether this type is specialized, meaning that it has type arguments.
Definition: Type.h:4913
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:113
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
unsigned param_size() const
Definition: DeclObjC.h:348
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1299
The collection of all-type qualifiers we support.
Definition: Type.h:116
Symbolic value.
Definition: SymbolManager.h:42
static const ObjCMethodDecl * findMethodDecl(const ObjCMessageExpr *MessageExpr, const ObjCObjectPointerType *TrackedType, ASTContext &ASTCtxt)
A method might not be available in the interface indicated by the static type.
QualType getReceiverType() const
Retrieve the receiver type to which this message is being directed.
Definition: ExprObjC.cpp:313
Represents a class type in Objective C.
Definition: Type.h:4557
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:91
The GDM component containing the dynamic type info.
LineState State
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
Expr * getSubExpr()
Definition: Expr.h:2662
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:48
static bool isObjCTypeParamDependent(QualType Type)
Represents any expression that calls an Objective-C method.
Definition: CallEvent.h:849
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Definition: CallEvent.cpp:685
const LangOptions & getLangOpts() const
Definition: ASTContext.h:596
bool isLiveRegion(const MemRegion *region)
QualType getSuperType() const
Retrieve the type referred to by 'super'.
Definition: ExprObjC.h:1231
const CXXRecordDecl * getParent() const
Returns the parent of this method declaration, which is the class in which this method is defined...
Definition: DeclCXX.h:1801
Selector getSelector() const
Definition: ExprObjC.cpp:306
static QualType getReturnTypeForMethod(const ObjCMethodDecl *Method, ArrayRef< QualType > TypeArgs, const ObjCObjectPointerType *SelfType, ASTContext &C)
Get the returned ObjCObjectPointerType by a method based on the tracked type information, or null pointer when the returned type is not an ObjCObjectPointerType.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:2610
A class that does preorder depth-first traversal on the entire Clang AST and visits each node...
Represents an ObjC class declaration.
Definition: DeclObjC.h:853
detail::InMemoryDirectory::const_iterator I
QualType getType() const
Definition: Decl.h:530
const LocationContext * getLocationContext() const
ID
Defines the set of possible language-specific address spaces.
Definition: AddressSpaces.h:27
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
const ObjCMethodDecl * getMethodDecl() const
Definition: ExprObjC.h:1251
QualType getSuperClassType() const
Retrieve the type of the superclass of this object type.
Definition: Type.h:4699
Expr - This represents one expression.
Definition: Expr.h:104
const ProgramStateRef & getState() const
const ProgramStateRef & getState() const
static bool storeWhenMoreInformative(ProgramStateRef &State, SymbolRef Sym, const ObjCObjectPointerType *const *Current, const ObjCObjectPointerType *StaticLowerBound, const ObjCObjectPointerType *StaticUpperBound, ASTContext &C)
Inputs:
Stores the currently inferred strictest bound on the runtime type of a region in a given state along ...
CK_BitCast - A conversion which causes a bit pattern of one type to be reinterpreted as a bit pattern...
bool isObjCClassType() const
Definition: Type.h:5406
Represents an implicit call to a C++ destructor.
Definition: CallEvent.h:696
ObjCMethodDecl * lookupInstanceMethod(Selector Sel) const
Lookup an instance method for a given selector.
Definition: DeclObjC.h:1510
ObjCMethodDecl * lookupClassMethod(Selector Sel) const
Lookup a class method for a given selector.
Definition: DeclObjC.h:1515
DeclContext * getDeclContext()
Definition: DeclBase.h:393
bool isObjCIdType() const
Definition: Type.h:5401
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine()) const
Definition: Type.h:911
const ObjCObjectPointerType * stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const
Strip off the Objective-C "kindof" type and (with it) any protocol qualifiers.
Definition: Type.cpp:644
ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg, DynamicTypeInfo NewTy)
Set dynamic type information of the region; return the new state.
bool hasRelatedResultType() const
Determine whether this method has a result type that is related to the message receiver's type...
Definition: DeclObjC.h:276
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:860
The result type of a method or function.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: ExprObjC.h:1290
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
ArrayRef< ParmVarDecl * > parameters() const
Definition: DeclObjC.h:376
bool isArray() const
Definition: ExprCXX.h:1813
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
Definition: Expr.h:840
CHECKER * registerChecker()
Used to register checkers.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition: Expr.h:4692
const TemplateArgument * iterator
Definition: Type.h:4070
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)"...
Definition: ExprCXX.h:1723
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:1701
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:44
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
Definition: Type.h:4095
std::string getAsString() const
Derive the full selector name (e.g.
TypedefNameDecl * getDecl() const
Definition: Type.h:3375
const Decl * getDecl() const
A class responsible for cleaning up unused symbols.
QualType getReturnType() const
Definition: DeclObjC.h:330
const StackFrameContext * getStackFrame() const
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
Definition: ASTContext.h:1469
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1155
static const ObjCObjectPointerType * getMostInformativeDerivedClassImpl(const ObjCObjectPointerType *From, const ObjCObjectPointerType *To, const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C)
bool isSuperClassOf(const ObjCInterfaceDecl *I) const
isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...
Definition: DeclObjC.h:1473
QualType getType() const
Definition: Expr.h:125
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg)
Get dynamic type information for a region.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getObjCObjectPointerType(QualType OIT) const
Return a ObjCObjectPointerType type for the given ObjCObjectType.
detail::InMemoryDirectory::const_iterator E
const MemRegion * getAsRegion() const
Definition: SVals.cpp:135
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:113
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
Definition: ProgramPoint.h:150
Expr * IgnoreParenImpCasts() LLVM_READONLY
IgnoreParenImpCasts - Ignore parentheses and implicit casts.
Definition: Expr.cpp:2551
Represents a pointer to an Objective C object.
Definition: Type.h:4821
REGISTER_MAP_WITH_PROGRAMSTATE(MostSpecializedTypeArgsMap, SymbolRef, const ObjCObjectPointerType *) namespace
const LangOptions & getLangOpts() const
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:5675
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
Definition: Type.h:4876
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
Definition: DeclObjC.h:1575
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT)
canAssignObjCInterfaces - Return true if the two interface types are compatible for assignment from R...
const ImplicitParamDecl * getSelfDecl() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:11761
static const ObjCObjectPointerType * getMostInformativeDerivedClass(const ObjCObjectPointerType *From, const ObjCObjectPointerType *To, ASTContext &C)
A downcast may loose specialization information.
FormatToken * Current
The parameter type of a method or function.
static const Expr * stripCastsAndSugar(const Expr *E)
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition: SVals.cpp:111
The receiver is a class.
Definition: ExprObjC.h:1003
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:922
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Definition: Checker.h:484
This class provides an interface through which checkers can create individual bug reports...
Definition: BugReporter.h:55
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:642
virtual const ObjCMessageExpr * getOriginExpr() const
Definition: CallEvent.h:872
The receiver is a superclass.
Definition: ExprObjC.h:1007
SVal getReturnValue() const
Returns the return value of the call.
Definition: CallEvent.cpp:227
bool isObjCIdType() const
True if this is equivalent to the 'id' type, i.e.
Definition: Type.h:4882
Represents a call to a C++ constructor.
Definition: CallEvent.h:744
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Definition: ExprObjC.h:1136
Defines enum values for all the target-independent builtin functions.
SourceManager & getSourceManager()
Definition: BugReporter.h:550
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.